提交构建抽象图谱的代码

topo_dev
liu 9 months ago
parent 34dfc0bfc7
commit 051157ebc9

@ -6,6 +6,7 @@ import com.supervision.neo4j.domain.Rel;
import com.supervision.neo4j.service.Neo4jService;
//import io.swagger.annotations.Api;
//import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -23,13 +24,25 @@ public class Neo4jController {
private Neo4jService neo4jService;
@PostMapping("/save")
public R<?> save(@RequestBody CaseNode caseNode) {
return neo4jService.save(caseNode);
public R<CaseNode> save(@RequestBody CaseNode caseNode) {
try {
CaseNode save = neo4jService.save(caseNode);
return R.ok(save);
} catch (RuntimeException e) {
return R.fail(e.getMessage());
}
}
@PostMapping("/delNode")
public R<?> delNode(Long id) {
return neo4jService.delNode(id);
neo4jService.delNode(id);
return R.ok();
}
@PostMapping("/deleteRel")
public R<?> deleteRel(Long relId) {
neo4jService.deleteRel(relId);
return R.ok();
}
@PostMapping("/findById")
@ -81,4 +94,16 @@ public class Neo4jController {
return neo4jService.test();
}
@ApiOperation("构建抽象图谱")
@GetMapping("createAbstractGraph")
public void createAbstractGraph(String path, String sheetName) {
neo4jService.createAbstractGraph(path, sheetName);
}
@ApiOperation("清除抽象图谱")
@GetMapping("deleteAbstractGraph")
public void deleteAbstractGraph() {
neo4jService.deleteAbstractGraph();
}
}

@ -55,4 +55,10 @@ public class CaseNode {
this.picType = picType;
}
public CaseNode( String name, String nodeType, String picType){
this.name = name;
this.nodeType = nodeType;
this.picType = picType;
}
}

