feat: 异步同步知识库分块检索索引
This commit is contained in:
@@ -1,10 +1,6 @@
|
||||
package tech.easyflow.publicapi.controller;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import com.easyagents.core.model.embedding.EmbeddingModel;
|
||||
import com.easyagents.core.store.DocumentStore;
|
||||
import com.easyagents.core.store.StoreOptions;
|
||||
import com.easyagents.core.store.StoreResult;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -18,11 +14,15 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import tech.easyflow.ai.documentimport.DocumentImportDtos;
|
||||
import tech.easyflow.ai.dto.DocumentChunkDeleteResult;
|
||||
import tech.easyflow.ai.dto.DocumentChunkAsyncUpdateResult;
|
||||
import tech.easyflow.ai.dto.DocumentChunkSyncRetryRequest;
|
||||
import tech.easyflow.ai.dto.DocumentChunkSyncStatus;
|
||||
import tech.easyflow.ai.dto.DocumentChunkSyncStatusRequest;
|
||||
import tech.easyflow.ai.entity.Document;
|
||||
import tech.easyflow.ai.entity.DocumentChunk;
|
||||
import tech.easyflow.ai.entity.DocumentCollection;
|
||||
import tech.easyflow.ai.entity.FaqItem;
|
||||
import tech.easyflow.ai.entity.Model;
|
||||
import tech.easyflow.ai.enums.KnowledgeApiPermissionScope;
|
||||
import tech.easyflow.ai.rag.KnowledgeRetrievalModes;
|
||||
import tech.easyflow.ai.rag.KnowledgeRetrievalRequest;
|
||||
@@ -33,9 +33,7 @@ import tech.easyflow.ai.service.FaqCategoryService;
|
||||
import tech.easyflow.ai.service.FaqItemService;
|
||||
import tech.easyflow.ai.service.KnowledgeShareAuditService;
|
||||
import tech.easyflow.ai.service.KnowledgeSharePermissionService;
|
||||
import tech.easyflow.ai.service.ModelService;
|
||||
import tech.easyflow.ai.service.impl.KnowledgeSharePermissionServiceImpl;
|
||||
import tech.easyflow.ai.support.DocumentStoreLifecycleSupport;
|
||||
import tech.easyflow.ai.vo.FaqImportResultVo;
|
||||
import tech.easyflow.common.domain.Result;
|
||||
import tech.easyflow.common.filestorage.FileStorageService;
|
||||
@@ -81,8 +79,6 @@ public class PublicKnowledgeShareController {
|
||||
private FaqItemService faqItemService;
|
||||
@Resource
|
||||
private FaqCategoryService faqCategoryService;
|
||||
@Resource
|
||||
private ModelService modelService;
|
||||
@Resource(name = "default")
|
||||
private FileStorageService fileStorageService;
|
||||
|
||||
@@ -351,37 +347,20 @@ public class PublicKnowledgeShareController {
|
||||
public Result<?> updateDocumentChunk(
|
||||
@RequestHeader("ApiKey") String apiKey,
|
||||
@JsonBody(value = "knowledgeId", required = true) BigInteger knowledgeId,
|
||||
@JsonBody DocumentChunk documentChunk,
|
||||
@JsonBody(required = true, skipConvertError = false)
|
||||
DocumentChunk documentChunk,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
assertApiShare(apiKey, request.getRequestURI(), knowledgeId, KnowledgeApiPermissionScope.KNOWLEDGE_MAINTENANCE.name());
|
||||
requireDocumentKnowledge(knowledgeId);
|
||||
DocumentChunk current = requireDocumentChunk(documentChunk.getId(), knowledgeId);
|
||||
boolean success = documentChunkService.updateById(documentChunk);
|
||||
if (success) {
|
||||
DocumentCollection knowledge = documentCollectionService.getById(knowledgeId);
|
||||
DocumentStore documentStore = knowledge.toDocumentStore();
|
||||
if (documentStore == null) {
|
||||
return Result.fail(2, "知识库没有配置向量库");
|
||||
}
|
||||
try {
|
||||
Model model = modelService.getModelInstance(knowledge.getVectorEmbedModelId());
|
||||
if (model == null) {
|
||||
return Result.fail(3, "知识库没有配置向量模型");
|
||||
}
|
||||
EmbeddingModel embeddingModel = model.toEmbeddingModel();
|
||||
documentStore.setEmbeddingModel(embeddingModel);
|
||||
StoreOptions options = StoreOptions.ofCollectionName(knowledge.getVectorStoreCollection());
|
||||
com.easyagents.core.document.Document doc = com.easyagents.core.document.Document.of(documentChunk.getContent());
|
||||
doc.setId(current.getId());
|
||||
StoreResult result = documentStore.update(doc, options);
|
||||
audit(apiKey, "API更新文档 Chunk", "KNOWLEDGE_API_SHARE_WRITE", request.getRequestURI(), Map.of("knowledgeId", knowledgeId, "chunkId", documentChunk.getId()));
|
||||
return Result.ok(result);
|
||||
} finally {
|
||||
DocumentStoreLifecycleSupport.closeQuietly(documentStore);
|
||||
}
|
||||
}
|
||||
return Result.ok(false);
|
||||
DocumentChunk updated = documentChunkService.updateContent(
|
||||
knowledgeId,
|
||||
current.getId(),
|
||||
documentChunk.getContent()
|
||||
);
|
||||
audit(apiKey, "API更新文档 Chunk", "KNOWLEDGE_API_SHARE_WRITE", request.getRequestURI(), Map.of("knowledgeId", knowledgeId, "chunkId", documentChunk.getId()));
|
||||
return Result.ok(DocumentChunkAsyncUpdateResult.from(updated));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,25 +376,51 @@ public class PublicKnowledgeShareController {
|
||||
assertApiShare(apiKey, request.getRequestURI(), knowledgeId, KnowledgeApiPermissionScope.KNOWLEDGE_MAINTENANCE.name());
|
||||
requireDocumentKnowledge(knowledgeId);
|
||||
requireDocumentChunk(chunkId, knowledgeId);
|
||||
DocumentCollection knowledge = documentCollectionService.getById(knowledgeId);
|
||||
DocumentStore documentStore = knowledge.toDocumentStore();
|
||||
if (documentStore == null) {
|
||||
return Result.fail(2, "知识库没有配置向量库");
|
||||
}
|
||||
try {
|
||||
Model model = modelService.getModelInstance(knowledge.getVectorEmbedModelId());
|
||||
if (model == null) {
|
||||
return Result.fail(3, "知识库没有配置向量模型");
|
||||
}
|
||||
documentStore.setEmbeddingModel(model.toEmbeddingModel());
|
||||
StoreOptions options = StoreOptions.ofCollectionName(knowledge.getVectorStoreCollection());
|
||||
documentStore.delete(Collections.singletonList(chunkId), options);
|
||||
documentChunkService.removeById(chunkId);
|
||||
audit(apiKey, "API删除文档 Chunk", "KNOWLEDGE_API_SHARE_WRITE", request.getRequestURI(), Map.of("knowledgeId", knowledgeId, "chunkId", chunkId));
|
||||
return Result.ok(true);
|
||||
} finally {
|
||||
DocumentStoreLifecycleSupport.closeQuietly(documentStore);
|
||||
DocumentChunkDeleteResult removed = documentChunkService.deleteChunk(
|
||||
knowledgeId,
|
||||
chunkId
|
||||
);
|
||||
audit(apiKey, "API删除文档 Chunk", "KNOWLEDGE_API_SHARE_WRITE", request.getRequestURI(), Map.of("knowledgeId", knowledgeId, "chunkId", chunkId));
|
||||
return Result.ok(removed != null);
|
||||
}
|
||||
|
||||
@PostMapping("/documentChunk/syncStatus")
|
||||
public Result<List<DocumentChunkSyncStatus>> documentChunkSyncStatus(
|
||||
@RequestHeader("ApiKey") String apiKey,
|
||||
@JsonBody(value = "knowledgeId", required = true) BigInteger knowledgeId,
|
||||
@JsonBody(required = true, skipConvertError = false)
|
||||
DocumentChunkSyncStatusRequest statusRequest,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
assertApiShare(apiKey, request.getRequestURI(), knowledgeId,
|
||||
KnowledgeApiPermissionScope.KNOWLEDGE_READ.name());
|
||||
requireDocumentKnowledge(knowledgeId);
|
||||
requireDocument(statusRequest.getDocumentId(), knowledgeId);
|
||||
return Result.ok(documentChunkService.listIndexSyncStatus(
|
||||
knowledgeId, statusRequest.getDocumentId(), statusRequest.getIds()
|
||||
));
|
||||
}
|
||||
|
||||
@PostMapping("/documentChunk/retrySync")
|
||||
public Result<DocumentChunk> retryDocumentChunkSync(
|
||||
@RequestHeader("ApiKey") String apiKey,
|
||||
@JsonBody(value = "knowledgeId", required = true) BigInteger knowledgeId,
|
||||
@JsonBody(required = true, skipConvertError = false)
|
||||
DocumentChunkSyncRetryRequest retryRequest,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
assertApiShare(apiKey, request.getRequestURI(), knowledgeId,
|
||||
KnowledgeApiPermissionScope.KNOWLEDGE_MAINTENANCE.name());
|
||||
requireDocumentKnowledge(knowledgeId);
|
||||
if (retryRequest.getIndexSyncVersion() == null) {
|
||||
throw new BusinessException("同步版本不能为空");
|
||||
}
|
||||
DocumentChunk chunk = documentChunkService.retryIndexSync(
|
||||
knowledgeId, retryRequest.getId(), retryRequest.getIndexSyncVersion()
|
||||
);
|
||||
audit(apiKey, "API重试文档 Chunk 索引同步", "KNOWLEDGE_API_SHARE_WRITE",
|
||||
request.getRequestURI(), Map.of("knowledgeId", knowledgeId, "chunkId", retryRequest.getId()));
|
||||
return Result.ok(chunk);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -66,6 +66,8 @@ public class PublicKnowledgeShareControllerContractTest {
|
||||
JsonBody chunkBody = chunk.getAnnotation(JsonBody.class);
|
||||
Assert.assertNotNull(chunkBody);
|
||||
Assert.assertEquals("", chunkBody.value());
|
||||
Assert.assertTrue(chunkBody.required());
|
||||
Assert.assertFalse(chunkBody.skipConvertError());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user