【功能新增】AI:新增知识库文档的更新信息与状态

This commit is contained in:
YunaiV 2025-03-01 11:42:11 +08:00
parent d1e207899a
commit a998168b3b
8 changed files with 87 additions and 14 deletions

View File

@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowl
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentRespVO;
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentCreateListReqVO;
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.service.knowledge.AiKnowledgeDocumentService;
@ -47,14 +48,14 @@ public class AiKnowledgeDocumentController {
}
@PostMapping("/create")
@Operation(summary = "新建文档")
@Operation(summary = "新建文档(单个)")
public CommonResult<Long> createKnowledgeDocument(@RequestBody @Valid AiKnowledgeDocumentCreateReqVO reqVO) {
Long id = documentService.createKnowledgeDocument(reqVO);
return success(id);
}
@PostMapping("/create-list")
@Operation(summary = "批量新建文档")
@Operation(summary = "新建文档(多个)")
public CommonResult<List<Long>> createKnowledgeDocumentList(
@RequestBody @Valid AiKnowledgeDocumentCreateListReqVO reqVO) {
List<Long> ids = documentService.createKnowledgeDocumentList(reqVO);
@ -68,4 +69,12 @@ public class AiKnowledgeDocumentController {
return success(true);
}
@PutMapping("/update-status")
@Operation(summary = "更新文档状态")
public CommonResult<Boolean> updateKnowledgeDocumentStatus(
@Valid @RequestBody AiKnowledgeDocumentUpdateStatusReqVO reqVO) {
documentService.updateKnowledgeDocumentStatus(reqVO);
return success(true);
}
}

View File