@ -14,6 +14,8 @@ public class Rel {
private String target;
private Long targetId;
// 是否是抽象,0抽象 1真实
private String picType = "1";
public Rel() {
}
@ -24,6 +26,13 @@ public class Rel {
this.targetId = targetId;
}
public Rel(Long sourceId, String name, Long targetId,String picType) {
this.sourceId = sourceId;
this.name = name;
this.targetId = targetId;
this.picType = picType;
}
public Rel(Long id, String source, Long sourceId, String name, String target, Long targetId) {
this.id = id;
this.source = source;

@ -12,9 +12,11 @@ import java.util.List;
*/
public interface Neo4jService {
R<?> save(CaseNode caseNode);
CaseNode save(CaseNode caseNode);
R<?> delNode(Long id);
void delNode(Long id);
void deleteRel(Long relId);
CaseNode findById(Long id);
@ -28,4 +30,8 @@ public interface Neo4jService {
R<?> getNode(String picType, String caseId);
R<?> test();
void deleteAbstractGraph();
void createAbstractGraph(String path,String sheetName);
}

@ -1,42 +1,47 @@
package com.supervision.neo4j.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.supervision.common.domain.R;
import com.supervision.common.utils.StringUtils;
import com.supervision.neo4j.domain.CaseNode;
import com.supervision.neo4j.domain.Rel;
import com.supervision.neo4j.service.Neo4jService;
import com.supervision.neo4j.utils.Neo4jUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.neo4j.cypherdsl.core.Case;
import org.neo4j.driver.*;
import org.neo4j.driver.Record;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author qmy
* @since 2023-10-26
*/
@Slf4j
@Service
public class Neo4jServiceImpl implements Neo4jService {
private final Driver driver;
@Autowired
private Neo4jServiceImpl(Driver driver) {
this.driver = driver;
}
@Override
public R<?> save(CaseNode caseNode) {
public CaseNode save(CaseNode caseNode) {
if (StringUtils.isEmpty(caseNode.getName()) || StringUtils.isEmpty(caseNode.getNodeType())) {
return R.fail("未传节点名称或节点类型或图谱类型!");
throw new RuntimeException("未传节点名称或节点类型或图谱类型!");
}
List<CaseNode> byName = findByName(caseNode.getCaseId(), caseNode.getRecordsId(), caseNode.getNodeType(), caseNode.getName(), caseNode.getPicType());
if (byName != null && !byName.isEmpty()) {
return R.fail("名称已存在");
throw new RuntimeException("名称已存在!");
}
CaseNode res = null;
try {
@ -67,20 +72,50 @@ public class Neo4jServiceImpl implements Neo4jService {
} catch (Exception e) {
e.printStackTrace();
}
return R.ok(res);
return res;
}
/**
* ,,,,
*
* @param id ID
*/
@Override
public R<?> delNode(Long id) {
public void delNode(Long id) {
try {
Session session = driver.session();
StringBuffer cql = new StringBuffer();
cql.append("MATCH (n) where id(n) = ").append(id).append(" DELETE n");
log.info(cql.toString());
Result run = session.run(cql.toString());
while (run.hasNext()) {
Record next = run.next();
// log.info(next.toString());
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
*
*
* @param relId ID
*/
public void deleteRel(Long relId) {
try {
Session session = driver.session();
StringBuilder cql = new StringBuilder();
cql.append("MATCH ()-[r]->() WHERE id(r) = ").append(relId).append(" DELETE r");
log.info(cql.toString());
Result run = session.run(cql.toString());
while (run.hasNext()) {
Record next = run.next();
// log.info(next.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
return R.ok();
}
@Override
@ -267,13 +302,84 @@ public class Neo4jServiceImpl implements Neo4jService {
Result run = session.run("MATCH (m:LawActor), (n:FictionalOrgan) where m.name=$lawActor OPTIONAL MATCH (m)-[r:`冒充`]->(n) RETURN id(m) as startId, id(n) as endId, id(r) as relId, m.recordId as recordId, m.recordsId as recordsId", params);
while (run.hasNext()) {
Record record = run.next();
String id = record.get("startId").asLong() + "";
String endId = record.get("endId").asLong() + "";
String relId = record.get("relId").asLong() + "";
String id = Neo4jUtils.valueTransportString(record.get("startId"));
String endId = Neo4jUtils.valueTransportString(record.get("endId"));
String relId = Neo4jUtils.valueTransportString(record.get("relId"));
System.out.println("************" + id);
System.out.println("************" + endId);
System.out.println("************" + relId);
}
return R.ok("222");
}
@Override
public void createAbstractGraph(String path,String sheetName) {
// 首先从数据库中读到数据
ExcelReader reader = ExcelUtil.getReader(path, sheetName);
List<AbstractGraphExcelHeader> abstractGraphExcelHeaders = reader.readAll(AbstractGraphExcelHeader.class);
Map<String, CaseNode> nodeMap = new HashMap<>();
Map<String, Rel> relMap = new HashMap<>();
for (AbstractGraphExcelHeader abstractGraphExcelHeader : abstractGraphExcelHeaders) {
// from
if (!nodeMap.containsKey(abstractGraphExcelHeader.getFrom())) {
CaseNode caseNode = new CaseNode(abstractGraphExcelHeader.getFrom(), abstractGraphExcelHeader.getFrom(), "0");
log.info("点:{}插入成功", abstractGraphExcelHeader.getFrom());
CaseNode save = save(caseNode);
nodeMap.put(abstractGraphExcelHeader.getFrom(), save);
}
// to
if (!nodeMap.containsKey(abstractGraphExcelHeader.getTo())) {
CaseNode caseNode = new CaseNode(abstractGraphExcelHeader.getTo(), abstractGraphExcelHeader.getTo(), "0");
CaseNode save = save(caseNode);
log.info("点:{}插入成功", abstractGraphExcelHeader.getTo());
nodeMap.put(abstractGraphExcelHeader.getTo(), save);
}
// relation
if (!relMap.containsKey(abstractGraphExcelHeader.getFrom() + "->" + abstractGraphExcelHeader.getRelation() + "->" + abstractGraphExcelHeader.getTo())) {
Rel rel = new Rel(nodeMap.get(abstractGraphExcelHeader.getFrom()).getId(), abstractGraphExcelHeader.getRelation(), nodeMap.get(abstractGraphExcelHeader.getTo()).getId(), "0");
saveRelation(rel);
log.info("关系:{}插入成功", (abstractGraphExcelHeader.getFrom() + "->" + abstractGraphExcelHeader.getRelation() + "->" + abstractGraphExcelHeader.getTo()));
relMap.put(abstractGraphExcelHeader.getFrom() + "->" + abstractGraphExcelHeader.getRelation() + "->" + abstractGraphExcelHeader.getTo(), rel);
}
}
}
public void deleteAbstractGraph() {
Session session = driver.session();
// 首先查出来所有的抽象节点
Result run = session.run("MATCH (n) WHERE n.picType = '0' OPTIONAL MATCH (n)-[r]-() RETURN id(n) as nodeId, id(r) as relId");
Set<String> nodeIdSet = new HashSet<>();
HashSet<String> relIdSet = new HashSet<>();
while (run.hasNext()) {
Record record = run.next();
String nodeId = Neo4jUtils.valueTransportString(record.get("nodeId"));
nodeIdSet.add(nodeId);
String relId = Neo4jUtils.valueTransportString(record.get("relId"));
relIdSet.add(relId);
}
// 删除边
for (String s : relIdSet) {
long relId = Long.parseLong(s);
deleteRel(relId);
log.info("删除边:{} 成功", relId);
}
// 删除节点
for (String s : nodeIdSet) {
long nodeId = Long.parseLong(s);
delNode(nodeId);
log.info("删除节点:{} 成功", nodeId);
}
}
@Data
private static class AbstractGraphExcelHeader {
private String from;
private String relation;
private String to;
}
}

@ -103,7 +103,7 @@ public class Neo4jUtils {
/**
* neo4j
*/
private static String valueTransportString(Value value) {
public static String valueTransportString(Value value) {
if (value instanceof NullValue) {
return null;
} else if (value instanceof IntegerValue) {

@ -87,6 +87,11 @@ public class RecordController {
return R.ok(modelRecordTypeService.getThreeInfo(caseId, name, recordId));
}
@GetMapping("testExtractThreeInfo")
public void testExtractThreeInfo(){
modelRecordTypeService.testExtractThreeInfo();
}
@ApiOperation("将三元组信息保存到知识图谱")
@PostMapping("/addNeo4j")
public R<String> addNeo4j(@RequestBody ListDTO list) {

@ -22,5 +22,7 @@ public interface ModelRecordTypeService extends IService<ModelRecordType> {
List<TripleInfo> getThreeInfo(String caseId, String name, String recordId);
void testExtractThreeInfo();
String addNeo4j(List<String> ids);
}

@ -119,16 +119,60 @@ public class ModelRecordTypeServiceImpl extends ServiceImpl<ModelRecordTypeMappe
}
@Override
public List<TripleInfo> getThreeInfo(String caseId, String name, String recordId) {
// TODO 这里应该改成异步的形式,通过异步的形式来进行提取三元组信息,不能每次点击就跑一遍
return extractTripleInfo(caseId, name, recordId);
}
@Override
public void testExtractThreeInfo() {
String prompt = """
---
?
---
(:;:;:)
,json
,{"主体":"主体名称","关系":"关系名称","客体":"客体名称"}
::,.:{"主体":"小明","关系":"伪造","客体":"租车合同"}
:,:{}
!
JSON
""";
// 抽取的客体名称一定属于给定的客体类型分类,且抽取的关系完全等于给定的关系。
Prompt ask = new Prompt(new UserMessage(prompt));
StopWatch stopWatch = new StopWatch();
stopWatch.start();
log.info("开始分析:");
ChatResponse call = chatClient.call(ask);
stopWatch.stop();
log.info("耗时:{}", stopWatch.getTotalTimeSeconds());
String content = call.getResult().getOutput().getContent();
log.info("分析的结果是:{}", content);
String oldPrompt = """
1.
{result
[
{startNodeType:'LawActor',entity:'',endNodeType:'FictionalOrgan',property:'',value:'' },
{startNodeType:'LawActor',entity:'',endNodeType:'Seal',property:'',value:''},
{startNodeType:'LawActor',entity:'',endNodeType:'BusinessLicense',property:'',value:''}
]
}
2.
3.{ "result": [] }
1便QQ
{"result":[{"startNodeType":"LawActor","entity":"裴金禄","endNodeType":"FictionalOrgan","property":"兰州胜利机械租赁有限公司","value":"冒充"},{"startNodeType":"LawActor","entity":"裴金禄","endNodeType":"Seal","property":"兰州胜利机械租赁有限公司合同专用章","value":"伪造"},{"startNodeType":"LawActor","entity":"裴金禄","endNodeType":"Seal","property":"中铁北京局集团有限公司合同专用章","value":"伪造"},{"startNodeType":"LawActor","entity":"裴金禄","endNodeType":"BusinessLicense","property":"兰州胜利机械租赁有限公司营业执照","value":"伪造"}]}
2:{ "result": [] }
""";
}
private List<TripleInfo> extractTripleInfo(String caseId, String name, String recordId) {
// 首先获取所有切分后的笔录
List<NoteRecordSplit> recordSplitList= noteRecordSplitMapper.selectRecord(caseId, name, recordId);
List<NoteRecordSplit> recordSplitList = noteRecordSplitMapper.selectRecord(caseId, name, recordId);
List<TripleInfo> tripleInfos = new ArrayList<>();
// 对切分后的笔录进行遍历
for (NoteRecordSplit record : recordSplitList) {
@ -189,7 +233,7 @@ public class ModelRecordTypeServiceImpl extends ServiceImpl<ModelRecordTypeMappe
CaseNode startNode = neo4jService.findOneByName(tripleInfo.getCaseId(), tripleInfo.getNoteRecordsId(), tripleInfo.getStartNodeType(), start, "1");
if (startNode == null) {
startNode = new CaseNode(start, tripleInfo.getStartNodeType(), tripleInfo.getNoteRecordId(), tripleInfo.getNoteRecordsId(), tripleInfo.getCaseId(), "1");
CaseNode save = (CaseNode) neo4jService.save(startNode).getData();
CaseNode save = neo4jService.save(startNode);
startNode.setId(save.getId());
}
//结束节点
@ -197,7 +241,7 @@ public class ModelRecordTypeServiceImpl extends ServiceImpl<ModelRecordTypeMappe
CaseNode endNode = neo4jService.findOneByName(tripleInfo.getCaseId(), tripleInfo.getNoteRecordsId(), tripleInfo.getEndNodeType(), end, "1");
if (endNode == null) {
endNode = new CaseNode(end, tripleInfo.getEndNodeType(), tripleInfo.getNoteRecordId(), tripleInfo.getNoteRecordsId(), tripleInfo.getCaseId(), "1");
CaseNode save = (CaseNode) neo4jService.save(endNode).getData();
CaseNode save = neo4jService.save(endNode);
endNode.setId(save.getId());
}
//关系

@ -20,6 +20,8 @@ spring:
top-k: 90
# 与top-k一起工作。较高的值例如0.95将导致更加多样化的文本而较低的值例如0.5)将生成更加集中和保守的文本。
top-p: 0.95
# 随机数种子,用于控制模型输出的随机性。
seed: 1
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:

Loading…
Cancel
Save