From 587504c36ac3467df9ff9672045640e245a849f8 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Mon, 24 Mar 2025 15:15:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20AI=E5=B7=A5=E4=BD=9C=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/enums/ErrorCodeConstants.java | 4 + .../admin/workflow/AiWorkflowController.java | 85 ++++++++++ .../workflow/vo/AiWorkflowPageReqVO.java | 26 +++ .../admin/workflow/vo/AiWorkflowRespVO.java | 27 +++ .../workflow/vo/AiWorkflowSaveReqVO.java | 22 +++ .../workflow/vo/AiWorkflowTestReqVO.java | 20 +++ .../vo/AiWorkflowUpdateModelReqVO.java | 18 ++ .../dal/dataobject/workflow/AiWorkflowDO.java | 40 +++++ .../dal/mysql/workflow/AiWorkflowMapper.java | 28 ++++ .../service/workflow/AiWorkflowService.java | 69 ++++++++ .../workflow/AiWorkflowServiceImpl.java | 157 ++++++++++++++++++ .../yudao-spring-boot-starter-ai/pom.xml | 8 + 12 files changed, 504 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowUpdateModelReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/workflow/AiWorkflowService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/workflow/AiWorkflowServiceImpl.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java index 8b235f9ac5..fa072f3fcb 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java @@ -61,4 +61,8 @@ public interface ErrorCodeConstants { ErrorCode TOOL_NOT_EXISTS = new ErrorCode(1_040_010_000, "工具不存在"); ErrorCode TOOL_NAME_NOT_EXISTS = new ErrorCode(1_040_010_001, "工具({})找不到 Bean"); + // ========== AI 工作流 1-040-011-000 ========== + ErrorCode WORKFLOW_NOT_EXISTS = new ErrorCode(1_040_011_000, "工作流不存在"); + ErrorCode WORKFLOW_KEY_EXISTS = new ErrorCode(1_040_011_001, "工作流标识已存在"); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java new file mode 100644 index 0000000000..1270f7679c --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.ai.controller.admin.workflow; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.*; +import cn.iocoder.yudao.module.ai.dal.dataobject.workflow.AiWorkflowDO; +import cn.iocoder.yudao.module.ai.service.workflow.AiWorkflowService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - AI 工作流") +@RestController +@RequestMapping("/ai/workflow") +@Slf4j +public class AiWorkflowController { + + @Resource + private AiWorkflowService workflowService; + + @PostMapping("/create") + @Operation(summary = "创建 AI 工作流") + @PreAuthorize("@ss.hasPermission('ai:workflow:create')") + public CommonResult createWorkflow(@Valid @RequestBody AiWorkflowSaveReqVO createReqVO) { + return success(workflowService.createWorkflow(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新 AI 工作流") + @PreAuthorize("@ss.hasPermission('ai:workflow:update')") + public CommonResult updateWorkflow(@Valid @RequestBody AiWorkflowSaveReqVO updateReqVO) { + workflowService.updateWorkflow(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除 AI 工作流") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('ai:workflow:delete')") + public CommonResult deleteWorkflow(@RequestParam("id") Long id) { + workflowService.deleteWorkflow(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得 AI 工作流") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('ai:workflow:query')") + public CommonResult getWorkflow(@RequestParam("id") Long id) { + AiWorkflowDO workflow = workflowService.getWorkflow(id); + return success(BeanUtils.toBean(workflow, AiWorkflowRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得 AI 工作流分页") + @PreAuthorize("@ss.hasPermission('ai:workflow:query')") + public CommonResult> getWorkflowPage(@Valid AiWorkflowPageReqVO pageReqVO) { + PageResult pageResult = workflowService.getWorkflowPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, AiWorkflowRespVO.class)); + } + + @PutMapping("/updateWorkflowModel") + @Operation(summary = "更新 AI 工作流模型") + @PreAuthorize("@ss.hasPermission('ai:workflow:update')") + public CommonResult updateWorkflowModel(@Valid @RequestBody AiWorkflowUpdateModelReqVO updateReqVO) { + workflowService.updateWorkflowModel(updateReqVO); + return success(true); + } + + @PostMapping("/test") + @Operation(summary = "测试 AI 工作流") + @PreAuthorize("@ss.hasPermission('ai:workflow:test')") + public CommonResult testWorkflow(@Valid @RequestBody AiWorkflowTestReqVO testReqVO) { + return success(workflowService.testWorkflow(testReqVO)); + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java new file mode 100644 index 0000000000..5418057817 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - AI 工作流分页 Request VO") +@Data +public class AiWorkflowPageReqVO extends PageParam { + + @Schema(description = "名称", example = "工作流") + private String name; + + @Schema(description = "标识", example = "FLOW") + private String definitionKey; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java new file mode 100644 index 0000000000..b1c66b91de --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - AI 工作流 Response VO") +@Data +public class AiWorkflowRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "工作流标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOW") + private String definitionKey; + + @Schema(description = "工作流名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "工作流") + private String name; + + @Schema(description = "工作流模型 JSON", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + private String model; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") + private LocalDateTime createTime; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java new file mode 100644 index 0000000000..ec269cc034 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +@Schema(description = "管理后台 - AI 工作流新增/修改 Request VO") +@Data +public class AiWorkflowSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "工作流标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOW") + @NotEmpty(message = "工作流标识不能为空") + private String definitionKey; + + @Schema(description = "工作流名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "工作流") + @NotEmpty(message = "工作流名称不能为空") + private String name; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java new file mode 100644 index 0000000000..077a3020a6 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.util.Map; + +@Schema(description = "管理后台 - AI 工作流测试 Request VO") +@Data +public class AiWorkflowTestReqVO { + + @Schema(description = "工作流模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + @NotEmpty(message = "工作流模型不能为空") + private String model; + + @Schema(description = "参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + private Map params; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowUpdateModelReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowUpdateModelReqVO.java new file mode 100644 index 0000000000..00a279ba54 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowUpdateModelReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +@Schema(description = "管理后台 - AI 工作流修改流程模型 Request VO") +@Data +public class AiWorkflowUpdateModelReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "工作流模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + @NotEmpty(message = "工作流模型不能为空") + private String model; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java new file mode 100644 index 0000000000..db6c090467 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.ai.dal.dataobject.workflow; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * AI 工作流 DO + * + * @author lesan + */ +@TableName(value = "ai_workflow", autoResultMap = true) +@KeySequence("ai_workflow") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +public class AiWorkflowDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + + /** + * 工作流标识 + */ + private String definitionKey; + + /** + * 工作流名称 + */ + private String name; + + /** + * 工作流模型 JSON 数据 + */ + private String model; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java new file mode 100644 index 0000000000..f6be0cec7b --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.ai.dal.mysql.workflow; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowPageReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.workflow.AiWorkflowDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * AI 工作流 Mapper + * + * @author lesan + */ +@Mapper +public interface AiWorkflowMapper extends BaseMapperX { + + default AiWorkflowDO selectByKey(String key) { + return selectOne(AiWorkflowDO::getDefinitionKey, key); + } + + default PageResult selectPage(AiWorkflowPageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .likeIfPresent(AiWorkflowDO::getName, pageReqVO.getName()) + .likeIfPresent(AiWorkflowDO::getDefinitionKey, pageReqVO.getDefinitionKey())); + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/workflow/AiWorkflowService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/workflow/AiWorkflowService.java new file mode 100644 index 0000000000..31fd476540 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/workflow/AiWorkflowService.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.ai.service.workflow; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowSaveReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowTestReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowUpdateModelReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.workflow.AiWorkflowDO; +import jakarta.validation.Valid; + +/** + * AI 工作流 Service 接口 + * + * @author lesan + */ +public interface AiWorkflowService { + + /** + * 创建 AI 工作流 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWorkflow(@Valid AiWorkflowSaveReqVO createReqVO); + + /** + * 更新 AI 工作流 + * + * @param updateReqVO 更新信息 + */ + void updateWorkflow(@Valid AiWorkflowSaveReqVO updateReqVO); + + /** + * 删除 AI 工作流 + * + * @param id 编号 + */ + void deleteWorkflow(Long id); + + /** + * 获得 AI 工作流 + * + * @param id 编号 + * @return AI 工作流 + */ + AiWorkflowDO getWorkflow(Long id); + + /** + * 获得 AI 工作流分页 + * + * @param pageReqVO 分页查询 + * @return AI 工作流分页 + */ + PageResult getWorkflowPage(AiWorkflowPageReqVO pageReqVO); + + /** + * 修改工作流模型 JSON 数据 + * + * @param updateReqVO 更新数据 + */ + void updateWorkflowModel(AiWorkflowUpdateModelReqVO updateReqVO); + + /** + * 测试 AI 工作流 + * + * @param testReqVO 测试数据 + */ + Object testWorkflow(AiWorkflowTestReqVO testReqVO); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/workflow/AiWorkflowServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/workflow/AiWorkflowServiceImpl.java new file mode 100644 index 0000000000..53128b7c2a --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/workflow/AiWorkflowServiceImpl.java @@ -0,0 +1,157 @@ +package cn.iocoder.yudao.module.ai.service.workflow; + +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowSaveReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowTestReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowUpdateModelReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.workflow.AiWorkflowDO; +import cn.iocoder.yudao.module.ai.dal.mysql.workflow.AiWorkflowMapper; +import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import dev.tinyflow.core.Tinyflow; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.WORKFLOW_KEY_EXISTS; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.WORKFLOW_NOT_EXISTS; + +/** + * AI 工作流 Service 实现类 + * + * @author lesan + */ +@Service +@Slf4j +public class AiWorkflowServiceImpl implements AiWorkflowService { + + @Resource + private AiWorkflowMapper workflowMapper; + + @Resource + private AiApiKeyService apiKeyService; + + @Override + public Long createWorkflow(AiWorkflowSaveReqVO createReqVO) { + validateWorkflowForCreateOrUpdate(null, createReqVO.getDefinitionKey()); + AiWorkflowDO workflow = BeanUtils.toBean(createReqVO, AiWorkflowDO.class); + workflow.setModel(StrUtil.EMPTY); + workflowMapper.insert(workflow); + return workflow.getId(); + } + + @Override + public void updateWorkflow(AiWorkflowSaveReqVO updateReqVO) { + validateWorkflowForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getDefinitionKey()); + AiWorkflowDO workflow = BeanUtils.toBean(updateReqVO, AiWorkflowDO.class); + workflowMapper.updateById(workflow); + } + + @Override + public void deleteWorkflow(Long id) { + validateWorkflowExists(id); + workflowMapper.deleteById(id); + } + + @Override + public AiWorkflowDO getWorkflow(Long id) { + return workflowMapper.selectById(id); + } + + @Override + public PageResult getWorkflowPage(AiWorkflowPageReqVO pageReqVO) { + return workflowMapper.selectPage(pageReqVO); + } + + @Override + public void updateWorkflowModel(AiWorkflowUpdateModelReqVO updateReqVO) { + validateWorkflowExists(updateReqVO.getId()); + workflowMapper.updateById(new AiWorkflowDO().setId(updateReqVO.getId()).setModel(updateReqVO.getModel())); + } + + @Override + public Object testWorkflow(AiWorkflowTestReqVO testReqVO) { + Map variables = testReqVO.getParams(); + Tinyflow tinyflow = parseFlowParam(testReqVO.getModel()); + return tinyflow.toChain().executeForResult(variables); + } + + private void validateWorkflowForCreateOrUpdate(Long id, String key) { + validateWorkflowExists(id); + validateKeyUnique(id, key); + } + + private void validateWorkflowExists(Long id) { + if (ObjUtil.isNull(id)) { + return; + } + AiWorkflowDO workflow = workflowMapper.selectById(id); + if (ObjUtil.isNull(workflow)) { + throw exception(WORKFLOW_NOT_EXISTS); + } + } + + private void validateKeyUnique(Long id, String key) { + if (StrUtil.isBlank(key)) { + return; + } + AiWorkflowDO workflow = workflowMapper.selectByKey(key); + if (ObjUtil.isNull(workflow)) { + return; + } + if (ObjUtil.isNull(id)) { + throw exception(WORKFLOW_KEY_EXISTS); + } + if (ObjUtil.notEqual(workflow.getId(), id)) { + throw exception(WORKFLOW_KEY_EXISTS); + } + } + + private Tinyflow parseFlowParam(String model) { + JSONObject json = JSONObject.parseObject(model); + JSONArray nodeArr = json.getJSONArray("nodes"); + Tinyflow tinyflow = new Tinyflow(json.toJSONString()); + for (int i = 0; i < nodeArr.size(); i++) { + JSONObject node = nodeArr.getJSONObject(i); + switch (node.getString("type")) { + case "llmNode": + JSONObject data = node.getJSONObject("data"); + AiApiKeyDO apiKey = apiKeyService.getApiKey(data.getLong("llmId")); + switch (apiKey.getPlatform()) { + // TODO @lesan 需要讨论一下这里怎么弄 + case "OpenAI": + break; + case "Ollama": + break; + case "YiYan": + break; + case "XingHuo": + break; + case "TongYi": + break; + case "DeepSeek": + break; + case "ZhiPu": + break; + } + break; + case "internalNode": + break; + default: + break; + } + } + return tinyflow; + } + + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index f37f3709c6..5740cf2041 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -15,6 +15,7 @@ AI 大模型拓展,接入国内外大模型 1.0.0-M6 + 1.0.0-rc.3 @@ -117,6 +118,13 @@ + + + dev.tinyflow + tinyflow-java-core + ${tinyflow.version} + + org.springframework.boot