@ -15,6 +15,7 @@ import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.hibernate.validator.constraints.URL;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -62,7 +63,7 @@ public class AiKnowledgeSegmentController {
@Parameter(name = "segmentMaxTokens", description = "分段的最大 Token 数", required = true)
})
public CommonResult<List<AiKnowledgeSegmentRespVO>> splitContent(
@RequestParam("url") String url,
@RequestParam("url") @URL String url,
@RequestParam(value = "segmentMaxTokens") Integer segmentMaxTokens) {
List<AiKnowledgeSegmentDO> segments = segmentService.splitContent(url, segmentMaxTokens);
return success(BeanUtils.toBean(segments, AiKnowledgeSegmentRespVO.class));

View File

@ -1,12 +1,9 @@
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
// TODO @芋艿稍后优化
@Schema(description = "管理后台 - AI 知识库文档更新 Request VO")
@Data
public class AiKnowledgeDocumentUpdateReqVO {
@ -18,8 +15,7 @@ public class AiKnowledgeDocumentUpdateReqVO {
@Schema(description = "名称", example = "Java 开发手册")
private String name;
@Schema(description = "是否启用", example = "1")
@InEnum(CommonStatusEnum.class)
private Integer status;
@Schema(description = "分片最大 Token 数", example = "1000")
private Integer segmentMaxTokens;
}

View File

@ -31,4 +31,10 @@ public interface AiKnowledgeSegmentMapper extends BaseMapperX<AiKnowledgeSegment
.orderByDesc(AiKnowledgeSegmentDO::getId));
}
default List<AiKnowledgeSegmentDO> selectListByDocumentId(Long documentId) {
return selectList(new LambdaQueryWrapperX<AiKnowledgeSegmentDO>()
.eq(AiKnowledgeSegmentDO::getDocumentId, documentId)
.orderByDesc(AiKnowledgeSegmentDO::getId));
}
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.service.knowledge;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO;
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.controller.admin.knowledge.vo.document.AiKnowledgeDocumentCreateListReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
@ -10,14 +11,14 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO
import java.util.List;
/**
* AI 知识库-文档 Service 接口
* AI 知识库文档 Service 接口
*
* @author xiaoxin
*/
public interface AiKnowledgeDocumentService {
/**
* 创建文档
* 创建文档单个
*
* @param createReqVO 文档创建 Request VO
* @return 文档编号
@ -25,7 +26,7 @@ public interface AiKnowledgeDocumentService {
Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO);
/**
* 批量创建文档
* 创建文档多个
*
* @param createListReqVO 批量创建 Request VO
* @return 文档编号列表
@ -55,6 +56,13 @@ public interface AiKnowledgeDocumentService {
*/
void updateKnowledgeDocument(AiKnowledgeDocumentUpdateReqVO reqVO);
/**
* 更新文档状态
*
* @param reqVO 更新状态信息
*/
void updateKnowledgeDocumentStatus(AiKnowledgeDocumentUpdateStatusReqVO reqVO);
/**
* 校验文档是否存在
*

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.ai.service.knowledge;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
@ -8,6 +9,7 @@ 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.document.AiKnowledgeDocumentPageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateStatusReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentCreateListReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
@ -88,6 +90,7 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic
.setKnowledgeId(createListReqVO.getKnowledgeId())
.setContent(content).setContentLength(content.length())
.setTokens(tokenCountEstimator.estimate(content))
.setSegmentMaxTokens(createListReqVO.getSegmentMaxTokens())
.setStatus(CommonStatusEnum.ENABLE.getStatus()));
}
knowledgeDocumentMapper.insertBatch(documentDOs);
@ -111,11 +114,38 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic
@Override
public void updateKnowledgeDocument(AiKnowledgeDocumentUpdateReqVO reqVO) {
// 1. 校验文档是否存在
validateKnowledgeDocumentExists(reqVO.getId());
AiKnowledgeDocumentDO oldDocument = validateKnowledgeDocumentExists(reqVO.getId());
// 2. 更新文档
AiKnowledgeDocumentDO document = BeanUtils.toBean(reqVO, AiKnowledgeDocumentDO.class);
knowledgeDocumentMapper.updateById(document);
// TODO @芋艿这里要处理状态的变更
// 3. 如果处于开启状态并且最大 tokens 发生变化 segment 需要重新索引
if (CommonStatusEnum.isEnable(oldDocument.getStatus())
&& reqVO.getSegmentMaxTokens() != null
&& ObjUtil.notEqual(reqVO.getSegmentMaxTokens(), oldDocument.getSegmentMaxTokens())) {
// 删除旧的文档切片
knowledgeSegmentService.deleteKnowledgeSegmentByDocumentId(reqVO.getId());
// 重新创建文档切片
knowledgeSegmentService.createKnowledgeSegmentBySplitContentAsync(reqVO.getId(), oldDocument.getContent());
}
}
@Override
public void updateKnowledgeDocumentStatus(AiKnowledgeDocumentUpdateStatusReqVO reqVO) {
// 1. 校验存在
AiKnowledgeDocumentDO document = validateKnowledgeDocumentExists(reqVO.getId());
// 2. 更新状态
knowledgeDocumentMapper.updateById(new AiKnowledgeDocumentDO()
.setId(reqVO.getId()).setStatus(reqVO.getStatus()));
// 3. 处理文档切片
if (CommonStatusEnum.isEnable(reqVO.getStatus())) {
knowledgeSegmentService.createKnowledgeSegmentBySplitContentAsync(reqVO.getId(), document.getContent());
} else {
knowledgeSegmentService.deleteKnowledgeSegmentByDocumentId(reqVO.getId());
}
}
@Override

View File

@ -58,6 +58,13 @@ public interface AiKnowledgeSegmentService {
*/
void updateKnowledgeSegmentStatus(AiKnowledgeSegmentUpdateStatusReqVO reqVO);
/**
* 根据文档编号删除段落
*
* @param documentId 文档编号
*/
void deleteKnowledgeSegmentByDocumentId(Long documentId);
/**
* 召回段落
*

View File

@ -115,6 +115,22 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
}
}
@Override
public void deleteKnowledgeSegmentByDocumentId(Long documentId) {
// 1. 查询需要删除的段落
List<AiKnowledgeSegmentDO> segments = segmentMapper.selectListByDocumentId(documentId);
if (CollUtil.isEmpty(segments)) {
return;
}
// 2. 批量删除段落记录
segmentMapper.deleteByIds(convertList(segments, AiKnowledgeSegmentDO::getId));
// 3. 删除向量存储中的段落
VectorStore vectorStore = getVectorStoreById(segments.get(0).getKnowledgeId());
vectorStore.delete(convertList(segments, AiKnowledgeSegmentDO::getVectorId));
}
@Override
public void updateKnowledgeSegmentStatus(AiKnowledgeSegmentUpdateStatusReqVO reqVO) {
// 1. 校验