Przeglądaj źródła

【功能新增】AI:聊天角色,新增 document 的引用绑定

YunaiV 5 miesięcy temu
rodzic
commit
9126691ac0
11 zmienionych plików z 100 dodań i 10 usunięć
  1. 13 0
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java
  2. 1 1
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java
  3. 5 1
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java
  4. 5 0
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java
  5. 5 0
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java
  6. 13 0
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java
  7. 6 1
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java
  8. 8 0
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentService.java
  9. 6 0
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
  10. 4 4
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java
  11. 34 3
      yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java

+ 13 - 0
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<List<AiKnowledgeDocumentRespVO>> getKnowledgeDocumentSimpleList() {
+        List<AiKnowledgeDocumentDO> list = documentService
+                .getKnowledgeDocumentListByStatus(CommonStatusEnum.ENABLE.getStatus());
+        return success(convertList(list, document -> new AiKnowledgeDocumentRespVO()
+                .setId(document.getId()).setName(document.getName())));
+    }
+
 }

+ 1 - 1
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<List<String>> getChatRoleCategoryList() {
-         return success(chatRoleService.getChatRoleCategoryList());
+        return success(chatRoleService.getChatRoleCategoryList());
     }
 
     // ========== 角色管理 ==========

+ 5 - 1
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<Long> documentIds;
+
     @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Boolean publicStatus;
 

+ 5 - 0
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<Long> documentIds;
+
 }

+ 5 - 0
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<Long> documentIds;
+
     @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "是否公开不能为空")
     private Boolean publicStatus;

+ 13 - 0
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<Long> documentIds;
+
     /**
      * 是否公开
      *

+ 6 - 1
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<AiKnowledgeDocume
     }
 
     default void updateRetrievalCountIncr(Collection<Long> ids) {
-        update( new LambdaUpdateWrapper<AiKnowledgeDocumentDO>()
+        update(new LambdaUpdateWrapper<AiKnowledgeDocumentDO>()
                 .setSql(" retrieval_count = retrieval_count + 1")
                 .in(AiKnowledgeDocumentDO::getId, ids));
     }
 
+    default List<AiKnowledgeDocumentDO> selectListByStatus(Integer status) {
+        return selectList(AiKnowledgeDocumentDO::getStatus, status);
+    }
+
 }

+ 8 - 0
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<AiKnowledgeDocumentDO> getKnowledgeDocumentListByStatus(Integer status);
+
 }

+ 6 - 0
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<AiKnowledgeDocumentDO> getKnowledgeDocumentListByStatus(Integer status) {
+        return knowledgeDocumentMapper.selectListByStatus(status);
+    }
+
 }

+ 4 - 4
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<AiChatRoleDO> getChatRoleMyPage(AiChatRolePageReqVO pageReqVO, Long userId);

+ 34 - 3
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<Long> 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<String> getChatRoleCategoryList() {
         List<AiChatRoleDO> 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 {
     }
 
 }
-