Commit 5cd870748df348ef43b99b19de358d10aaac3b3c

Authored by xiaoxin
1 parent 8e56b81a

【解决todo】AI 知识库: 字段命名统一 补充注释

yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.java
@@ -29,7 +29,7 @@ public class AiKnowledgeSegmentController { @@ -29,7 +29,7 @@ public class AiKnowledgeSegmentController {
29 29
30 @GetMapping("/page") 30 @GetMapping("/page")
31 @Operation(summary = "获取段落分页") 31 @Operation(summary = "获取段落分页")
32 - public CommonResult<PageResult<AiKnowledgeSegmentRespVO>> getKnowledgeSegmentPageMy(@Valid AiKnowledgeSegmentPageReqVO pageReqVO) { 32 + public CommonResult<PageResult<AiKnowledgeSegmentRespVO>> getKnowledgeSegmentPage(@Valid AiKnowledgeSegmentPageReqVO pageReqVO) {
33 PageResult<AiKnowledgeSegmentDO> pageResult = segmentService.getKnowledgeSegmentPage(pageReqVO); 33 PageResult<AiKnowledgeSegmentDO> pageResult = segmentService.getKnowledgeSegmentPage(pageReqVO);
34 return success(BeanUtils.toBean(pageResult, AiKnowledgeSegmentRespVO.class)); 34 return success(BeanUtils.toBean(pageResult, AiKnowledgeSegmentRespVO.class));
35 } 35 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeDocumentCreateReqVO.java
@@ -23,21 +23,21 @@ public class AiKnowledgeDocumentCreateReqVO { @@ -23,21 +23,21 @@ public class AiKnowledgeDocumentCreateReqVO {
23 @URL(message = "文档 URL 格式不正确") 23 @URL(message = "文档 URL 格式不正确")
24 private String url; 24 private String url;
25 25
26 - @Schema(description = "每个文本块的目标 token 数", requiredMode = Schema.RequiredMode.REQUIRED, example = "800")  
27 - @NotNull(message = "每个文本块的目标 token 数不能为空")  
28 - private Integer defaultChunkSize; 26 + @Schema(description = "每个段落的目标 token 数", requiredMode = Schema.RequiredMode.REQUIRED, example = "800")
  27 + @NotNull(message = "每个段落的目标 token 数不能为空")
  28 + private Integer defaultSegmentTokens;
29 29
30 - @Schema(description = "每个文本块的最小字符数", requiredMode = Schema.RequiredMode.REQUIRED, example = "350")  
31 - @NotNull(message = "每个文本块的最小字符数不能为空")  
32 - private Integer minChunkSizeChars; 30 + @Schema(description = "每个段落的最小字符数", requiredMode = Schema.RequiredMode.REQUIRED, example = "350")
  31 + @NotNull(message = "每个段落的最小字符数不能为空")
  32 + private Integer minSegmentWordCount;
33 33
34 - @Schema(description = "丢弃阈值", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") 34 + @Schema(description = "丢弃阈值:低于此阈值的段落会被丢弃", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
35 @NotNull(message = "丢弃阈值不能为空") 35 @NotNull(message = "丢弃阈值不能为空")
36 private Integer minChunkLengthToEmbed; 36 private Integer minChunkLengthToEmbed;
37 37
38 - @Schema(description = "最大块数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")  
39 - @NotNull(message = "最大块数不能为空")  
40 - private Integer maxNumChunks; 38 + @Schema(description = "最大段落数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
  39 + @NotNull(message = "最大段落数不能为空")
  40 + private Integer maxNumSegments;
41 41
42 @Schema(description = "分块是否保留分隔符", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") 42 @Schema(description = "分块是否保留分隔符", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
43 @NotNull(message = "分块是否保留分隔符不能为空") 43 @NotNull(message = "分块是否保留分隔符不能为空")
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDO.java
@@ -38,9 +38,11 @@ public class AiKnowledgeDO extends BaseDO { @@ -38,9 +38,11 @@ public class AiKnowledgeDO extends BaseDO {
38 * 知识库描述 38 * 知识库描述
39 */ 39 */
40 private String description; 40 private String description;
41 - // TODO @新:如果全部可见,需要怎么设置? 41 +
42 /** 42 /**
43 - * 可见权限,只能选择哪些人可见 43 + * 可见权限,选择哪些人可见
  44 + * <p>
  45 + * -1 所有人可见,其他为各自用户编号
44 */ 46 */
45 @TableField(typeHandler = JacksonTypeHandler.class) 47 @TableField(typeHandler = JacksonTypeHandler.class)
46 private List<Long> visibilityPermissions; 48 private List<Long> visibilityPermissions;
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDocumentDO.java
@@ -40,23 +40,25 @@ public class AiKnowledgeDocumentDO extends BaseDO { @@ -40,23 +40,25 @@ public class AiKnowledgeDocumentDO extends BaseDO {
40 */ 40 */
41 private String url; 41 private String url;
42 /** 42 /**
43 - * token 数量 43 + * 文档 token 数量
44 */ 44 */
45 private Integer tokens; 45 private Integer tokens;
46 /** 46 /**
47 - * 字符数 47 + * 文档字符数
48 */ 48 */
49 private Integer wordCount; 49 private Integer wordCount;
50 - // TODO @新:chunk 1)是不是 segment,这样命名保持一致会好点哈?2)Size 是不是改成 Tokens 会统一点;3)defaultChunkSize、defaultChunkSize、minChunkSizeChars、maxNumChunks 这几个字段的命名,可能要微信一起讨论下。尽量命名保持风格统一哈。 50 +
  51 +
  52 + // ========== 自定义分段所用参数 ==========
  53 + // TODO @新:3)defaultChunkSize、defaultChunkSize、minChunkSizeChars、maxNumChunks 这几个字段的命名,可能要微信一起讨论下。尽量命名保持风格统一哈。
51 /** 54 /**
52 * 每个文本块的目标 token 数 55 * 每个文本块的目标 token 数
53 */ 56 */
54 - private Integer defaultChunkSize;  
55 - // TODO @xin:SizeChars 和 wordCount 好像是一个意思,是不是也要统一哈。 57 + private Integer defaultSegmentTokens;
56 /** 58 /**
57 * 每个文本块的最小字符数 59 * 每个文本块的最小字符数
58 */ 60 */
59 - private Integer minChunkSizeChars; 61 + private Integer minSegmentWordCount;
60 /** 62 /**
61 * 低于此值的块会被丢弃 63 * 低于此值的块会被丢弃
62 */ 64 */
@@ -64,11 +66,13 @@ public class AiKnowledgeDocumentDO extends BaseDO { @@ -64,11 +66,13 @@ public class AiKnowledgeDocumentDO extends BaseDO {
64 /** 66 /**
65 * 最大块数 67 * 最大块数
66 */ 68 */
67 - private Integer maxNumChunks; 69 + private Integer maxNumSegments;
68 /** 70 /**
69 * 分块是否保留分隔符 71 * 分块是否保留分隔符
70 */ 72 */
71 private Boolean keepSeparator; 73 private Boolean keepSeparator;
  74 + // ===================================
  75 +
72 /** 76 /**
73 * 切片状态 77 * 切片状态
74 * <p> 78 * <p>
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeSegmentDO.java
@@ -2,8 +2,6 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; @@ -2,8 +2,6 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 -import com.baomidou.mybatisplus.annotation.FieldStrategy;  
6 -import com.baomidou.mybatisplus.annotation.TableField;  
7 import com.baomidou.mybatisplus.annotation.TableId; 5 import com.baomidou.mybatisplus.annotation.TableId;
8 import com.baomidou.mybatisplus.annotation.TableName; 6 import com.baomidou.mybatisplus.annotation.TableName;
9 import lombok.Data; 7 import lombok.Data;
@@ -27,7 +25,6 @@ public class AiKnowledgeSegmentDO extends BaseDO { @@ -27,7 +25,6 @@ public class AiKnowledgeSegmentDO extends BaseDO {
27 /** 25 /**
28 * 向量库的编号 26 * 向量库的编号
29 */ 27 */
30 - @TableField(updateStrategy = FieldStrategy.ALWAYS) // TODO @新:尽量规避要这个注解。万一后面加个 status 单独更新,可能会踩坑。  
31 private String vectorId; 28 private String vectorId;
32 /** 29 /**
33 * 知识库编号 30 * 知识库编号
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java
@@ -25,8 +25,7 @@ public interface AiKnowledgeSegmentMapper extends BaseMapperX&lt;AiKnowledgeSegment @@ -25,8 +25,7 @@ public interface AiKnowledgeSegmentMapper extends BaseMapperX&lt;AiKnowledgeSegment
25 .orderByDesc(AiKnowledgeSegmentDO::getId)); 25 .orderByDesc(AiKnowledgeSegmentDO::getId));
26 } 26 }
27 27
28 - // TODO @新:selectListByXXX 哈  
29 - default List<AiKnowledgeSegmentDO> selectList(List<String> vectorIdList) { 28 + default List<AiKnowledgeSegmentDO> selectListByVectorIds(List<String> vectorIdList) {
30 return selectList(new LambdaQueryWrapperX<AiKnowledgeSegmentDO>() 29 return selectList(new LambdaQueryWrapperX<AiKnowledgeSegmentDO>()
31 .in(AiKnowledgeSegmentDO::getVectorId, vectorIdList) 30 .in(AiKnowledgeSegmentDO::getVectorId, vectorIdList)
32 .orderByDesc(AiKnowledgeSegmentDO::getId)); 31 .orderByDesc(AiKnowledgeSegmentDO::getId));
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
@@ -71,8 +71,8 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic @@ -71,8 +71,8 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic
71 } 71 }
72 72
73 // 2 构造文本分段器 73 // 2 构造文本分段器
74 - TokenTextSplitter tokenTextSplitter = new TokenTextSplitter(createReqVO.getDefaultChunkSize(), createReqVO.getMinChunkSizeChars(), createReqVO.getMinChunkLengthToEmbed(),  
75 - createReqVO.getMaxNumChunks(), createReqVO.getKeepSeparator()); 74 + TokenTextSplitter tokenTextSplitter = new TokenTextSplitter(createReqVO.getDefaultSegmentTokens(), createReqVO.getMinSegmentWordCount(), createReqVO.getMinChunkLengthToEmbed(),
  75 + createReqVO.getMaxNumSegments(), createReqVO.getKeepSeparator());
76 // 2.1 文档分段 76 // 2.1 文档分段
77 List<Document> segments = tokenTextSplitter.apply(documents); 77 List<Document> segments = tokenTextSplitter.apply(documents);
78 // 2.2 分段内容入库 78 // 2.2 分段内容入库
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java
@@ -90,7 +90,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService @@ -90,7 +90,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
90 } else { 90 } else {
91 // 2.2 禁用删除向量 91 // 2.2 禁用删除向量
92 vectorStore.delete(List.of(oldKnowledgeSegment.getVectorId())); 92 vectorStore.delete(List.of(oldKnowledgeSegment.getVectorId()));
93 - knowledgeSegment.setVectorId(null); 93 + knowledgeSegment.setVectorId("");
94 } 94 }
95 // 3 更新段落状态 95 // 3 更新段落状态
96 segmentMapper.updateById(knowledgeSegment); 96 segmentMapper.updateById(knowledgeSegment);
@@ -114,7 +114,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService @@ -114,7 +114,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
114 return ListUtil.empty(); 114 return ListUtil.empty();
115 } 115 }
116 // 3.2 段落召回 116 // 3.2 段落召回
117 - return segmentMapper.selectList(CollUtil.getFieldValues(documentList, "id", String.class)); 117 + return segmentMapper.selectListByVectorIds(CollUtil.getFieldValues(documentList, "id", String.class));
118 } 118 }
119 119
120 /** 120 /**
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeService.java
@@ -47,13 +47,12 @@ public interface AiKnowledgeService { @@ -47,13 +47,12 @@ public interface AiKnowledgeService {
47 */ 47 */
48 PageResult<AiKnowledgeDO> getKnowledgePageMy(Long userId, PageParam pageReqVO); 48 PageResult<AiKnowledgeDO> getKnowledgePageMy(Long userId, PageParam pageReqVO);
49 49
50 - // TODO @新:knowledgeId 和 validateKnowledgeExists 的 id 是同一个么?如果是的话,建议变量也用 id 哈,然后两边的 id 注释,保持一致  
51 /** 50 /**
52 * 根据知识库编号获取向量存储实例 51 * 根据知识库编号获取向量存储实例
53 * 52 *
54 - * @param knowledgeId 知识库编号 53 + * @param id 知识库编号
55 * @return 向量存储实例 54 * @return 向量存储实例
56 */ 55 */
57 - VectorStore getVectorStoreById(Long knowledgeId); 56 + VectorStore getVectorStoreById(Long id);
58 57
59 } 58 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeServiceImpl.java
@@ -30,20 +30,17 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_NOT_ @@ -30,20 +30,17 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_NOT_
30 public class AiKnowledgeServiceImpl implements AiKnowledgeService { 30 public class AiKnowledgeServiceImpl implements AiKnowledgeService {
31 31
32 @Resource 32 @Resource
33 - private AiChatModelService chatModalService;  
34 -  
35 - @Resource  
36 private AiKnowledgeMapper knowledgeMapper; 33 private AiKnowledgeMapper knowledgeMapper;
  34 +
37 @Resource 35 @Resource
38 private AiChatModelService chatModelService; 36 private AiChatModelService chatModelService;
39 @Resource 37 @Resource
40 private AiApiKeyService apiKeyService; 38 private AiApiKeyService apiKeyService;
41 - // TODO @新:chatModelService 和 apiKeyService 可以放到 33 行的 chatModalService 后面。尽量保持,想通类型的变量在一块。例如说,Service 一块,Mapper 一块。  
42 39
43 @Override 40 @Override
44 public Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId) { 41 public Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId) {
45 // 1. 校验模型配置 42 // 1. 校验模型配置
46 - AiChatModelDO model = chatModalService.validateChatModel(createReqVO.getModelId()); 43 + AiChatModelDO model = chatModelService.validateChatModel(createReqVO.getModelId());
47 44
48 // 2. 插入知识库 45 // 2. 插入知识库
49 AiKnowledgeDO knowledgeBase = BeanUtils.toBean(createReqVO, AiKnowledgeDO.class) 46 AiKnowledgeDO knowledgeBase = BeanUtils.toBean(createReqVO, AiKnowledgeDO.class)
@@ -60,7 +57,7 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService { @@ -60,7 +57,7 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService {
60 throw exception(KNOWLEDGE_NOT_EXISTS); 57 throw exception(KNOWLEDGE_NOT_EXISTS);
61 } 58 }
62 // 1.2 校验模型配置 59 // 1.2 校验模型配置
63 - AiChatModelDO model = chatModalService.validateChatModel(updateReqVO.getModelId()); 60 + AiChatModelDO model = chatModelService.validateChatModel(updateReqVO.getModelId());
64 61
65 // 2. 更新知识库 62 // 2. 更新知识库
66 AiKnowledgeDO updateDO = BeanUtils.toBean(updateReqVO, AiKnowledgeDO.class); 63 AiKnowledgeDO updateDO = BeanUtils.toBean(updateReqVO, AiKnowledgeDO.class);
@@ -83,8 +80,8 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService { @@ -83,8 +80,8 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService {
83 } 80 }
84 81
85 @Override 82 @Override
86 - public VectorStore getVectorStoreById(Long knowledgeId) {  
87 - AiKnowledgeDO knowledge = validateKnowledgeExists(knowledgeId); 83 + public VectorStore getVectorStoreById(Long id) {
  84 + AiKnowledgeDO knowledge = validateKnowledgeExists(id);
88 AiChatModelDO model = chatModelService.validateChatModel(knowledge.getModelId()); 85 AiChatModelDO model = chatModelService.validateChatModel(knowledge.getModelId());
89 // 创建或获取 VectorStore 对象 86 // 创建或获取 VectorStore 对象
90 return apiKeyService.getOrCreateVectorStore(model.getKeyId()); 87 return apiKeyService.getOrCreateVectorStore(model.getKeyId());
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
@@ -197,7 +197,6 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -197,7 +197,6 @@ public class AiModelFactoryImpl implements AiModelFactory {
197 }); 197 });
198 } 198 }
199 199
200 - // TODO @新:貌似可以创建一个大的 VectorStore。然后搜的时候,通过 Filter.Expression 过滤对应的数据。  
201 @Override 200 @Override
202 public VectorStore getOrCreateVectorStore(EmbeddingModel embeddingModel, AiPlatformEnum platform, String apiKey, String url) { 201 public VectorStore getOrCreateVectorStore(EmbeddingModel embeddingModel, AiPlatformEnum platform, String apiKey, String url) {
203 String cacheKey = buildClientCacheKey(VectorStore.class, platform, apiKey, url); 202 String cacheKey = buildClientCacheKey(VectorStore.class, platform, apiKey, url);