Commit 9126691ac0f699c8f4971b2b04f62ba539b2a962

Authored by YunaiV
1 parent f286a813

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

yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java
1 1 package cn.iocoder.yudao.module.ai.controller.admin.knowledge;
2 2  
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 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
10 11 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateStatusReqVO;
11 12 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO;
12 13 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
  14 +import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeDocumentMapper;
13 15 import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService;
14 16 import io.swagger.v3.oas.annotations.Operation;
  17 +import io.swagger.v3.oas.annotations.Parameter;
15 18 import io.swagger.v3.oas.annotations.tags.Tag;
16 19 import jakarta.annotation.Resource;
17 20 import jakarta.validation.Valid;
... ... @@ -22,6 +25,7 @@ import org.springframework.web.bind.annotation.*;
22 25 import java.util.List;
23 26  
24 27 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  28 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
25 29  
26 30 @Tag(name = "管理后台 - AI 知识库文档")
27 31 @RestController
... ... @@ -91,4 +95,13 @@ public class AiKnowledgeDocumentController {
91 95 return success(true);
92 96 }
93 97  
  98 + @GetMapping("/simple-list")
  99 + @Operation(summary = "获得知识库文档的精简列表")
  100 + public CommonResult<List<AiKnowledgeDocumentRespVO>> getKnowledgeDocumentSimpleList() {
  101 + List<AiKnowledgeDocumentDO> list = documentService
  102 + .getKnowledgeDocumentListByStatus(CommonStatusEnum.ENABLE.getStatus());
  103 + return success(convertList(list, document -> new AiKnowledgeDocumentRespVO()
  104 + .setId(document.getId()).setName(document.getName())));
  105 + }
  106 +
94 107 }
... ...
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 {
75 75 @GetMapping("/category-list")
76 76 @Operation(summary = "获得聊天角色的分类列表")
77 77 public CommonResult<List<String>> getChatRoleCategoryList() {
78   - return success(chatRoleService.getChatRoleCategoryList());
  78 + return success(chatRoleService.getChatRoleCategoryList());
79 79 }
80 80  
81 81 // ========== 角色管理 ==========
... ...
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;
8 8 import lombok.Data;
9 9  
10 10 import java.time.LocalDateTime;
  11 +import java.util.List;
11 12  
12 13 @Schema(description = "管理后台 - AI 聊天角色 Response VO")
13 14 @Data
... ... @@ -20,7 +21,7 @@ public class AiChatRoleRespVO implements VO {
20 21 private Long userId;
21 22  
22 23 @Schema(description = "模型编号", example = "17640")
23   - @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = {"name", "model"}, refs = {"modelName", "model"})
  24 + @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = { "name", "model" }, refs = { "modelName", "model" })
24 25 private Long modelId;
25 26 @Schema(description = "模型名字", example = "张三")
26 27 private String modelName;
... ... @@ -45,6 +46,9 @@ public class AiChatRoleRespVO implements VO {
45 46 @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED)
46 47 private String systemMessage;
47 48  
  49 + @Schema(description = "知识库文档编号列表", example = "1,2,3")
  50 + private List<Long> documentIds;
  51 +
48 52 @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
49 53 private Boolean publicStatus;
50 54  
... ...
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;
5 5 import lombok.Data;
6 6 import org.hibernate.validator.constraints.URL;
7 7  
  8 +import java.util.List;
  9 +
