|
|
@@ -1,9 +1,11 @@
|
|
|
package com.lingyue.graph.controller;
|
|
|
|
|
|
import com.lingyue.common.domain.AjaxResult;
|
|
|
+import com.lingyue.graph.entity.GraphNode;
|
|
|
import com.lingyue.graph.service.DocumentBlockGeneratorService;
|
|
|
import com.lingyue.graph.service.DocumentBlockGeneratorService.BlockDTO;
|
|
|
import com.lingyue.graph.service.GraphNerService;
|
|
|
+import com.lingyue.graph.service.GraphNodeService;
|
|
|
import com.lingyue.graph.service.NerToBlockService;
|
|
|
import com.lingyue.graph.service.NerToBlockService.TextElementDTO;
|
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
|
@@ -11,10 +13,12 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|
|
import lombok.Data;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.http.*;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
+import java.util.*;
|
|
|
|
|
|
/**
|
|
|
* NER 到 Block 转换控制器
|
|
|
@@ -32,8 +36,13 @@ import java.util.Map;
|
|
|
public class NerBlockController {
|
|
|
|
|
|
private final GraphNerService graphNerService;
|
|
|
+ private final GraphNodeService graphNodeService;
|
|
|
private final NerToBlockService nerToBlockService;
|
|
|
private final DocumentBlockGeneratorService blockGeneratorService;
|
|
|
+ private final RestTemplate restTemplate;
|
|
|
+
|
|
|
+ @Value("${server.port:5232}")
|
|
|
+ private int serverPort;
|
|
|
|
|
|
/**
|
|
|
* 将文本和实体转换为 TextElement 列表
|
|
|
@@ -79,10 +88,10 @@ public class NerBlockController {
|
|
|
// 获取文档文本
|
|
|
String text = graphNerService.getDocumentText(documentId);
|
|
|
|
|
|
- // 如果没有提供实体,尝试从图数据库获取
|
|
|
+ // 如果没有提供实体,从图数据库获取
|
|
|
if (entities == null || entities.isEmpty()) {
|
|
|
- // TODO: 从 GraphNode 表获取实体并转换
|
|
|
- log.info("未提供实体,生成纯文本块: documentId={}", documentId);
|
|
|
+ entities = getEntitiesFromGraphNodes(documentId);
|
|
|
+ log.info("从图数据库获取实体: documentId={}, count={}", documentId, entities.size());
|
|
|
}
|
|
|
|
|
|
List<BlockDTO> blocks = blockGeneratorService.generateBlocks(documentId, text, entities);
|
|
|
@@ -93,6 +102,139 @@ public class NerBlockController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 重新生成并保存文档块(用于已解析但没有 blocks 的文档)
|
|
|
+ */
|
|
|
+ @PostMapping("/documents/{documentId}/regenerate-blocks")
|
|
|
+ @Operation(summary = "重新生成并保存块", description = "从已存储的文档和NER结果重新生成并保存Block到数据库")
|
|
|
+ public AjaxResult<?> regenerateAndSaveBlocks(@PathVariable String documentId) {
|
|
|
+ try {
|
|
|
+ // 1. 获取文档文本
|
|
|
+ String text = graphNerService.getDocumentText(documentId);
|
|
|
+ if (text == null || text.isEmpty()) {
|
|
|
+ return AjaxResult.error("文档文本不存在: " + documentId);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 从图数据库获取实体
|
|
|
+ List<Map<String, Object>> entities = getEntitiesFromGraphNodes(documentId);
|
|
|
+ log.info("重新生成块: documentId={}, textLength={}, entityCount={}",
|
|
|
+ documentId, text.length(), entities.size());
|
|
|
+
|
|
|
+ // 3. 生成块
|
|
|
+ List<BlockDTO> blocks = blockGeneratorService.generateBlocks(documentId, text, entities);
|
|
|
+ if (blocks.isEmpty()) {
|
|
|
+ return AjaxResult.error("生成块失败:没有可用的内容");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 保存到 document-service
|
|
|
+ int savedCount = saveBlocksToDocumentService(documentId, blocks);
|
|
|
+
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+ result.put("blockCount", blocks.size());
|
|
|
+ result.put("savedCount", savedCount);
|
|
|
+ result.put("entityCount", entities.size());
|
|
|
+
|
|
|
+ return AjaxResult.success("重新生成并保存成功", result);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("重新生成块失败: documentId={}, error={}", documentId, e.getMessage(), e);
|
|
|
+ return AjaxResult.error("重新生成失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从 GraphNode 表获取实体并转换为 NER 格式
|
|
|
+ */
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private List<Map<String, Object>> getEntitiesFromGraphNodes(String documentId) {
|
|
|
+ List<GraphNode> nodes = graphNodeService.getNodesByDocumentId(documentId);
|
|
|
+ List<Map<String, Object>> entities = new ArrayList<>();
|
|
|
+
|
|
|
+ for (GraphNode node : nodes) {
|
|
|
+ Map<String, Object> entity = new HashMap<>();
|
|
|
+ entity.put("name", node.getName());
|
|
|
+ entity.put("type", node.getType());
|
|
|
+ entity.put("tempId", node.getId());
|
|
|
+
|
|
|
+ // 位置信息(从 GraphNode.position JSONB 字段获取)
|
|
|
+ Object positionObj = node.getPosition();
|
|
|
+ if (positionObj instanceof Map) {
|
|
|
+ Map<String, Object> posMap = (Map<String, Object>) positionObj;
|
|
|
+ Map<String, Object> position = new HashMap<>();
|
|
|
+ position.put("charStart", posMap.get("charStart"));
|
|
|
+ position.put("charEnd", posMap.get("charEnd"));
|
|
|
+ entity.put("position", position);
|
|
|
+ }
|
|
|
+
|
|
|
+ entities.add(entity);
|
|
|
+ }
|
|
|
+
|
|
|
+ return entities;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 调用 document-service 保存块
|
|
|
+ */
|
|
|
+ private int saveBlocksToDocumentService(String documentId, List<BlockDTO> blocks) {
|
|
|
+ try {
|
|
|
+ String url = "http://localhost:" + serverPort + "/api/v1/documents/" + documentId + "/blocks/batch";
|
|
|
+
|
|
|
+ // 转换为 Map 列表
|
|
|
+ List<Map<String, Object>> blockMaps = new ArrayList<>();
|
|
|
+ for (BlockDTO block : blocks) {
|
|
|
+ Map<String, Object> blockMap = new HashMap<>();
|
|
|
+ blockMap.put("blockId", block.getBlockId());
|
|
|
+ blockMap.put("documentId", block.getDocumentId());
|
|
|
+ blockMap.put("parentId", block.getParentId());
|
|
|
+ blockMap.put("children", block.getChildren());
|
|
|
+ blockMap.put("blockIndex", block.getBlockIndex());
|
|
|
+ blockMap.put("blockType", block.getBlockType());
|
|
|
+ blockMap.put("charStart", block.getCharStart());
|
|
|
+ blockMap.put("charEnd", block.getCharEnd());
|
|
|
+
|
|
|
+ if (block.getElements() != null) {
|
|
|
+ List<Map<String, Object>> elementMaps = new ArrayList<>();
|
|
|
+ for (TextElementDTO el : block.getElements()) {
|
|
|
+ Map<String, Object> elMap = new HashMap<>();
|
|
|
+ elMap.put("type", el.getType());
|
|
|
+ elMap.put("content", el.getContent());
|
|
|
+ elMap.put("entityId", el.getEntityId());
|
|
|
+ elMap.put("entityText", el.getEntityText());
|
|
|
+ elMap.put("entityType", el.getEntityType());
|
|
|
+ elMap.put("confirmed", el.getConfirmed());
|
|
|
+ elementMaps.add(elMap);
|
|
|
+ }
|
|
|
+ blockMap.put("elements", elementMaps);
|
|
|
+ }
|
|
|
+
|
|
|
+ blockMaps.add(blockMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Object> request = new HashMap<>();
|
|
|
+ request.put("blocks", blockMaps);
|
|
|
+
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
+
|
|
|
+ HttpEntity<Map<String, Object>> entity = new HttpEntity<>(request, headers);
|
|
|
+
|
|
|
+ ResponseEntity<Map> response = restTemplate.exchange(url, HttpMethod.POST, entity, Map.class);
|
|
|
+
|
|
|
+ if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
|
|
|
+ Object data = response.getBody().get("data");
|
|
|
+ if (data instanceof Number) {
|
|
|
+ return ((Number) data).intValue();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return blocks.size();
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("保存块到 document-service 失败: documentId={}, error={}", documentId, e.getMessage());
|
|
|
+ throw new RuntimeException("保存块失败: " + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// ==================== 请求 DTO ====================
|
|
|
|
|
|
@Data
|