diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java index cca856fe17..c52cfe2cf7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.controller.admin.knowledge; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -10,8 +11,10 @@ import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowl import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateStatusReqVO; import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; +import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeDocumentMapper; import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; 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; @@ -22,6 +25,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - AI 知识库文档") @RestController @@ -91,4 +95,13 @@ public class AiKnowledgeDocumentController { return success(true); } + @GetMapping("/simple-list") + @Operation(summary = "获得知识库文档的精简列表") + public CommonResult> getKnowledgeDocumentSimpleList() { + List list = documentService + .getKnowledgeDocumentListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, document -> new AiKnowledgeDocumentRespVO() + .setId(document.getId()).setName(document.getName()))); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java index 02f698b944..5714c5fedd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java @@ -75,7 +75,7 @@ public class AiChatRoleController { @GetMapping("/category-list") @Operation(summary = "获得聊天角色的分类列表") public CommonResult> getChatRoleCategoryList() { - return success(chatRoleService.getChatRoleCategoryList()); + return success(chatRoleService.getChatRoleCategoryList()); } // ========== 角色管理 ========== diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java index d47c66d2bd..cbbed87c04 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; +import java.util.List; @Schema(description = "管理后台 - AI 聊天角色 Response VO") @Data @@ -20,7 +21,7 @@ public class AiChatRoleRespVO implements VO { private Long userId; @Schema(description = "模型编号", example = "17640") - @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = {"name", "model"}, refs = {"modelName", "model"}) + @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = { "name", "model" }, refs = { "modelName", "model" }) private Long modelId; @Schema(description = "模型名字", example = "张三") private String modelName; @@ -45,6 +46,9 @@ public class AiChatRoleRespVO implements VO { @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED) private String systemMessage; + @Schema(description = "知识库文档编号列表", example = "1,2,3") + private List documentIds; + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Boolean publicStatus; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java index 4673901d38..5f802202a8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java @@ -5,6 +5,8 @@ import jakarta.validation.constraints.NotEmpty; import lombok.Data; import org.hibernate.validator.constraints.URL; +import java.util.List; + @Schema(description = "管理后台 - AI 聊天角色新增/修改【我的】 Request VO") @Data public class AiChatRoleSaveMyReqVO { @@ -29,4 +31,7 @@ public class AiChatRoleSaveMyReqVO { @NotEmpty(message = "角色设定不能为空") private String systemMessage; + @Schema(description = "知识库文档编号列表", example = "1,2,3") + private List documentIds; + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java index bdda027ef2..e7ba7fd2d1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java @@ -7,6 +7,8 @@ import lombok.*; import jakarta.validation.constraints.*; import org.hibernate.validator.constraints.URL; +import java.util.List; + @Schema(description = "管理后台 - AI 聊天角色新增/修改 Request VO") @Data public class AiChatRoleSaveReqVO { @@ -42,6 +44,9 @@ public class AiChatRoleSaveReqVO { @NotEmpty(message = "角色设定不能为空") private String systemMessage; + @Schema(description = "知识库文档编号列表", example = "1,2,3") + private List documentIds; + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "是否公开不能为空") private Boolean publicStatus; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java index fd35b85795..006057e353 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java @@ -2,11 +2,16 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.model; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.util.List; + /** * AI 聊天角色 DO * @@ -62,6 +67,14 @@ public class AiChatRoleDO extends BaseDO { */ private Long modelId; + /** + * 知识库文档编号列表 + * + * 关联 {@link AiKnowledgeDocumentDO#getId()} 字段 + */ + @TableField(typeHandler = LongListTypeHandler.class) + private List documentIds; + /** * 是否公开 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java index eeacca6345..11a76cc57b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; +import java.util.List; /** * AI 知识库文档 Mapper @@ -26,9 +27,13 @@ public interface AiKnowledgeDocumentMapper extends BaseMapperX ids) { - update( new LambdaUpdateWrapper() + update(new LambdaUpdateWrapper() .setSql(" retrieval_count = retrieval_count + 1") .in(AiKnowledgeDocumentDO::getId, ids)); } + default List selectListByStatus(Integer status) { + return selectList(AiKnowledgeDocumentDO::getStatus, status); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentService.java index 8ff137b331..e1a45efc1a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentService.java @@ -115,4 +115,12 @@ public interface AiKnowledgeDocumentService { return convertMap(getKnowledgeDocumentList(ids), AiKnowledgeDocumentDO::getId); } + /** + * 获取指定状态的文档列表 + * + * @param status 状态 + * @return 文档列表 + */ + List getKnowledgeDocumentListByStatus(Integer status); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java index 48dd78dbb9..3e47720711 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java @@ -7,6 +7,7 @@ import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentCreateListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO; @@ -210,4 +211,9 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic return knowledgeDocumentMapper.selectByIds(ids); } + @Override + public List getKnowledgeDocumentListByStatus(Integer status) { + return knowledgeDocumentMapper.selectListByStatus(status); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java index 81c8d259b6..e7fecf6ac7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java @@ -32,7 +32,7 @@ public interface AiChatRoleService { * 创建【我的】聊天角色 * * @param createReqVO 创建信息 - * @param userId 用户编号 + * @param userId 用户编号 * @return 编号 */ Long createChatRoleMy(AiChatRoleSaveMyReqVO createReqVO, Long userId); @@ -48,7 +48,7 @@ public interface AiChatRoleService { * 创建【我的】聊天角色 * * @param updateReqVO 更新信息 - * @param userId 用户编号 + * @param userId 用户编号 */ void updateChatRoleMy(AiChatRoleSaveMyReqVO updateReqVO, Long userId); @@ -62,7 +62,7 @@ public interface AiChatRoleService { /** * 删除【我的】聊天角色 * - * @param id 编号 + * @param id 编号 * @param userId 用户编号 */ void deleteChatRoleMy(Long id, Long userId); @@ -106,7 +106,7 @@ public interface AiChatRoleService { * 获得【我的】聊天角色分页 * * @param pageReqVO 分页查询 - * @param userId 用户编号 + * @param userId 用户编号 * @return 聊天角色分页 */ PageResult getChatRoleMyPage(AiChatRolePageReqVO pageReqVO, Long userId); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index 2cf4d46d1c..ce93d4e1de 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -5,12 +5,14 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.model.AiChatRoleMapper; +import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -35,8 +37,15 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Resource private AiChatRoleMapper chatRoleMapper; + @Resource + private AiKnowledgeDocumentService knowledgeDocumentService; + @Override public Long createChatRole(AiChatRoleSaveReqVO createReqVO) { + // 校验文档 + validateDocuments(createReqVO.getDocumentIds()); + + // 保存角色 AiChatRoleDO chatRole = BeanUtils.toBean(createReqVO, AiChatRoleDO.class); chatRoleMapper.insert(chatRole); return chatRole.getId(); @@ -44,6 +53,10 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Override public Long createChatRoleMy(AiChatRoleSaveMyReqVO createReqVO, Long userId) { + // 校验文档 + validateDocuments(createReqVO.getDocumentIds()); + + // 保存角色 AiChatRoleDO chatRole = BeanUtils.toBean(createReqVO, AiChatRoleDO.class).setUserId(userId) .setStatus(CommonStatusEnum.ENABLE.getStatus()).setPublicStatus(false); chatRoleMapper.insert(chatRole); @@ -54,7 +67,10 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { public void updateChatRole(AiChatRoleSaveReqVO updateReqVO) { // 校验存在 validateChatRoleExists(updateReqVO.getId()); - // 更新 + // 校验文档 + validateDocuments(updateReqVO.getDocumentIds()); + + // 更新角色 AiChatRoleDO updateObj = BeanUtils.toBean(updateReqVO, AiChatRoleDO.class); chatRoleMapper.updateById(updateObj); } @@ -66,12 +82,27 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { if (ObjectUtil.notEqual(chatRole.getUserId(), userId)) { throw exception(CHAT_ROLE_NOT_EXISTS); } + // 校验文档 + validateDocuments(updateReqVO.getDocumentIds()); // 更新 AiChatRoleDO updateObj = BeanUtils.toBean(updateReqVO, AiChatRoleDO.class); chatRoleMapper.updateById(updateObj); } + /** + * 校验文档是否存在 + * + * @param documentIds 文档编号列表 + */ + private void validateDocuments(List documentIds) { + if (CollUtil.isEmpty(documentIds)) { + return; + } + // 校验文档是否存在 + documentIds.forEach(knowledgeDocumentService::validateKnowledgeDocumentExists); + } + @Override public void deleteChatRole(Long id) { // 校验存在 @@ -134,7 +165,8 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Override public List getChatRoleCategoryList() { List list = chatRoleMapper.selectListGroupByCategory(CommonStatusEnum.ENABLE.getStatus()); - return convertList(list, AiChatRoleDO::getCategory, role -> role != null && StrUtil.isNotBlank(role.getCategory())); + return convertList(list, AiChatRoleDO::getCategory, + role -> role != null && StrUtil.isNotBlank(role.getCategory())); } @Override @@ -143,4 +175,3 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { } } -