Skip to content

Commit

Permalink
Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-…
Browse files Browse the repository at this point in the history
…vue-pro

# Conflicts:
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java
#	yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/job/product/ProductStatisticsJob.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/config/TradeOrderProperties.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppService.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientTests.java
  • Loading branch information
YunaiV committed Aug 18, 2024
2 parents c21ee3e + e850fbf commit e219755
Show file tree
Hide file tree
Showing 80 changed files with 1,454 additions and 641 deletions.
2 changes: 1 addition & 1 deletion yudao-module-ai/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

<name>${project.artifactId}</name>
<description>
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维脑图等功能
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能
目前已接入各种模型,不限于:
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public enum AiChatRoleEnum implements IntArrayValuable {
除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。
"""),

AI_MIND_MAP_ROLE(2, "脑图助手", """
AI_MIND_MAP_ROLE(2, "导图助手", """
你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子:
# Geek-AI 助手
## 完整的开源系统
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ public interface ErrorCodeConstants {
// ========== API 音乐 1-040-006-000 ==========
ErrorCode MUSIC_NOT_EXISTS = new ErrorCode(1_022_006_000, "音乐不存在!");


// ========== API 写作 1-022-007-000 ==========
ErrorCode WRITE_NOT_EXISTS = new ErrorCode(1_022_007_000, "作文不存在!");
ErrorCode WRITE_STREAM_ERROR = new ErrorCode(1_022_07_001, "写作生成异常!");

// ========== API 思维导图 1-040-008-000 ==========
ErrorCode MIND_MAP_NOT_EXISTS = new ErrorCode(1_040_008_000, "思维导图不存在!");

}
2 changes: 1 addition & 1 deletion yudao-module-ai/yudao-module-ai-biz/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<name>${project.artifactId}</name>
<description>
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维脑图等功能
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能
目前已接入各种模型,不限于:
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageRespVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageUpdateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
Expand Down Expand Up @@ -45,6 +42,13 @@ public CommonResult<PageResult<AiImageRespVO>> getImagePageMy(@Validated AiImage
return success(BeanUtils.toBean(pageResult, AiImageRespVO.class));
}

@GetMapping("/public-page")
@Operation(summary = "获取公开的绘图分页")
public CommonResult<PageResult<AiImageRespVO>> getImagePagePublic(AiImagePublicPageReqVO pageReqVO) {
PageResult<AiImageDO> pageResult = imageService.getImagePagePublic(pageReqVO);
return success(BeanUtils.toBean(pageResult, AiImageRespVO.class));
}

@GetMapping("/get-my")
@Operation(summary = "获取【我的】绘图记录")
@Parameter(name = "id", required = true, description = "绘画编号", example = "1024")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.ai.controller.admin.image.vo;

import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

@Schema(description = "管理后台 - AI 绘画公开的分页 Request VO")
@Data
public class AiImagePublicPageReqVO extends PageParam {

@Schema(description = "提示词")
private String prompt;

}
Original file line number Diff line number Diff line change
@@ -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 思维导图")
Expand All @@ -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));
}

}
Original file line number Diff line number Diff line change
@@ -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;

}
Original file line number Diff line number Diff line change
@@ -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;

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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.image.vo.AiImagePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePublicPageReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
import org.apache.ibatis.annotations.Mapper;

Expand Down Expand Up @@ -41,6 +42,13 @@ default PageResult<AiImageDO> selectPageMy(Long userId, AiImagePageReqVO reqVO)
.orderByDesc(AiImageDO::getId));
}

default PageResult<AiImageDO> selectPage(AiImagePublicPageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<AiImageDO>()
.eqIfPresent(AiImageDO::getPublicStatus, Boolean.TRUE)
.likeIfPresent(AiImageDO::getPrompt, pageReqVO.getPrompt())
.orderByDesc(AiImageDO::getId));
}

default List<AiImageDO> selectListByStatusAndPlatform(Integer status, String platform) {
return selectList(AiImageDO::getStatus, status,
AiImageDO::getPlatform, platform);
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -11,4 +14,13 @@
*/
@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));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageUpdateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
Expand All @@ -28,6 +26,14 @@ public interface AiImageService {
*/
PageResult<AiImageDO> getImagePageMy(Long userId, AiImagePageReqVO pageReqVO);

/**
* 获取公开的绘图分页
*
* @param pageReqVO 分页条件
* @return 绘图分页
*/
PageResult<AiImageDO> getImagePagePublic(AiImagePublicPageReqVO pageReqVO);

/**
* 获得绘图记录
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageUpdateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
Expand Down Expand Up @@ -70,6 +68,11 @@ public PageResult<AiImageDO> getImagePageMy(Long userId, AiImagePageReqVO pageRe
return imageMapper.selectPageMy(userId, pageReqVO);
}

@Override
public PageResult<AiImageDO> getImagePagePublic(AiImagePublicPageReqVO pageReqVO) {
return imageMapper.selectPage(pageReqVO);
}

@Override
public AiImageDO getImage(Long id) {
return imageMapper.selectById(id);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.ai.service.knowledge;

/**
* AI 知识库 Service 接口
*
* @author xiaoxin
*/
public interface DocService {

/**
* 向量化文档
*/
void embeddingDoc();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.ai.service.knowledge;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.RedisVectorStore;
import org.springframework.beans.factory.annotation.Value;

import java.util.List;

/**
* AI 知识库 Service 实现类
*
* @author xiaoxin
*/
//@Service // TODO 芋艿:临时注释,避免无法启动
@Slf4j
public class DocServiceImpl implements DocService {

@Resource
private RedisVectorStore vectorStore;
@Resource
private TokenTextSplitter tokenTextSplitter;

// TODO @xin 临时测试用,后续删
@Value("classpath:/webapp/test/Fel.pdf")
private org.springframework.core.io.Resource data;

@Override
public void embeddingDoc() {
// 读取文件
TikaDocumentReader loader = new TikaDocumentReader(data);
List<Document> documents = loader.get();
// 文档分段
List<Document> segments = tokenTextSplitter.apply(documents);
// 向量化并存储
vectorStore.add(segments);
}

}
Original file line number Diff line number Diff line change
@@ -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;

/**
Expand All @@ -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);

}
Loading

0 comments on commit e219755

Please sign in to comment.