8 10 @Schema(description = "管理后台 - AI 聊天角色新增/修改【我的】 Request VO")
9 11 @Data
10 12 public class AiChatRoleSaveMyReqVO {
... ... @@ -29,4 +31,7 @@ public class AiChatRoleSaveMyReqVO {
29 31 @NotEmpty(message = "角色设定不能为空")
30 32 private String systemMessage;
31 33  
  34 + @Schema(description = "知识库文档编号列表", example = "1,2,3")
  35 + private List<Long> documentIds;
  36 +
32 37 }
33 38 \ No newline at end of file
... ...
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.*;
7 7 import jakarta.validation.constraints.*;
8 8 import org.hibernate.validator.constraints.URL;
9 9  
  10 +import java.util.List;
  11 +
10 12 @Schema(description = "管理后台 - AI 聊天角色新增/修改 Request VO")
11 13 @Data
12 14 public class AiChatRoleSaveReqVO {
... ... @@ -42,6 +44,9 @@ public class AiChatRoleSaveReqVO {
42 44 @NotEmpty(message = "角色设定不能为空")
43 45 private String systemMessage;
44 46  
  47 + @Schema(description = "知识库文档编号列表", example = "1,2,3")
  48 + private List<Long> documentIds;
  49 +
45 50 @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
46 51 @NotNull(message = "是否公开不能为空")
47 52 private Boolean publicStatus;
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
  6 +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
5 7 import com.baomidou.mybatisplus.annotation.KeySequence;
  8 +import com.baomidou.mybatisplus.annotation.TableField;
6 9 import com.baomidou.mybatisplus.annotation.TableId;
7 10 import com.baomidou.mybatisplus.annotation.TableName;
8 11 import lombok.*;
9 12  
  13 +import java.util.List;
  14 +
10 15 /**
11 16 * AI 聊天角色 DO
12 17 *
... ... @@ -63,6 +68,14 @@ public class AiChatRoleDO extends BaseDO {
63 68 private Long modelId;
64 69  
65 70 /**
  71 + * 知识库文档编号列表
  72 + *
  73 + * 关联 {@link AiKnowledgeDocumentDO#getId()} 字段
  74 + */
  75 + @TableField(typeHandler = LongListTypeHandler.class)
  76 + private List<Long> documentIds;
  77 +
  78 + /**
66 79 * 是否公开
67 80 *
68 81 * 1. true - 公开;由管理员在【角色管理】所创建
... ...
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;
9 9 import org.apache.ibatis.annotations.Mapper;
10 10  
11 11 import java.util.Collection;
  12 +import java.util.List;
12 13  
13 14 /**
14 15 * AI 知识库文档 Mapper
... ... @@ -26,9 +27,13 @@ public interface AiKnowledgeDocumentMapper extends BaseMapperX&lt;AiKnowledgeDocume
26 27 }
27 28  
28 29 default void updateRetrievalCountIncr(Collection<Long> ids) {
29   - update( new LambdaUpdateWrapper<AiKnowledgeDocumentDO>()
  30 + update(new LambdaUpdateWrapper<AiKnowledgeDocumentDO>()
30 31 .setSql(" retrieval_count = retrieval_count + 1")
31 32 .in(AiKnowledgeDocumentDO::getId, ids));
32 33 }
33 34  
  35 + default List<AiKnowledgeDocumentDO> selectListByStatus(Integer status) {
  36 + return selectList(AiKnowledgeDocumentDO::getStatus, status);
  37 + }
  38 +
34 39 }
... ...
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 {
115 115 return convertMap(getKnowledgeDocumentList(ids), AiKnowledgeDocumentDO::getId);
116 116 }
117 117  
  118 + /**
  119 + * 获取指定状态的文档列表
  120 + *
  121 + * @param status 状态
  122 + * @return 文档列表
  123 + */
  124 + List<AiKnowledgeDocumentDO> getKnowledgeDocumentListByStatus(Integer status);
  125 +
118 126 }
... ...
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;
7 7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
8 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  10 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
10 11 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentCreateListReqVO;
11 12 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO;
12 13 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO;
... ... @@ -210,4 +211,9 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic
210 211 return knowledgeDocumentMapper.selectByIds(ids);
211 212 }
212 213  
  214 + @Override
  215 + public List<AiKnowledgeDocumentDO> getKnowledgeDocumentListByStatus(Integer status) {
  216 + return knowledgeDocumentMapper.selectListByStatus(status);
  217 + }
  218 +
213 219 }
... ...
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 {
32 32 * 创建【我的】聊天角色
33 33 *
34 34 * @param createReqVO 创建信息
35   - * @param userId 用户编号
  35 + * @param userId 用户编号
36 36 * @return 编号
37 37 */
38 38 Long createChatRoleMy(AiChatRoleSaveMyReqVO createReqVO, Long userId);
... ... @@ -48,7 +48,7 @@ public interface AiChatRoleService {
48 48 * 创建【我的】聊天角色
49 49 *
50 50 * @param updateReqVO 更新信息
51   - * @param userId 用户编号
  51 + * @param userId 用户编号
52 52 */
53 53 void updateChatRoleMy(AiChatRoleSaveMyReqVO updateReqVO, Long userId);
54 54  
... ... @@ -62,7 +62,7 @@ public interface AiChatRoleService {
62 62 /**
63 63 * 删除【我的】聊天角色
64 64 *
65   - * @param id 编号
  65 + * @param id 编号
66 66 * @param userId 用户编号
67 67 */
68 68 void deleteChatRoleMy(Long id, Long userId);
... ... @@ -106,7 +106,7 @@ public interface AiChatRoleService {
106 106 * 获得【我的】聊天角色分页
107 107 *
108 108 * @param pageReqVO 分页查询
109   - * @param userId 用户编号
  109 + * @param userId 用户编号
110 110 * @return 聊天角色分页
111 111 */
112 112 PageResult<AiChatRoleDO> getChatRoleMyPage(AiChatRolePageReqVO pageReqVO, Long userId);
... ...
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;
5 5 import cn.hutool.core.util.StrUtil;
6 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  8 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
8 9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
9 10 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO;
10 11 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO;
11 12 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO;
12 13 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
13 14 import cn.iocoder.yudao.module.ai.dal.mysql.model.AiChatRoleMapper;
  15 +import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService;
14 16 import jakarta.annotation.Resource;
15 17 import lombok.extern.slf4j.Slf4j;
16 18 import org.springframework.stereotype.Service;
... ... @@ -35,8 +37,15 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
35 37 @Resource
36 38 private AiChatRoleMapper chatRoleMapper;
37 39  
  40 + @Resource
  41 + private AiKnowledgeDocumentService knowledgeDocumentService;
  42 +
38 43 @Override
39 44 public Long createChatRole(AiChatRoleSaveReqVO createReqVO) {
  45 + // 校验文档
  46 + validateDocuments(createReqVO.getDocumentIds());
  47 +
  48 + // 保存角色
40 49 AiChatRoleDO chatRole = BeanUtils.toBean(createReqVO, AiChatRoleDO.class);
41 50 chatRoleMapper.insert(chatRole);
42 51 return chatRole.getId();
... ... @@ -44,6 +53,10 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
44 53  
45 54 @Override
46 55 public Long createChatRoleMy(AiChatRoleSaveMyReqVO createReqVO, Long userId) {
  56 + // 校验文档
  57 + validateDocuments(createReqVO.getDocumentIds());
  58 +
  59 + // 保存角色
47 60 AiChatRoleDO chatRole = BeanUtils.toBean(createReqVO, AiChatRoleDO.class).setUserId(userId)
48 61 .setStatus(CommonStatusEnum.ENABLE.getStatus()).setPublicStatus(false);
49 62 chatRoleMapper.insert(chatRole);
... ... @@ -54,7 +67,10 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
54 67 public void updateChatRole(AiChatRoleSaveReqVO updateReqVO) {
55 68 // 校验存在
56 69 validateChatRoleExists(updateReqVO.getId());
57   - // 更新
  70 + // 校验文档
  71 + validateDocuments(updateReqVO.getDocumentIds());
  72 +
  73 + // 更新角色
58 74 AiChatRoleDO updateObj = BeanUtils.toBean(updateReqVO, AiChatRoleDO.class);
59 75 chatRoleMapper.updateById(updateObj);
60 76 }
... ... @@ -66,12 +82,27 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
66 82 if (ObjectUtil.notEqual(chatRole.getUserId(), userId)) {
67 83 throw exception(CHAT_ROLE_NOT_EXISTS);
68 84 }
  85 + // 校验文档
  86 + validateDocuments(updateReqVO.getDocumentIds());
69 87  
70 88 // 更新
71 89 AiChatRoleDO updateObj = BeanUtils.toBean(updateReqVO, AiChatRoleDO.class);
72 90 chatRoleMapper.updateById(updateObj);
73 91 }
74 92  
  93 + /**
  94 + * 校验文档是否存在
  95 + *
  96 + * @param documentIds 文档编号列表
  97 + */
  98 + private void validateDocuments(List<Long> documentIds) {
  99 + if (CollUtil.isEmpty(documentIds)) {
  100 + return;
  101 + }
  102 + // 校验文档是否存在
  103 + documentIds.forEach(knowledgeDocumentService::validateKnowledgeDocumentExists);
  104 + }
  105 +
75 106 @Override
76 107 public void deleteChatRole(Long id) {
77 108 // 校验存在
... ... @@ -134,7 +165,8 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
134 165 @Override
135 166 public List<String> getChatRoleCategoryList() {
136 167 List<AiChatRoleDO> list = chatRoleMapper.selectListGroupByCategory(CommonStatusEnum.ENABLE.getStatus());
137   - return convertList(list, AiChatRoleDO::getCategory, role -> role != null && StrUtil.isNotBlank(role.getCategory()));
  168 + return convertList(list, AiChatRoleDO::getCategory,
  169 + role -> role != null && StrUtil.isNotBlank(role.getCategory()));
138 170 }
139 171  
140 172 @Override
... ... @@ -143,4 +175,3 @@ public class AiChatRoleServiceImpl implements AiChatRoleService {
143 175 }
144 176  
145 177 }
146   -
... ...