Merge branch 'refs/heads/up-master-jdk21-ai' into master-jdk21-ai

# Conflicts:
#	yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/DocServiceImpl.java
This commit is contained in:
xiaoxin
2024-08-15 16:00:56 +08:00
18 changed files with 273 additions and 17 deletions

View File

@@ -12,7 +12,7 @@
<name>${project.artifactId}</name>
<description>
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维图等功能。
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维图等功能。
目前已接入各种模型,不限于:
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
国外OpenAI、Ollama、Midjourney、StableDiffusion、Suno

View File

@@ -1,20 +1,25 @@
package cn.iocoder.yudao.module.ai.controller.admin.mindmap;
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.mindmap.vo.AiMindMapGenerateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapRespVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO;
import cn.iocoder.yudao.module.ai.service.mindmap.AiMindMapService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - AI 思维导图")
@@ -26,10 +31,29 @@ public class AiMindMapController {
private AiMindMapService mindMapService;
@PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@Operation(summary = "图生成(流式)", description = "流式返回,响应较快")
@Operation(summary = "图生成(流式)", description = "流式返回,响应较快")
@PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题
public Flux<CommonResult<String>> generateMindMap(@RequestBody @Valid AiMindMapGenerateReqVO generateReqVO) {
return mindMapService.generateMindMap(generateReqVO, getLoginUserId());
}
// ================ 导图管理 ================
@DeleteMapping("/delete")
@Operation(summary = "删除思维导图")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('ai:mind-map:delete')")
public CommonResult<Boolean> deleteMindMap(@RequestParam("id") Long id) {
mindMapService.deleteMindMap(id);
return success(true);
}
@GetMapping("/page")
@Operation(summary = "获得思维导图分页")
@PreAuthorize("@ss.hasPermission('ai:mind-map:query')")
public CommonResult<PageResult<AiMindMapRespVO>> getMindMapPage(@Valid AiMindMapPageReqVO pageReqVO) {
PageResult<AiMindMapDO> pageResult = mindMapService.getMindMapPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, AiMindMapRespVO.class));
}
}

View File

@@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - AI 思维导图分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AiMindMapPageReqVO extends PageParam {
@Schema(description = "用户编号", example = "4325")
private Long userId;
@Schema(description = "生成内容提示", example = "Java 学习路线")
private String prompt;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - AI 思维导图 Response VO")
@Data
public class AiMindMapRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3373")
private Long id;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4325")
private Long userId;
@Schema(description = "生成内容提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 学习路线")
private String prompt;
@Schema(description = "生成的思维导图内容")
private String generatedContent;
@Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI")
private String platform;
@Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo-0125")
private String model;
@Schema(description = "错误信息")
private String errorMessage;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -1,6 +1,9 @@
package cn.iocoder.yudao.module.ai.dal.mysql.mindmap;
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.mindmap.vo.AiMindMapPageReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO;
import org.apache.ibatis.annotations.Mapper;
@@ -11,4 +14,13 @@ import org.apache.ibatis.annotations.Mapper;
*/
@Mapper
public interface AiMindMapMapper extends BaseMapperX<AiMindMapDO> {
default PageResult<AiMindMapDO> selectPage(AiMindMapPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<AiMindMapDO>()
.eqIfPresent(AiMindMapDO::getUserId, reqVO.getUserId())
.eqIfPresent(AiMindMapDO::getPrompt, reqVO.getPrompt())
.betweenIfPresent(AiMindMapDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(AiMindMapDO::getId));
}
}

View File

@@ -1,7 +1,10 @@
package cn.iocoder.yudao.module.ai.service.mindmap;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO;
import reactor.core.publisher.Flux;
/**
@@ -20,4 +23,19 @@ public interface AiMindMapService {
*/
Flux<CommonResult<String>> generateMindMap(AiMindMapGenerateReqVO generateReqVO, Long userId);
/**
* 删除思维导图
*
* @param id 编号
*/
void deleteMindMap(Long id);
/**
* 获得思维导图分页
*
* @param pageReqVO 分页查询
* @return 思维导图分页
*/
PageResult<AiMindMapDO> getMindMapPage(AiMindMapPageReqVO pageReqVO);
}

View File

@@ -6,9 +6,11 @@ import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
import cn.iocoder.yudao.framework.ai.core.util.AiUtils;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
@@ -33,8 +35,10 @@ import reactor.core.publisher.Flux;
import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.MIND_MAP_NOT_EXISTS;
/**
* AI 思维导图 Service 实现类
@@ -57,10 +61,10 @@ public class AiMindMapServiceImpl implements AiMindMapService {
@Override
public Flux<CommonResult<String>> generateMindMap(AiMindMapGenerateReqVO generateReqVO, Long userId) {
// 1. 获取图模型。尝试获取思维导图助手角色,如果没有则使用默认模型
// 1. 获取图模型。尝试获取思维导图助手角色,如果没有则使用默认模型
AiChatRoleDO role = CollUtil.getFirst(
chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_MIND_MAP_ROLE.getName()));
// 1.1 获取图执行模型
// 1.1 获取图执行模型
AiChatModelDO model = getModel(role);
// 1.2 获取角色设定消息
String systemMessage = role != null && StrUtil.isNotBlank(role.getSystemMessage())
@@ -131,4 +135,23 @@ public class AiMindMapServiceImpl implements AiMindMapService {
return model;
}
@Override
public void deleteMindMap(Long id) {
// 校验存在
validateMindMapExists(id);
// 删除
mindMapMapper.deleteById(id);
}
private void validateMindMapExists(Long id) {
if (mindMapMapper.selectById(id) == null) {
throw exception(MIND_MAP_NOT_EXISTS);
}
}
@Override
public PageResult<AiMindMapDO> getMindMapPage(AiMindMapPageReqVO pageReqVO) {
return mindMapMapper.selectPage(pageReqVO);
}
}