|
|
@ -1,12 +1,24 @@
|
|
|
|
package com.supervision.pdfqaserver.service.impl;
|
|
|
|
package com.supervision.pdfqaserver.service.impl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
|
|
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
|
import com.supervision.pdfqaserver.cache.PromptCache;
|
|
|
|
import com.supervision.pdfqaserver.cache.PromptCache;
|
|
|
|
|
|
|
|
import com.supervision.pdfqaserver.dao.Neo4jRepository;
|
|
|
|
|
|
|
|
import com.supervision.pdfqaserver.dto.ERAttributeDTO;
|
|
|
|
import com.supervision.pdfqaserver.dto.EREDTO;
|
|
|
|
import com.supervision.pdfqaserver.dto.EREDTO;
|
|
|
|
|
|
|
|
import com.supervision.pdfqaserver.dto.EntityExtractionDTO;
|
|
|
|
|
|
|
|
import com.supervision.pdfqaserver.dto.RelationExtractionDTO;
|
|
|
|
import com.supervision.pdfqaserver.service.TripleToCypherExecutor;
|
|
|
|
import com.supervision.pdfqaserver.service.TripleToCypherExecutor;
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import org.springframework.ai.ollama.OllamaChatModel;
|
|
|
|
import org.springframework.ai.ollama.OllamaChatModel;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
|
|
import static com.supervision.pdfqaserver.cache.PromptCache.ERE_TO_INSERT_CYPHER;
|
|
|
|
import static com.supervision.pdfqaserver.cache.PromptCache.ERE_TO_INSERT_CYPHER;
|
|
|
|
|
|
|
|
|
|
|
|
@Slf4j
|
|
|
|
@Slf4j
|
|
|
@ -15,6 +27,8 @@ import static com.supervision.pdfqaserver.cache.PromptCache.ERE_TO_INSERT_CYPHER
|
|
|
|
public class TripleToCypherExecutorImpl implements TripleToCypherExecutor {
|
|
|
|
public class TripleToCypherExecutorImpl implements TripleToCypherExecutor {
|
|
|
|
|
|
|
|
|
|
|
|
private final OllamaChatModel ollamaChatModel;
|
|
|
|
private final OllamaChatModel ollamaChatModel;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final Neo4jRepository neo4jRepository;
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public String generateInsertCypher(EREDTO eredto) {
|
|
|
|
public String generateInsertCypher(EREDTO eredto) {
|
|
|
|
|
|
|
|
|
|
|
@ -32,4 +46,57 @@ public class TripleToCypherExecutorImpl implements TripleToCypherExecutor {
|
|
|
|
public void executeCypher(String cypher) {
|
|
|
|
public void executeCypher(String cypher) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void saveERE(EREDTO eredto) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<EntityExtractionDTO> entities = eredto.getEntities();
|
|
|
|
|
|
|
|
Map<String, List<Long>> nodeCache = new HashMap<>();
|
|
|
|
|
|
|
|
if (CollUtil.isNotEmpty(entities)){
|
|
|
|
|
|
|
|
// 保存节点
|
|
|
|
|
|
|
|
for (EntityExtractionDTO entity : entities) {
|
|
|
|
|
|
|
|
if (StrUtil.isEmpty(entity.getName())){
|
|
|
|
|
|
|
|
log.info("实体name属性为空,详情:{}", JSONUtil.toJsonStr(entity));
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Map<String, Object> attributes = entity.getAttributes().stream().collect(Collectors.toMap(
|
|
|
|
|
|
|
|
ERAttributeDTO::getAttributeEn, ERAttributeDTO::getValue
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
attributes.put("name", entity.getName());
|
|
|
|
|
|
|
|
log.info("保存节点{},属性:{}", entity.getEntityEn(),JSONUtil.toJsonStr(entity.getAttributes()));
|
|
|
|
|
|
|
|
List<Long> nodeIds = neo4jRepository.saveOrUpdateEntityNode(entity.getEntityEn(), "name", attributes);
|
|
|
|
|
|
|
|
nodeCache.put(StrUtil.join("_", entity.getEntity(), entity.getName()), nodeIds);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CollUtil.isNotEmpty(eredto.getRelations())){
|
|
|
|
|
|
|
|
// 保存关系
|
|
|
|
|
|
|
|
for (RelationExtractionDTO relation : eredto.getRelations()) {
|
|
|
|
|
|
|
|
String sourceNodeKey = StrUtil.join("_", relation.getSourceType(), relation.getSource());
|
|
|
|
|
|
|
|
List<Long> sourceNodeIds = nodeCache.get(sourceNodeKey);
|
|
|
|
|
|
|
|
if (CollUtil.isEmpty(sourceNodeIds)) {
|
|
|
|
|
|
|
|
log.info("关系{}没有source节点", sourceNodeKey);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
String targetNodeKey = StrUtil.join("_", relation.getTargetType(), relation.getTarget());
|
|
|
|
|
|
|
|
List<Long> targetNodeIds = nodeCache.get(targetNodeKey);
|
|
|
|
|
|
|
|
if (CollUtil.isEmpty(targetNodeIds)) {
|
|
|
|
|
|
|
|
log.info("关系{}没有target节点", targetNodeKey);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Map<String, Object> attributes = relation.getAttributes().stream().collect(Collectors.toMap(
|
|
|
|
|
|
|
|
ERAttributeDTO::getAttributeEn, ERAttributeDTO::getValue
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
for (Long sourceNodeId : sourceNodeIds) {
|
|
|
|
|
|
|
|
for (Long targetNodeId : targetNodeIds) {
|
|
|
|
|
|
|
|
if (sourceNodeId.equals(targetNodeId)) {
|
|
|
|
|
|
|
|
log.info("关系{}的source和target节点相同", sourceNodeKey);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
log.info("保存关系{}-{}-{}的属性:{}", relation.getSourceTypeEn(), relation.getRelationEn(),relation.getTargetTypeEn(), attributes);
|
|
|
|
|
|
|
|
neo4jRepository.saveOrUpdateRelation(sourceNodeId, targetNodeId, relation.getRelationEn(), false, false, attributes);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|