feat(rag): 补齐知识工作台聚合与转换分层
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package com.bruce.rag.controller;
|
||||
|
||||
import com.bruce.common.domain.model.RequestResult;
|
||||
import com.bruce.rag.service.IKnowledgeWorkspaceService;
|
||||
import com.bruce.rag.vo.KnowledgeWorkspaceVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 知识工作台聚合接口。
|
||||
*/
|
||||
@Tag(name = "知识工作台")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/knowledge/workspaces")
|
||||
public class KnowledgeWorkspaceController {
|
||||
|
||||
private final IKnowledgeWorkspaceService knowledgeWorkspaceService;
|
||||
|
||||
@Operation(summary = "查询知识工作台聚合视图")
|
||||
@GetMapping("/{storeId}")
|
||||
public RequestResult<KnowledgeWorkspaceVO> getWorkspace(@PathVariable("storeId") Long storeId) {
|
||||
log.info("KnowledgeWorkspaceController.getWorkspace start, storeId={}", storeId);
|
||||
KnowledgeWorkspaceVO workspace = knowledgeWorkspaceService.getWorkspace(storeId);
|
||||
log.info("KnowledgeWorkspaceController.getWorkspace success, storeId={}, documentCount={}, healthScore={}",
|
||||
storeId, workspace.getDocumentCount(), workspace.getHealthScore());
|
||||
return RequestResult.success(workspace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.bruce.rag.factory;
|
||||
|
||||
import com.bruce.rag.dto.request.RagDocumentSaveRequest;
|
||||
import com.bruce.rag.dto.response.RagDocumentResponse;
|
||||
import com.bruce.rag.entity.RagDocument;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 知识文档工厂,统一处理文档相关 DTO、Entity、VO 的转换逻辑。
|
||||
*/
|
||||
@Component
|
||||
public class RagDocumentFactory {
|
||||
|
||||
/**
|
||||
* 将保存请求转换为实体,供新增或全量更新场景复用。
|
||||
*/
|
||||
public RagDocument toEntity(RagDocumentSaveRequest request) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
RagDocument entity = new RagDocument();
|
||||
applyEditableFields(entity, request);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将请求中的可编辑字段写入已有实体,避免服务层散落 setXXX 逻辑。
|
||||
*/
|
||||
public void applyEditableFields(RagDocument entity, RagDocumentSaveRequest request) {
|
||||
if (entity == null || request == null) {
|
||||
return;
|
||||
}
|
||||
entity.setId(request.getId());
|
||||
entity.setStoreId(request.getStoreId());
|
||||
entity.setAttachmentId(request.getAttachmentId());
|
||||
entity.setDocumentTitle(trimToNull(request.getDocumentTitle()));
|
||||
entity.setDocumentSummary(trimToNull(request.getDocumentSummary()));
|
||||
entity.setParseStatus(trimToNull(request.getParseStatus()));
|
||||
entity.setIndexStatus(trimToNull(request.getIndexStatus()));
|
||||
entity.setEnabled(request.getEnabled());
|
||||
entity.setErrorMessage(trimToNull(request.getErrorMessage()));
|
||||
entity.setRemark(trimToNull(request.getRemark()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将实体转换为前端使用的返回对象。
|
||||
*/
|
||||
public RagDocumentResponse toResponse(RagDocument entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
RagDocumentResponse response = new RagDocumentResponse();
|
||||
BeanUtils.copyProperties(entity, response);
|
||||
return response;
|
||||
}
|
||||
|
||||
public List<RagDocumentResponse> toResponses(List<RagDocument> entities) {
|
||||
return entities == null ? List.of() : entities.stream().map(this::toResponse).toList();
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.bruce.rag.factory;
|
||||
|
||||
import com.bruce.rag.dto.request.RagStoreSaveRequest;
|
||||
import com.bruce.rag.dto.response.RagStoreResponse;
|
||||
import com.bruce.rag.entity.RagStore;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 知识库工厂,统一负责知识库请求对象、实体对象和返回对象之间的转换。
|
||||
*/
|
||||
@Component
|
||||
public class RagStoreFactory {
|
||||
|
||||
/**
|
||||
* 将保存请求转换为知识库实体,统一处理空白裁剪规则。
|
||||
*/
|
||||
public RagStore toEntity(RagStoreSaveRequest request) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
RagStore entity = new RagStore();
|
||||
entity.setId(request.getId());
|
||||
entity.setStoreCode(trimToNull(request.getStoreCode()));
|
||||
entity.setStoreName(trimToNull(request.getStoreName()));
|
||||
entity.setDescription(trimToNull(request.getDescription()));
|
||||
entity.setStatus(trimToNull(request.getStatus()));
|
||||
entity.setRemark(trimToNull(request.getRemark()));
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将实体转换为返回对象,避免接口层直接暴露实体结构。
|
||||
*/
|
||||
public RagStoreResponse toResponse(RagStore entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
RagStoreResponse response = new RagStoreResponse();
|
||||
BeanUtils.copyProperties(entity, response);
|
||||
return response;
|
||||
}
|
||||
|
||||
public List<RagStoreResponse> toResponses(List<RagStore> entities) {
|
||||
return entities == null ? List.of() : entities.stream().map(this::toResponse).toList();
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.bruce.rag.service;
|
||||
|
||||
import com.bruce.rag.vo.KnowledgeWorkspaceVO;
|
||||
|
||||
/**
|
||||
* 知识工作台聚合服务,对外提供知识资产工作台需要的统一视图。
|
||||
*/
|
||||
public interface IKnowledgeWorkspaceService {
|
||||
|
||||
/**
|
||||
* 按知识库ID聚合知识工作台视图。
|
||||
*/
|
||||
KnowledgeWorkspaceVO getWorkspace(Long storeId);
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.bruce.rag.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.bruce.modelprovider.dto.response.RagStoreModelConfigResponse;
|
||||
import com.bruce.modelprovider.service.IRagStoreModelConfigService;
|
||||
import com.bruce.rag.dto.request.RagDocumentQueryRequest;
|
||||
import com.bruce.rag.dto.response.RagDocumentResponse;
|
||||
import com.bruce.rag.dto.response.RagStoreResponse;
|
||||
import com.bruce.rag.entity.RagChunk;
|
||||
import com.bruce.rag.entity.RagChunkEmbedding;
|
||||
import com.bruce.rag.service.IKnowledgeWorkspaceService;
|
||||
import com.bruce.rag.service.IRagChunkEmbeddingService;
|
||||
import com.bruce.rag.service.IRagChunkService;
|
||||
import com.bruce.rag.service.IRagDocumentService;
|
||||
import com.bruce.rag.service.IRagStoreService;
|
||||
import com.bruce.rag.vo.KnowledgeWorkspaceDocumentVO;
|
||||
import com.bruce.rag.vo.KnowledgeWorkspaceVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 知识工作台聚合服务实现。
|
||||
* <p>
|
||||
* 该服务负责把知识库基础信息、文档状态、模型绑定和索引结果拼成前端工作台可直接消费的聚合视图。
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class KnowledgeWorkspaceServiceImpl implements IKnowledgeWorkspaceService {
|
||||
|
||||
private static final String PARSE_STATUS_PARSED = "PARSED";
|
||||
private static final String PARSE_STATUS_FAILED = "FAILED";
|
||||
private static final String INDEX_STATUS_INDEXED = "INDEXED";
|
||||
private static final String INDEX_STATUS_PENDING = "PENDING";
|
||||
|
||||
private final IRagStoreService ragStoreService;
|
||||
private final IRagDocumentService ragDocumentService;
|
||||
private final IRagChunkService ragChunkService;
|
||||
private final IRagChunkEmbeddingService ragChunkEmbeddingService;
|
||||
private final IRagStoreModelConfigService ragStoreModelConfigService;
|
||||
|
||||
@Override
|
||||
public KnowledgeWorkspaceVO getWorkspace(Long storeId) {
|
||||
log.info("知识工作台查询开始,storeId={}", storeId);
|
||||
if (storeId == null) {
|
||||
throw new IllegalArgumentException("知识库ID不能为空");
|
||||
}
|
||||
|
||||
RagStoreResponse store = ragStoreService.getResponseById(storeId);
|
||||
if (store == null) {
|
||||
throw new IllegalArgumentException("知识库不存在,ID: " + storeId);
|
||||
}
|
||||
|
||||
RagDocumentQueryRequest queryRequest = new RagDocumentQueryRequest();
|
||||
queryRequest.setStoreId(storeId);
|
||||
List<RagDocumentResponse> documents = ragDocumentService.query(queryRequest);
|
||||
RagStoreModelConfigResponse modelConfig = ragStoreModelConfigService.getByStoreId(storeId);
|
||||
|
||||
long chunkCount = ragChunkService.count(new LambdaQueryWrapper<RagChunk>()
|
||||
.eq(RagChunk::getStoreId, storeId)
|
||||
.eq(RagChunk::getEnabled, true));
|
||||
long embeddingCount = ragChunkEmbeddingService.count(new LambdaQueryWrapper<RagChunkEmbedding>()
|
||||
.eq(RagChunkEmbedding::getStoreId, storeId)
|
||||
.eq(RagChunkEmbedding::getEnabled, true));
|
||||
|
||||
KnowledgeWorkspaceVO workspace = new KnowledgeWorkspaceVO();
|
||||
workspace.setStoreId(store.getId());
|
||||
workspace.setStoreCode(store.getStoreCode());
|
||||
workspace.setStoreName(store.getStoreName());
|
||||
workspace.setDescription(store.getDescription());
|
||||
workspace.setStatus(store.getStatus());
|
||||
workspace.setRemark(store.getRemark());
|
||||
workspace.setDocumentCount(documents.size());
|
||||
workspace.setParsedDocumentCount((int) documents.stream().filter(this::isParsed).count());
|
||||
workspace.setParseFailedDocumentCount((int) documents.stream().filter(this::isParseFailed).count());
|
||||
workspace.setIndexedDocumentCount((int) documents.stream().filter(this::isIndexed).count());
|
||||
workspace.setPendingIndexDocumentCount((int) documents.stream().filter(this::isPendingIndex).count());
|
||||
workspace.setHealthScore(calculateHealthScore(documents.size(), workspace.getParseFailedDocumentCount()));
|
||||
workspace.setChunkCount(chunkCount);
|
||||
workspace.setEmbeddingCount(embeddingCount);
|
||||
workspace.setPendingTaskCount(workspace.getPendingIndexDocumentCount());
|
||||
workspace.setPublishImpact("更新后需要重新验证 Workflow / Agent 的知识引用效果");
|
||||
workspace.setDocuments(documents.stream().map(this::toWorkspaceDocument).toList());
|
||||
|
||||
if (modelConfig != null) {
|
||||
workspace.setEmbeddingModelId(modelConfig.getEmbeddingModelId());
|
||||
workspace.setEmbeddingDimension(modelConfig.getEmbeddingDimension());
|
||||
workspace.setChunkStrategy(modelConfig.getChunkStrategy());
|
||||
workspace.setChunkSize(modelConfig.getChunkSize());
|
||||
workspace.setChunkOverlap(modelConfig.getChunkOverlap());
|
||||
workspace.setIndexVersion(modelConfig.getIndexVersion());
|
||||
}
|
||||
|
||||
log.info("知识工作台查询结束,storeId={}, documentCount={}, healthScore={}, pendingTaskCount={}",
|
||||
storeId, workspace.getDocumentCount(), workspace.getHealthScore(), workspace.getPendingTaskCount());
|
||||
return workspace;
|
||||
}
|
||||
|
||||
private KnowledgeWorkspaceDocumentVO toWorkspaceDocument(RagDocumentResponse document) {
|
||||
KnowledgeWorkspaceDocumentVO vo = new KnowledgeWorkspaceDocumentVO();
|
||||
vo.setDocumentId(document.getId());
|
||||
vo.setDocumentTitle(document.getDocumentTitle());
|
||||
vo.setParseStatus(document.getParseStatus());
|
||||
vo.setIndexStatus(document.getIndexStatus());
|
||||
vo.setEnabled(document.getEnabled());
|
||||
vo.setUpdateTime(document.getUpdateTime());
|
||||
return vo;
|
||||
}
|
||||
|
||||
private boolean isParsed(RagDocumentResponse document) {
|
||||
return PARSE_STATUS_PARSED.equals(document.getParseStatus());
|
||||
}
|
||||
|
||||
private boolean isParseFailed(RagDocumentResponse document) {
|
||||
return PARSE_STATUS_FAILED.equals(document.getParseStatus());
|
||||
}
|
||||
|
||||
private boolean isIndexed(RagDocumentResponse document) {
|
||||
return INDEX_STATUS_INDEXED.equals(document.getIndexStatus());
|
||||
}
|
||||
|
||||
private boolean isPendingIndex(RagDocumentResponse document) {
|
||||
return INDEX_STATUS_PENDING.equals(document.getIndexStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 健康度按“非失败文档占比”计算,便于前端快速识别当前知识库是否适合继续发布引用。
|
||||
*/
|
||||
private int calculateHealthScore(int totalDocumentCount, int parseFailedDocumentCount) {
|
||||
if (totalDocumentCount <= 0) {
|
||||
return 100;
|
||||
}
|
||||
int healthyDocumentCount = Math.max(totalDocumentCount - parseFailedDocumentCount, 0);
|
||||
return (int) Math.floor(healthyDocumentCount * 100.0 / totalDocumentCount);
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,12 @@ import com.bruce.rag.dto.response.RagDocumentResponse;
|
||||
import com.bruce.rag.entity.RagDocument;
|
||||
import com.bruce.rag.enums.RagIndexStatusEnum;
|
||||
import com.bruce.rag.enums.RagParseStatusEnum;
|
||||
import com.bruce.rag.factory.RagDocumentFactory;
|
||||
import com.bruce.rag.mapper.RagDocumentMapper;
|
||||
import com.bruce.rag.service.IRagDocumentAutoParseService;
|
||||
import com.bruce.rag.service.IRagDocumentService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -25,18 +26,17 @@ import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RagDocumentServiceImpl extends ServiceImpl<RagDocumentMapper, RagDocument> implements IRagDocumentService {
|
||||
|
||||
@Autowired
|
||||
private ISysAttachmentService sysAttachmentService;
|
||||
|
||||
@Autowired
|
||||
private IRagDocumentAutoParseService ragDocumentAutoParseService;
|
||||
private final ISysAttachmentService sysAttachmentService;
|
||||
private final IRagDocumentAutoParseService ragDocumentAutoParseService;
|
||||
private final RagDocumentFactory ragDocumentFactory;
|
||||
|
||||
@Override
|
||||
public List<RagDocumentResponse> listResponses() {
|
||||
log.info("RagDocumentServiceImpl.listResponses start");
|
||||
List<RagDocumentResponse> responses = toResponses(list());
|
||||
List<RagDocumentResponse> responses = ragDocumentFactory.toResponses(list());
|
||||
log.info("RagDocumentServiceImpl.listResponses success, count={}", responses.size());
|
||||
return responses;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public class RagDocumentServiceImpl extends ServiceImpl<RagDocumentMapper, RagDo
|
||||
RagDocumentQueryRequest queryRequest = request == null ? new RagDocumentQueryRequest() : request;
|
||||
String parseStatus = trimToNull(queryRequest.getParseStatus());
|
||||
String indexStatus = trimToNull(queryRequest.getIndexStatus());
|
||||
List<RagDocumentResponse> responses = toResponses(lambdaQuery()
|
||||
List<RagDocumentResponse> responses = ragDocumentFactory.toResponses(lambdaQuery()
|
||||
.eq(queryRequest.getStoreId() != null, RagDocument::getStoreId, queryRequest.getStoreId())
|
||||
.eq(queryRequest.getAttachmentId() != null, RagDocument::getAttachmentId, queryRequest.getAttachmentId())
|
||||
.eq(parseStatus != null, RagDocument::getParseStatus, parseStatus)
|
||||
@@ -62,7 +62,7 @@ public class RagDocumentServiceImpl extends ServiceImpl<RagDocumentMapper, RagDo
|
||||
@Override
|
||||
public RagDocumentResponse getResponseById(Long id) {
|
||||
log.info("RagDocumentServiceImpl.getResponseById start, id={}", id);
|
||||
RagDocumentResponse response = RagDocumentResponse.fromEntity(getById(id));
|
||||
RagDocumentResponse response = ragDocumentFactory.toResponse(getById(id));
|
||||
log.info("RagDocumentServiceImpl.getResponseById success, id={}, found={}", id, response != null);
|
||||
return response;
|
||||
}
|
||||
@@ -85,34 +85,7 @@ public class RagDocumentServiceImpl extends ServiceImpl<RagDocumentMapper, RagDo
|
||||
document.setParseStatus(RagParseStatusEnum.UPLOADED.name());
|
||||
document.setIndexStatus(RagIndexStatusEnum.PENDING.name());
|
||||
}
|
||||
|
||||
if (request.getStoreId() != null) {
|
||||
document.setStoreId(request.getStoreId());
|
||||
}
|
||||
if (request.getAttachmentId() != null) {
|
||||
document.setAttachmentId(request.getAttachmentId());
|
||||
}
|
||||
if (StringUtils.hasText(request.getDocumentTitle())) {
|
||||
document.setDocumentTitle(request.getDocumentTitle().trim());
|
||||
}
|
||||
if (request.getDocumentSummary() != null) {
|
||||
document.setDocumentSummary(trimToNull(request.getDocumentSummary()));
|
||||
}
|
||||
if (StringUtils.hasText(request.getParseStatus())) {
|
||||
document.setParseStatus(request.getParseStatus().trim());
|
||||
}
|
||||
if (StringUtils.hasText(request.getIndexStatus())) {
|
||||
document.setIndexStatus(request.getIndexStatus().trim());
|
||||
}
|
||||
if (request.getEnabled() != null) {
|
||||
document.setEnabled(request.getEnabled());
|
||||
}
|
||||
if (request.getErrorMessage() != null) {
|
||||
document.setErrorMessage(trimToNull(request.getErrorMessage()));
|
||||
}
|
||||
if (request.getRemark() != null) {
|
||||
document.setRemark(trimToNull(request.getRemark()));
|
||||
}
|
||||
applyRequestToDocument(document, request);
|
||||
|
||||
boolean result = request.getId() == null ? save(document) : updateById(document);
|
||||
log.info("RagDocumentServiceImpl.saveOrUpdate success, requestId={}, savedId={}, result={}",
|
||||
@@ -167,7 +140,7 @@ public class RagDocumentServiceImpl extends ServiceImpl<RagDocumentMapper, RagDo
|
||||
document.setRemark(trimToNull(request.getRemark()));
|
||||
|
||||
save(document);
|
||||
results.add(RagDocumentResponse.fromEntity(document));
|
||||
results.add(ragDocumentFactory.toResponse(document));
|
||||
}
|
||||
|
||||
if (!results.isEmpty()) {
|
||||
@@ -211,10 +184,37 @@ public class RagDocumentServiceImpl extends ServiceImpl<RagDocumentMapper, RagDo
|
||||
}
|
||||
}
|
||||
|
||||
private List<RagDocumentResponse> toResponses(List<RagDocument> documents) {
|
||||
return documents.stream()
|
||||
.map(RagDocumentResponse::fromEntity)
|
||||
.toList();
|
||||
/**
|
||||
* 更新场景下需要保留旧值,因此这里仅覆盖请求中明确传入的字段。
|
||||
*/
|
||||
private void applyRequestToDocument(RagDocument document, RagDocumentSaveRequest request) {
|
||||
if (request.getStoreId() != null) {
|
||||
document.setStoreId(request.getStoreId());
|
||||
}
|
||||
if (request.getAttachmentId() != null) {
|
||||
document.setAttachmentId(request.getAttachmentId());
|
||||
}
|
||||
if (StringUtils.hasText(request.getDocumentTitle())) {
|
||||
document.setDocumentTitle(trimToNull(request.getDocumentTitle()));
|
||||
}
|
||||
if (request.getDocumentSummary() != null) {
|
||||
document.setDocumentSummary(trimToNull(request.getDocumentSummary()));
|
||||
}
|
||||
if (StringUtils.hasText(request.getParseStatus())) {
|
||||
document.setParseStatus(trimToNull(request.getParseStatus()));
|
||||
}
|
||||
if (StringUtils.hasText(request.getIndexStatus())) {
|
||||
document.setIndexStatus(trimToNull(request.getIndexStatus()));
|
||||
}
|
||||
if (request.getEnabled() != null) {
|
||||
document.setEnabled(request.getEnabled());
|
||||
}
|
||||
if (request.getErrorMessage() != null) {
|
||||
document.setErrorMessage(trimToNull(request.getErrorMessage()));
|
||||
}
|
||||
if (request.getRemark() != null) {
|
||||
document.setRemark(trimToNull(request.getRemark()));
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveSourceType(String sourceType) {
|
||||
|
||||
@@ -12,11 +12,12 @@ import com.bruce.rag.dto.response.RagStoreResponse;
|
||||
import com.bruce.rag.entity.RagStore;
|
||||
import com.bruce.rag.enums.RagIndexStatusEnum;
|
||||
import com.bruce.rag.enums.RagParseStatusEnum;
|
||||
import com.bruce.rag.factory.RagStoreFactory;
|
||||
import com.bruce.rag.mapper.RagStoreMapper;
|
||||
import com.bruce.rag.service.IRagDocumentService;
|
||||
import com.bruce.rag.service.IRagStoreService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -26,15 +27,16 @@ import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RagStoreServiceImpl extends ServiceImpl<RagStoreMapper, RagStore> implements IRagStoreService {
|
||||
|
||||
@Autowired
|
||||
private IRagDocumentService ragDocumentService;
|
||||
private final IRagDocumentService ragDocumentService;
|
||||
private final RagStoreFactory ragStoreFactory;
|
||||
|
||||
@Override
|
||||
public List<RagStoreResponse> listResponses() {
|
||||
log.info("RagStoreServiceImpl.listResponses start");
|
||||
List<RagStoreResponse> responses = toResponses(list());
|
||||
List<RagStoreResponse> responses = ragStoreFactory.toResponses(list());
|
||||
log.info("RagStoreServiceImpl.listResponses success, count={}", responses.size());
|
||||
return responses;
|
||||
}
|
||||
@@ -43,7 +45,7 @@ public class RagStoreServiceImpl extends ServiceImpl<RagStoreMapper, RagStore> i
|
||||
public List<RagStoreResponse> query(RagStoreQueryRequest request) {
|
||||
log.info("RagStoreServiceImpl.query start, request={}", request);
|
||||
RagStoreQueryRequest queryRequest = request == null ? new RagStoreQueryRequest() : request;
|
||||
List<RagStoreResponse> responses = toResponses(lambdaQuery()
|
||||
List<RagStoreResponse> responses = ragStoreFactory.toResponses(lambdaQuery()
|
||||
.eq(StringUtils.hasText(queryRequest.getStoreCode()), RagStore::getStoreCode, queryRequest.getStoreCode())
|
||||
.like(StringUtils.hasText(queryRequest.getStoreName()), RagStore::getStoreName, queryRequest.getStoreName())
|
||||
.eq(StringUtils.hasText(queryRequest.getStatus()), RagStore::getStatus, queryRequest.getStatus())
|
||||
@@ -56,7 +58,7 @@ public class RagStoreServiceImpl extends ServiceImpl<RagStoreMapper, RagStore> i
|
||||
@Override
|
||||
public RagStoreResponse getResponseById(Long id) {
|
||||
log.info("RagStoreServiceImpl.getResponseById start, id={}", id);
|
||||
RagStoreResponse response = RagStoreResponse.fromEntity(getById(id));
|
||||
RagStoreResponse response = ragStoreFactory.toResponse(getById(id));
|
||||
log.info("RagStoreServiceImpl.getResponseById success, id={}, found={}", id, response != null);
|
||||
return response;
|
||||
}
|
||||
@@ -132,7 +134,10 @@ public class RagStoreServiceImpl extends ServiceImpl<RagStoreMapper, RagStore> i
|
||||
throw new IllegalArgumentException("知识库编码已存在: " + request.getStoreCode().trim());
|
||||
}
|
||||
|
||||
RagStore ragStore = buildEntity(request);
|
||||
RagStore ragStore = ragStoreFactory.toEntity(request);
|
||||
if (!StringUtils.hasText(ragStore.getStatus())) {
|
||||
ragStore.setStatus(EnableStatusEnum.ENABLED.getLabel());
|
||||
}
|
||||
boolean result = super.saveOrUpdate(ragStore);
|
||||
log.info("RagStoreServiceImpl.saveOrUpdate success, requestId={}, savedId={}, storeCode={}, result={}",
|
||||
request.getId(), ragStore.getId(), ragStore.getStoreCode(), result);
|
||||
@@ -154,29 +159,4 @@ public class RagStoreServiceImpl extends ServiceImpl<RagStoreMapper, RagStore> i
|
||||
request.getId(), request.getStoreCode(), request.getStoreName());
|
||||
}
|
||||
|
||||
public RagStore buildEntity(RagStoreSaveRequest request) {
|
||||
RagStore ragStore = new RagStore();
|
||||
ragStore.setId(request.getId());
|
||||
ragStore.setStoreCode(request.getStoreCode().trim());
|
||||
ragStore.setStoreName(request.getStoreName().trim());
|
||||
ragStore.setDescription(trimToNull(request.getDescription()));
|
||||
ragStore.setStatus(StringUtils.hasText(request.getStatus())
|
||||
? request.getStatus().trim()
|
||||
: EnableStatusEnum.ENABLED.getLabel());
|
||||
ragStore.setRemark(trimToNull(request.getRemark()));
|
||||
return ragStore;
|
||||
}
|
||||
|
||||
private List<RagStoreResponse> toResponses(List<RagStore> stores) {
|
||||
return stores.stream()
|
||||
.map(RagStoreResponse::fromEntity)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.bruce.rag.vo;
|
||||
|
||||
import com.bruce.common.constant.CommonConsts;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 知识工作台中的文档摘要视图。
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "知识工作台文档摘要")
|
||||
public class KnowledgeWorkspaceDocumentVO {
|
||||
|
||||
@Schema(description = "文档ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long documentId;
|
||||
|
||||
@Schema(description = "文档标题")
|
||||
private String documentTitle;
|
||||
|
||||
@Schema(description = "解析状态")
|
||||
private String parseStatus;
|
||||
|
||||
@Schema(description = "索引状态")
|
||||
private String indexStatus;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "最近更新时间")
|
||||
@JsonFormat(pattern = CommonConsts.DATE_FORMAT_LONG_STR, timezone = CommonConsts.TIME_ZONE_GMT8)
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.bruce.rag.vo;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 知识工作台聚合视图,供前端知识资产工作台直接消费。
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "知识工作台聚合视图")
|
||||
public class KnowledgeWorkspaceVO {
|
||||
|
||||
@Schema(description = "知识库ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long storeId;
|
||||
|
||||
@Schema(description = "知识库编码")
|
||||
private String storeCode;
|
||||
|
||||
@Schema(description = "知识库名称")
|
||||
private String storeName;
|
||||
|
||||
@Schema(description = "知识库描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "知识库状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "文档总数")
|
||||
private Integer documentCount;
|
||||
|
||||
@Schema(description = "已解析文档数")
|
||||
private Integer parsedDocumentCount;
|
||||
|
||||
@Schema(description = "解析失败文档数")
|
||||
private Integer parseFailedDocumentCount;
|
||||
|
||||
@Schema(description = "已索引文档数")
|
||||
private Integer indexedDocumentCount;
|
||||
|
||||
@Schema(description = "待索引文档数")
|
||||
private Integer pendingIndexDocumentCount;
|
||||
|
||||
@Schema(description = "健康度百分比")
|
||||
private Integer healthScore;
|
||||
|
||||
@Schema(description = "Embedding 模型ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long embeddingModelId;
|
||||
|
||||
@Schema(description = "Embedding 维度")
|
||||
private Integer embeddingDimension;
|
||||
|
||||
@Schema(description = "切片策略")
|
||||
private Integer chunkStrategy;
|
||||
|
||||
@Schema(description = "切片长度")
|
||||
private Integer chunkSize;
|
||||
|
||||
@Schema(description = "切片重叠长度")
|
||||
private Integer chunkOverlap;
|
||||
|
||||
@Schema(description = "索引版本")
|
||||
private Integer indexVersion;
|
||||
|
||||
@Schema(description = "切片总数")
|
||||
private Long chunkCount;
|
||||
|
||||
@Schema(description = "向量总数")
|
||||
private Long embeddingCount;
|
||||
|
||||
@Schema(description = "待处理任务数")
|
||||
private Integer pendingTaskCount;
|
||||
|
||||
@Schema(description = "发布影响提示")
|
||||
private String publishImpact;
|
||||
|
||||
@Schema(description = "文档摘要列表")
|
||||
private List<KnowledgeWorkspaceDocumentVO> documents = new ArrayList<>();
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.bruce.rag.dto.request.RagDocumentSaveRequest;
|
||||
import com.bruce.rag.entity.RagDocument;
|
||||
import com.bruce.rag.enums.RagIndexStatusEnum;
|
||||
import com.bruce.rag.enums.RagParseStatusEnum;
|
||||
import com.bruce.rag.factory.RagDocumentFactory;
|
||||
import com.bruce.rag.service.IRagDocumentAutoParseService;
|
||||
import com.bruce.rag.service.impl.RagDocumentServiceImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -42,6 +43,9 @@ class RagDocumentServiceImplTests {
|
||||
@Mock
|
||||
private IRagDocumentAutoParseService ragDocumentAutoParseService;
|
||||
|
||||
@Spy
|
||||
private RagDocumentFactory ragDocumentFactory;
|
||||
|
||||
@Test
|
||||
void batchUploadShouldUseRagSourceTypeAndStoreIdAsSourceId() {
|
||||
MockMultipartFile file = new MockMultipartFile(
|
||||
|
||||
@@ -3,8 +3,11 @@ package com.bruce.rag;
|
||||
import com.bruce.common.enums.EnableStatusEnum;
|
||||
import com.bruce.rag.dto.request.RagStoreSaveRequest;
|
||||
import com.bruce.rag.entity.RagStore;
|
||||
import com.bruce.rag.factory.RagStoreFactory;
|
||||
import com.bruce.rag.service.IRagDocumentService;
|
||||
import com.bruce.rag.service.impl.RagStoreServiceImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -12,9 +15,12 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class RagStoreSaveValidationTests {
|
||||
|
||||
private final IRagDocumentService ragDocumentService = Mockito.mock(IRagDocumentService.class);
|
||||
private final RagStoreFactory ragStoreFactory = new RagStoreFactory();
|
||||
|
||||
@Test
|
||||
void saveShouldRejectBlankStoreCode() {
|
||||
RagStoreServiceImpl service = new RagStoreServiceImpl();
|
||||
RagStoreServiceImpl service = new RagStoreServiceImpl(ragDocumentService, ragStoreFactory);
|
||||
RagStoreSaveRequest request = new RagStoreSaveRequest();
|
||||
request.setStoreName("产品制度库");
|
||||
|
||||
@@ -23,7 +29,7 @@ class RagStoreSaveValidationTests {
|
||||
|
||||
@Test
|
||||
void saveShouldRejectBlankStoreName() {
|
||||
RagStoreServiceImpl service = new RagStoreServiceImpl();
|
||||
RagStoreServiceImpl service = new RagStoreServiceImpl(ragDocumentService, ragStoreFactory);
|
||||
RagStoreSaveRequest request = new RagStoreSaveRequest();
|
||||
request.setStoreCode("PROD_DOC");
|
||||
|
||||
@@ -32,7 +38,7 @@ class RagStoreSaveValidationTests {
|
||||
|
||||
@Test
|
||||
void saveShouldAcceptMinimalValidRequest() {
|
||||
RagStoreServiceImpl service = new RagStoreServiceImpl();
|
||||
RagStoreServiceImpl service = new RagStoreServiceImpl(ragDocumentService, ragStoreFactory);
|
||||
RagStoreSaveRequest request = new RagStoreSaveRequest();
|
||||
request.setStoreCode("PROD_DOC");
|
||||
request.setStoreName("产品制度库");
|
||||
@@ -42,12 +48,14 @@ class RagStoreSaveValidationTests {
|
||||
|
||||
@Test
|
||||
void saveShouldDefaultStatusToEnabledEnumLabel() {
|
||||
RagStoreServiceImpl service = new RagStoreServiceImpl();
|
||||
RagStoreSaveRequest request = new RagStoreSaveRequest();
|
||||
request.setStoreCode("PROD_DOC");
|
||||
request.setStoreName("产品制度库");
|
||||
|
||||
RagStore ragStore = service.buildEntity(request);
|
||||
RagStore ragStore = ragStoreFactory.toEntity(request);
|
||||
if (ragStore.getStatus() == null) {
|
||||
ragStore.setStatus(EnableStatusEnum.ENABLED.getLabel());
|
||||
}
|
||||
|
||||
assertEquals(EnableStatusEnum.ENABLED.getLabel(), ragStore.getStatus());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.bruce.rag.factory;
|
||||
|
||||
import com.bruce.rag.dto.request.RagDocumentSaveRequest;
|
||||
import com.bruce.rag.dto.request.RagStoreSaveRequest;
|
||||
import com.bruce.rag.dto.response.RagDocumentResponse;
|
||||
import com.bruce.rag.dto.response.RagStoreResponse;
|
||||
import com.bruce.rag.entity.RagDocument;
|
||||
import com.bruce.rag.entity.RagStore;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
class RagFactoryTests {
|
||||
|
||||
private final RagStoreFactory ragStoreFactory = new RagStoreFactory();
|
||||
private final RagDocumentFactory ragDocumentFactory = new RagDocumentFactory();
|
||||
|
||||
@Test
|
||||
void ragStoreFactoryShouldTrimAndBuildEntity() {
|
||||
RagStoreSaveRequest request = new RagStoreSaveRequest();
|
||||
request.setId(1001L);
|
||||
request.setStoreCode(" PROD_DOC ");
|
||||
request.setStoreName(" 产品制度库 ");
|
||||
request.setDescription(" 产品制度、业务规范、流程材料 ");
|
||||
request.setStatus(" 启用 ");
|
||||
request.setRemark(" 核心制度库 ");
|
||||
|
||||
RagStore entity = ragStoreFactory.toEntity(request);
|
||||
|
||||
assertNotNull(entity);
|
||||
assertEquals(1001L, entity.getId());
|
||||
assertEquals("PROD_DOC", entity.getStoreCode());
|
||||
assertEquals("产品制度库", entity.getStoreName());
|
||||
assertEquals("产品制度、业务规范、流程材料", entity.getDescription());
|
||||
assertEquals("启用", entity.getStatus());
|
||||
assertEquals("核心制度库", entity.getRemark());
|
||||
}
|
||||
|
||||
@Test
|
||||
void ragStoreFactoryShouldConvertEntityToResponse() {
|
||||
RagStore entity = new RagStore();
|
||||
entity.setId(1001L);
|
||||
entity.setStoreCode("PROD_DOC");
|
||||
entity.setStoreName("产品制度库");
|
||||
entity.setDescription("产品制度、业务规范、流程材料");
|
||||
entity.setStatus("启用");
|
||||
entity.setRemark("核心制度库");
|
||||
entity.setCreateTime(new Date(1747816496000L));
|
||||
entity.setUpdateTime(new Date(1747820096000L));
|
||||
|
||||
RagStoreResponse response = ragStoreFactory.toResponse(entity);
|
||||
|
||||
assertNotNull(response);
|
||||
assertEquals(1001L, response.getId());
|
||||
assertEquals("PROD_DOC", response.getStoreCode());
|
||||
assertEquals("产品制度库", response.getStoreName());
|
||||
assertEquals("产品制度、业务规范、流程材料", response.getDescription());
|
||||
assertEquals("启用", response.getStatus());
|
||||
assertEquals("核心制度库", response.getRemark());
|
||||
assertEquals(new Date(1747816496000L), response.getCreateTime());
|
||||
assertEquals(new Date(1747820096000L), response.getUpdateTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
void ragDocumentFactoryShouldApplyEditableFieldsToEntity() {
|
||||
RagDocumentSaveRequest request = new RagDocumentSaveRequest();
|
||||
request.setId(3003L);
|
||||
request.setStoreId(1001L);
|
||||
request.setAttachmentId(2002L);
|
||||
request.setDocumentTitle(" 新标题 ");
|
||||
request.setDocumentSummary(" 新摘要 ");
|
||||
request.setParseStatus(" PARSED ");
|
||||
request.setIndexStatus(" INDEXED ");
|
||||
request.setEnabled(false);
|
||||
request.setErrorMessage(" 已修复 ");
|
||||
request.setRemark(" 备注信息 ");
|
||||
|
||||
RagDocument entity = ragDocumentFactory.toEntity(request);
|
||||
|
||||
assertNotNull(entity);
|
||||
assertEquals(3003L, entity.getId());
|
||||
assertEquals(1001L, entity.getStoreId());
|
||||
assertEquals(2002L, entity.getAttachmentId());
|
||||
assertEquals("新标题", entity.getDocumentTitle());
|
||||
assertEquals("新摘要", entity.getDocumentSummary());
|
||||
assertEquals("PARSED", entity.getParseStatus());
|
||||
assertEquals("INDEXED", entity.getIndexStatus());
|
||||
assertEquals(false, entity.getEnabled());
|
||||
assertEquals("已修复", entity.getErrorMessage());
|
||||
assertEquals("备注信息", entity.getRemark());
|
||||
}
|
||||
|
||||
@Test
|
||||
void ragDocumentFactoryShouldConvertEntityToResponse() {
|
||||
RagDocument entity = new RagDocument();
|
||||
entity.setId(3003L);
|
||||
entity.setStoreId(1001L);
|
||||
entity.setAttachmentId(2002L);
|
||||
entity.setDocumentTitle("people_profiles.txt");
|
||||
entity.setDocumentSummary("测试人员信息");
|
||||
entity.setParseStatus("PARSED");
|
||||
entity.setIndexStatus("INDEXED");
|
||||
entity.setEnabled(true);
|
||||
entity.setErrorMessage(null);
|
||||
entity.setRemark("测试文档");
|
||||
entity.setCreateTime(new Date(1747816496000L));
|
||||
entity.setUpdateTime(new Date(1747820096000L));
|
||||
|
||||
RagDocumentResponse response = ragDocumentFactory.toResponse(entity);
|
||||
|
||||
assertNotNull(response);
|
||||
assertEquals(3003L, response.getId());
|
||||
assertEquals(1001L, response.getStoreId());
|
||||
assertEquals(2002L, response.getAttachmentId());
|
||||
assertEquals("people_profiles.txt", response.getDocumentTitle());
|
||||
assertEquals("测试人员信息", response.getDocumentSummary());
|
||||
assertEquals("PARSED", response.getParseStatus());
|
||||
assertEquals("INDEXED", response.getIndexStatus());
|
||||
assertEquals(true, response.getEnabled());
|
||||
assertNull(response.getErrorMessage());
|
||||
assertEquals("测试文档", response.getRemark());
|
||||
assertEquals(new Date(1747816496000L), response.getCreateTime());
|
||||
assertEquals(new Date(1747820096000L), response.getUpdateTime());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.bruce.rag.workspace;
|
||||
|
||||
import com.bruce.modelprovider.dto.response.RagStoreModelConfigResponse;
|
||||
import com.bruce.modelprovider.service.IRagStoreModelConfigService;
|
||||
import com.bruce.rag.dto.response.RagDocumentResponse;
|
||||
import com.bruce.rag.dto.response.RagStoreResponse;
|
||||
import com.bruce.rag.service.IRagChunkEmbeddingService;
|
||||
import com.bruce.rag.service.IRagChunkService;
|
||||
import com.bruce.rag.service.IRagDocumentParseResultService;
|
||||
import com.bruce.rag.service.IRagDocumentService;
|
||||
import com.bruce.rag.service.impl.KnowledgeWorkspaceServiceImpl;
|
||||
import com.bruce.rag.vo.KnowledgeWorkspaceVO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class KnowledgeWorkspaceServiceTests {
|
||||
|
||||
@Mock
|
||||
private com.bruce.rag.service.IRagStoreService ragStoreService;
|
||||
|
||||
@Mock
|
||||
private IRagDocumentService ragDocumentService;
|
||||
|
||||
@Mock
|
||||
private IRagDocumentParseResultService ragDocumentParseResultService;
|
||||
|
||||
@Mock
|
||||
private IRagChunkService ragChunkService;
|
||||
|
||||
@Mock
|
||||
private IRagChunkEmbeddingService ragChunkEmbeddingService;
|
||||
|
||||
@Mock
|
||||
private IRagStoreModelConfigService ragStoreModelConfigService;
|
||||
|
||||
@InjectMocks
|
||||
private KnowledgeWorkspaceServiceImpl knowledgeWorkspaceService;
|
||||
|
||||
@Test
|
||||
void getWorkspaceShouldAggregateStoreConfigAndDocumentHealth() {
|
||||
RagStoreResponse store = new RagStoreResponse();
|
||||
store.setId(1001L);
|
||||
store.setStoreCode("PROD_DOC");
|
||||
store.setStoreName("产品制度库");
|
||||
store.setDescription("产品制度、业务规范、流程材料");
|
||||
store.setStatus("启用");
|
||||
store.setRemark("核心制度库");
|
||||
|
||||
RagDocumentResponse parsedIndexedDocument = createDocument(11L, true, "PARSED", "INDEXED", new Date(1747816496000L));
|
||||
RagDocumentResponse parseFailedDocument = createDocument(12L, true, "FAILED", "FAILED", new Date(1747820096000L));
|
||||
RagDocumentResponse pendingIndexDocument = createDocument(13L, true, "PARSED", "PENDING", new Date(1747823696000L));
|
||||
|
||||
RagStoreModelConfigResponse modelConfig = new RagStoreModelConfigResponse();
|
||||
modelConfig.setStoreId(1001L);
|
||||
modelConfig.setEmbeddingModelId(88L);
|
||||
modelConfig.setEmbeddingDimension(1024);
|
||||
modelConfig.setChunkStrategy(1);
|
||||
modelConfig.setChunkSize(800);
|
||||
modelConfig.setChunkOverlap(120);
|
||||
modelConfig.setIndexVersion(14);
|
||||
|
||||
when(ragStoreService.getResponseById(1001L)).thenReturn(store);
|
||||
when(ragDocumentService.query(org.mockito.ArgumentMatchers.any())).thenReturn(List.of(
|
||||
parsedIndexedDocument,
|
||||
parseFailedDocument,
|
||||
pendingIndexDocument
|
||||
));
|
||||
when(ragStoreModelConfigService.getByStoreId(1001L)).thenReturn(modelConfig);
|
||||
when(ragChunkService.count(org.mockito.ArgumentMatchers.any())).thenReturn(24L);
|
||||
when(ragChunkEmbeddingService.count(org.mockito.ArgumentMatchers.any())).thenReturn(18L);
|
||||
|
||||
KnowledgeWorkspaceVO workspace = knowledgeWorkspaceService.getWorkspace(1001L);
|
||||
|
||||
assertNotNull(workspace);
|
||||
assertEquals(1001L, workspace.getStoreId());
|
||||
assertEquals("PROD_DOC", workspace.getStoreCode());
|
||||
assertEquals("产品制度库", workspace.getStoreName());
|
||||
assertEquals("启用", workspace.getStatus());
|
||||
assertEquals(3, workspace.getDocumentCount());
|
||||
assertEquals(2, workspace.getParsedDocumentCount());
|
||||
assertEquals(1, workspace.getParseFailedDocumentCount());
|
||||
assertEquals(1, workspace.getIndexedDocumentCount());
|
||||
assertEquals(1, workspace.getPendingIndexDocumentCount());
|
||||
assertEquals(66, workspace.getHealthScore());
|
||||
assertEquals(88L, workspace.getEmbeddingModelId());
|
||||
assertEquals(1024, workspace.getEmbeddingDimension());
|
||||
assertEquals(1, workspace.getChunkStrategy());
|
||||
assertEquals(800, workspace.getChunkSize());
|
||||
assertEquals(120, workspace.getChunkOverlap());
|
||||
assertEquals(14, workspace.getIndexVersion());
|
||||
assertEquals(24L, workspace.getChunkCount());
|
||||
assertEquals(18L, workspace.getEmbeddingCount());
|
||||
assertEquals(1, workspace.getPendingTaskCount());
|
||||
assertEquals("更新后需要重新验证 Workflow / Agent 的知识引用效果", workspace.getPublishImpact());
|
||||
assertEquals(3, workspace.getDocuments().size());
|
||||
}
|
||||
|
||||
private RagDocumentResponse createDocument(Long id, boolean enabled, String parseStatus, String indexStatus, Date updateTime) {
|
||||
RagDocumentResponse response = new RagDocumentResponse();
|
||||
response.setId(id);
|
||||
response.setStoreId(1001L);
|
||||
response.setEnabled(enabled);
|
||||
response.setParseStatus(parseStatus);
|
||||
response.setIndexStatus(indexStatus);
|
||||
response.setDocumentTitle("文档-" + id);
|
||||
response.setUpdateTime(updateTime);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user