|
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.knowledge;
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.collection.ListUtil;
|
|
|
+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.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO;
|
|
@@ -23,6 +24,10 @@ import org.springframework.ai.vectorstore.filter.FilterExpressionBuilder;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.util.List;
|
|
|
+import java.util.Objects;
|
|
|
+
|
|
|
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
+import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_SEGMENT_NOT_EXISTS;
|
|
|
|
|
|
/**
|
|
|
* AI 知识库分片 Service 实现类
|
|
@@ -50,14 +55,45 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
|
|
|
|
|
|
@Override
|
|
|
public void updateKnowledgeSegment(AiKnowledgeSegmentUpdateReqVO reqVO) {
|
|
|
- segmentMapper.updateById(BeanUtils.toBean(reqVO, AiKnowledgeSegmentDO.class));
|
|
|
- // TODO @xin 重新向量化
|
|
|
+ // 0 校验
|
|
|
+ AiKnowledgeSegmentDO oldKnowledgeSegment = validateKnowledgeSegmentExists(reqVO.getId());
|
|
|
+ // 2.1 获取知识库向量实例
|
|
|
+ VectorStore vectorStore = knowledgeService.getVectorStoreById(oldKnowledgeSegment.getKnowledgeId());
|
|
|
+ // 2.2 删除原向量
|
|
|
+ vectorStore.delete(List.of(oldKnowledgeSegment.getVectorId()));
|
|
|
+
|
|
|
+ // 2.3 重新向量化
|
|
|
+ Document document = new Document(reqVO.getContent());
|
|
|
+ document.getMetadata().put(AiKnowledgeSegmentDO.FIELD_KNOWLEDGE_ID, oldKnowledgeSegment.getKnowledgeId());
|
|
|
+ vectorStore.add(List.of(document));
|
|
|
+
|
|
|
+ // 2.1 更新段落内容
|
|
|
+ AiKnowledgeSegmentDO knowledgeSegment = BeanUtils.toBean(reqVO, AiKnowledgeSegmentDO.class);
|
|
|
+ knowledgeSegment.setVectorId(document.getId());
|
|
|
+ segmentMapper.updateById(knowledgeSegment);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void updateKnowledgeSegmentStatus(AiKnowledgeSegmentUpdateStatusReqVO reqVO) {
|
|
|
- segmentMapper.updateById(BeanUtils.toBean(reqVO, AiKnowledgeSegmentDO.class));
|
|
|
- // TODO @xin 1.禁用删除向量 2.启用重新向量化
|
|
|
+ // 0 校验
|
|
|
+ AiKnowledgeSegmentDO oldKnowledgeSegment = validateKnowledgeSegmentExists(reqVO.getId());
|
|
|
+ // 1 获取知识库向量实例
|
|
|
+ VectorStore vectorStore = knowledgeService.getVectorStoreById(oldKnowledgeSegment.getKnowledgeId());
|
|
|
+ AiKnowledgeSegmentDO knowledgeSegment = BeanUtils.toBean(reqVO, AiKnowledgeSegmentDO.class);
|
|
|
+
|
|
|
+ if (Objects.equals(reqVO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
|
|
|
+ // 2.1 启用重新向量化
|
|
|
+ Document document = new Document(oldKnowledgeSegment.getContent());
|
|
|
+ document.getMetadata().put(AiKnowledgeSegmentDO.FIELD_KNOWLEDGE_ID, oldKnowledgeSegment.getKnowledgeId());
|
|
|
+ vectorStore.add(List.of(document));
|
|
|
+ knowledgeSegment.setVectorId(document.getId());
|
|
|
+ } else {
|
|
|
+ // 2.2 禁用删除向量
|
|
|
+ vectorStore.delete(List.of(oldKnowledgeSegment.getVectorId()));
|
|
|
+ knowledgeSegment.setVectorId(null);
|
|
|
+ }
|
|
|
+ // 3 更新段落状态
|
|
|
+ segmentMapper.updateById(knowledgeSegment);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -71,9 +107,8 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
|
|
|
|
|
|
// 1.2 向量检索
|
|
|
List<Document> documentList = vectorStore.similaritySearch(SearchRequest.query(reqVO.getContent())
|
|
|
- //TODO @xin 配置提取
|
|
|
- .withTopK(5)
|
|
|
- .withSimilarityThreshold(0.5d)
|
|
|
+ .withTopK(knowledge.getTopK())
|
|
|
+ .withSimilarityThreshold(knowledge.getSimilarityThreshold())
|
|
|
.withFilterExpression(new FilterExpressionBuilder().eq(AiKnowledgeSegmentDO.FIELD_KNOWLEDGE_ID, reqVO.getKnowledgeId()).build()));
|
|
|
if (CollUtil.isEmpty(documentList)) {
|
|
|
return ListUtil.empty();
|
|
@@ -81,4 +116,19 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
|
|
|
// 2.1 段落召回
|
|
|
return segmentMapper.selectList(CollUtil.getFieldValues(documentList, "id", String.class));
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验段落是否存在
|
|
|
+ *
|
|
|
+ * @param id 文档编号
|
|
|
+ * @return 段落信息
|
|
|
+ */
|
|
|
+ private AiKnowledgeSegmentDO validateKnowledgeSegmentExists(Long id) {
|
|
|
+ AiKnowledgeSegmentDO knowledgeSegment = segmentMapper.selectById(id);
|
|
|
+ if (knowledgeSegment == null) {
|
|
|
+ throw exception(KNOWLEDGE_SEGMENT_NOT_EXISTS);
|
|
|
+ }
|
|
|
+ return knowledgeSegment;
|
|
|
+ }
|
|
|
}
|