You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fu-hsi-service/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java

838 lines
44 KiB
Java

10 months ago
package com.supervision.police.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
10 months ago
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.deepoove.poi.XWPFTemplate;
import com.supervision.common.constant.IndexRuleConstants;
10 months ago
import com.supervision.common.domain.R;
import com.supervision.common.utils.StringUtils;
9 months ago
import com.supervision.constant.JudgeResultEnum;
10 months ago
import com.supervision.neo4j.dto.ResultDTO;
import com.supervision.neo4j.utils.Neo4jUtils;
import com.supervision.police.domain.*;
import com.supervision.police.dto.*;
import com.supervision.police.dto.caseScore.CaseScore;
import com.supervision.police.dto.caseScore.CaseScoreDetailBuilder;
import com.supervision.police.dto.caseScore.CaseScoreDetailDTO;
import com.supervision.police.dto.indexRule.IndexRule;
import com.supervision.police.dto.indexRule.Operand;
import com.supervision.police.dto.indexRule.OperandUnit;
import com.supervision.police.dto.indexRule.RuleCondition;
10 months ago
import com.supervision.police.mapper.*;
import com.supervision.police.mybatis.RowSqlMapper;
import com.supervision.police.service.*;
import com.supervision.utils.CalculationUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
10 months ago
import org.neo4j.driver.Driver;
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
10 months ago
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
10 months ago
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
10 months ago
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
10 months ago
import static com.supervision.common.constant.IndexRuleConstants.*;
import static com.supervision.common.constant.NotePromptConstants.TYPE_STRUCTURAL_REASONING;
@Slf4j
10 months ago
@Service
@RequiredArgsConstructor
10 months ago
public class ModelServiceImpl implements ModelService {
private final ResourceLoader resourceLoader;
10 months ago
private final Driver driver;
private final ModelCaseMapper modelCaseMapper;
private final ModelAtomicIndexMapper modelAtomicIndexMapper;
10 months ago
private final ModelAtomicResultMapper modelAtomicResultMapper;
10 months ago
private final ModelIndexMapper modelIndexMapper;
10 months ago
private final ModelIndexResultMapper modelIndexResultMapper;
10 months ago
private final CasePersonMapper casePersonMapper;
private final CaseEvidenceService caseEvidenceService;
private final ModelAtomicResultService modelAtomicResultService;
private final RowSqlMapper rowSqlMapper;
private final ModelIndexService modelIndexService;
private final CaseStatusManageService caseStatusManageService;
private final ModelIndexAtomicRelationService modelIndexAtomicRelationService;
private final NoteRecordService noteRecordService;
@Autowired
private NotePromptService notePromptService;
@Autowired
private EvidenceDirectoryService evidenceDirectoryService;
private final EvidenceCategoryService evidenceCategoryService;
10 months ago
@Override
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
10 months ago
public R<?> analyseCase(AnalyseCaseDTO analyseCaseDTO) {
10 months ago
ModelCase modelCase = modelCaseMapper.selectById(analyseCaseDTO.getCaseId());
9 months ago
// 获取案件行为人ID
CasePerson casePerson = casePersonMapper.selectOne(new LambdaQueryWrapper<CasePerson>()
.eq(CasePerson::getCaseId, analyseCaseDTO.getCaseId())
.eq(CasePerson::getCaseActorFlag, 1)
.eq(CasePerson::getRoleCode, "1")
.eq(StrUtil.isNotEmpty(analyseCaseDTO.getLawActorName()), CasePerson::getName, analyseCaseDTO.getLawActorName()));
if (ObjectUtil.isEmpty(casePerson)) {
10 months ago
throw new RuntimeException("未找到的行为人" + analyseCaseDTO.getLawActorName());
}
9 months ago
// 首先将原先的值进行赋值,设置到pre_result
modelIndexResultMapper.updatePreResult(analyseCaseDTO.getCaseId());
10 months ago
//原子指标
List<ModelAtomicIndex> atomicIndices = modelAtomicIndexMapper.selectByCaseType(modelCase.getCaseType());
// 存放原子指标的结果,key:原子指标ID,value:(key大指标ID,value:结果)
Map<String, Map<String, String>> atomicResultMap = new HashMap<>();
10 months ago
for (ModelAtomicIndex atomicIndex : atomicIndices) {
//原子指标结果
ModelAtomicResult result = new ModelAtomicResult();
result.setCasePersonId(casePerson.getId());
10 months ago
result.setCaseId(analyseCaseDTO.getCaseId());
result.setAtomicId(atomicIndex.getId());
//查询语句
String ql = atomicIndex.getQueryLang();
10 months ago
//原子指标结果表
try {
//查询图谱 index_source: 1人工定义 2数据库查询 3图谱生成 4大模型
if ("1".equals(atomicIndex.getIndexSource())) {
10 months ago
// list
manuallyDefinedCase(analyseCaseDTO, result, atomicIndex);
} else if ("2".equals(atomicIndex.getIndexSource()) && StringUtils.isNotEmpty(ql)) {
10 months ago
//
9 months ago
analyseDataBaseCase(analyseCaseDTO, result, ql, casePerson.getName());
} else if ("3".equals(atomicIndex.getIndexSource()) && StringUtils.isNotEmpty(ql)) {
// 使用知识图谱进行计算
9 months ago
analyseGraphCase(analyseCaseDTO, result, ql, casePerson.getName());
} else if ("4".equals(atomicIndex.getIndexSource())) {
10 months ago
//
} else if ("5".equals(atomicIndex.getIndexSource())) {
// todo: 结构化推理
//analyseStructuredInference(analyseCaseDTO, result);
10 months ago
}
} catch (Exception e) {
log.error(e.getMessage(), e);
10 months ago
}
// 根据原子指标ID查model_index_atomic_relation表所有的指标ID
List<ModelIndexAtomicRelation> relationList = modelIndexAtomicRelationService.lambdaQuery().eq(ModelIndexAtomicRelation::getAtomicIndexId, atomicIndex.getId()).list();
for (ModelIndexAtomicRelation relation : relationList) {
// 保存或更新原子指标结果表
ModelAtomicResult exist = modelAtomicResultMapper.selectByCaseIdAndAtomicId(analyseCaseDTO.getCaseId(), casePerson.getId(), relation.getModelIndexId(), atomicIndex.getId());
result.setIndexId(relation.getModelIndexId());
if (exist == null) {
result.setId(null);
modelAtomicResultMapper.insert(result);
} else {
result.setId(exist.getId());
modelAtomicResultMapper.updateById(result);
}
Map<String, String> indexMap = atomicResultMap.computeIfAbsent(
result.getAtomicId(),
k -> new HashMap<>() // 如果不存在则创建一个新的 HashMap
);
indexMap.put(relation.getModelIndexId(), result.getAtomicResult());
9 months ago
}
10 months ago
}
// 最终计算得分
calculateFinalScore(analyseCaseDTO, modelCase, atomicResultMap);
caseStatusManageService.whenAnalyseCaseSuccess(analyseCaseDTO.getCaseId(), modelCase.getTotalScore());
// 计算完成之后,把所有的笔录上传到模型
noteRecordService.uploadFileToLangChainChat(analyseCaseDTO.getCaseId());
return R.ok();
}
10 months ago
@Override
public R<?> analyseCaseNew(AnalyseCaseDTO analyseCaseDTO) {
log.info("数据准备阶段");
String caseId = analyseCaseDTO.getCaseId();
Map<String, Integer> typeScoreMap = new HashMap<>();
// 查出案件信息
ModelCase modelCase = modelCaseMapper.selectById(caseId);
// 获取案件行为人ID
CasePerson casePerson = casePersonMapper.selectOne(new LambdaQueryWrapper<CasePerson>()
.eq(CasePerson::getCaseId, analyseCaseDTO.getCaseId())
.eq(CasePerson::getCaseActorFlag, 1)
.eq(CasePerson::getRoleCode, "1")
.eq(StrUtil.isNotEmpty(analyseCaseDTO.getLawActorName()), CasePerson::getName, analyseCaseDTO.getLawActorName()));
if (ObjectUtil.isEmpty(casePerson)) {
throw new RuntimeException("未找到的行为人" + analyseCaseDTO.getLawActorName());
}
// 查出指标信息
List<ModelIndex> modelIndices = modelIndexService.list(new LambdaQueryWrapper<ModelIndex>().eq(ModelIndex::getDataStatus, "1").eq(ModelIndex::getCaseType, modelCase.getCaseType()));
// 查出原子指标信息
List<ModelAtomicIndex> atomicIndices = modelAtomicIndexMapper.selectByCaseType(modelCase.getCaseType());
// 查出提示词信息
List<NotePrompt> notePrompts = notePromptService.list(new LambdaQueryWrapper<NotePrompt>().eq(NotePrompt::getType, TYPE_STRUCTURAL_REASONING));
// 查出证据目录信息
List<EvidenceDirectory> evidenceDirectories = evidenceDirectoryService.list(new LambdaQueryWrapper<EvidenceDirectory>().eq(EvidenceDirectory::getCaseId, caseId));
// 查出证据信息
List<CaseEvidence> caseEvidences = caseEvidenceService.list(new LambdaQueryWrapper<CaseEvidence>().eq(CaseEvidence::getCaseId, caseId));
log.info("开始计算指标结果");
// 遍历指标集合,处理每个指标的判断逻辑,得出结果
modelIndices.forEach(modelIndex -> {
log.info("开始计算指标ID:{},指标名称:{}", modelIndex.getId(), modelIndex.getName());
IndexRule indexRule = modelIndex.getIndexRule();
Set<Boolean> ruleConditionGroupResultList = new HashSet<>();
if (indexRule != null) {
indexRule.getRuleConditionGroupList().forEach(ruleConditionGroup -> {
Set<Boolean> ruleConditionResultSet = new HashSet<>();
ruleConditionGroup.getRuleConditionList().forEach(ruleCondition -> {
Set<Boolean> operandUnitResultSet = new HashSet<>();
// 得到当前指标要求的存在关系(存在或不存在)
boolean relationSymbol = IndexRuleConstants.EVALUATE_RESULT_EXIST.equals(ruleCondition.getRelationalSymbol());
ModelAtomicIndex modelAtomicIndex = atomicIndices.stream().filter(atomicIndex -> atomicIndex.getId().equals(ruleCondition.getAtomicIndexId())).findAny().orElse(null);
7 months ago
if (modelAtomicIndex == null && !OPERAND_TYPE_STRUCTURE.equals(ruleCondition.getIndexSource())) {
log.error("原子指标不存在,跳出当前循环。原子指标ID:{}", ruleCondition.getAtomicIndexId());
return;
}
7 months ago
// 定义原子指标结果共有属性
ModelAtomicResult result = new ModelAtomicResult();
result.setIndexId(modelIndex.getId());
result.setCasePersonId(casePerson.getId());
result.setCaseId(analyseCaseDTO.getCaseId());
result.setAtomicId(ruleCondition.getAtomicIndexId());
result.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode());
ModelAtomicResult exist = modelAtomicResultMapper.selectByCaseIdAndAtomicId(caseId, casePerson.getId(), modelIndex.getId(), ruleCondition.getAtomicIndexId());
if (exist != null) {
result.setId(exist.getId());
}
switch (ruleCondition.getIndexSource()) {
case OPERAND_TYPE_MANUAL:
operandUnitResultSet.add(relationSymbol == manualIndexAnalysis(ruleCondition.getAtomicIndexId(), caseId));
break;
case OPERAND_TYPE_DB:
operandUnitResultSet.add(relationSymbol == dbIndexAnalysis(caseId, modelAtomicIndex.getQueryLang(), result));
break;
case OPERAND_TYPE_GRAPH:
operandUnitResultSet.add(relationSymbol == graphIndexAnalysis(casePerson.getName(), modelAtomicIndex.getQueryLang(), analyseCaseDTO.getCaseId(), ruleCondition, result));
7 months ago
break;
case OPERAND_TYPE_STRUCTURE:
ruleCondition.getOperandUnitList().forEach(operandUnit -> operandUnitResultSet.add(structureIndexAnalysis(operandUnit, ruleCondition.getAtomicIndexId(), atomicIndices, notePrompts, evidenceDirectories, caseEvidences, result)));
break;
default:
break;
}
ruleConditionResultSet.add(CalculationUtil.calculateBooleanSet(operandUnitResultSet, ruleCondition.getLogic()));
});
ruleConditionGroupResultList.add(CalculationUtil.calculateBooleanSet(ruleConditionResultSet, ruleConditionGroup.getRowLogic()));
});
} else {
log.error("指标规则不存在,跳出当前循环。指标ID:{}", modelIndex.getId());
return;
}
// 计算指标结果并保存
boolean result = CalculationUtil.calculateBooleanSet(ruleConditionGroupResultList, indexRule.getGroupLogic());
ModelIndexResult modelIndexResult = new ModelIndexResult();
modelIndexResult.setCaseId(caseId);
modelIndexResult.setIndexId(modelIndex.getId());
ModelIndexResult exist = modelIndexResultMapper.selectByCaseIdAndIndexId(analyseCaseDTO.getCaseId(), modelIndex.getId());
if (exist != null) {
modelIndexResult.setId(exist.getId());
}
modelIndexResult.setIndexResult(result ? "true" : "false");
if (exist == null) {
modelIndexResultMapper.insert(modelIndexResult);
} else {
modelIndexResultMapper.updateById(modelIndexResult);
}
if (result) {
Integer score = typeScoreMap.getOrDefault(modelIndex.getIndexType(), 0);
log.info("指标ID:{},指标类型:{},得分:{}分", modelIndex.getId(), modelIndex.getIndexType(), modelIndex.getIndexScore());
typeScoreMap.put(modelIndex.getIndexType(), score + modelIndex.getIndexScore());
log.info("当前类型总分:{}分", typeScoreMap.get(modelIndex.getIndexType()));
}
});
Integer gx = typeScoreMap.getOrDefault("1", 0);
Integer rz = typeScoreMap.getOrDefault("2", 0);
Integer cz = typeScoreMap.getOrDefault("3", 0);
int max = Integer.max(gx + rz, gx + cz);
modelCase.setTotalScore(max);
log.info("更新案件得分情况。最终得分:{}分(共性+入罪/共性+出罪 取最大值)。入罪:{}分。出罪:{}分。共性:{}分。", max, rz, cz, gx);
caseStatusManageService.whenAnalyseCaseSuccess(analyseCaseDTO.getCaseId(), modelCase.getTotalScore());
noteRecordService.uploadFileToLangChainChat(analyseCaseDTO.getCaseId());
return R.ok();
}
/**
*
*
* @param atomicIndexId ID
* @param caseId ID
*/
private boolean manualIndexAnalysis(String atomicIndexId, String caseId) {
boolean flag = false;
List<ModelAtomicResult> modelAtomicResults = modelAtomicResultMapper.selectList(
new LambdaQueryWrapper<ModelAtomicResult>().eq(ModelAtomicResult::getCaseId, caseId)
.eq(ModelAtomicResult::getAtomicId, atomicIndexId));
if (modelAtomicResults != null && !modelAtomicResults.isEmpty()) {
ModelAtomicResult modelAtomicResult = CollUtil.getFirst(modelAtomicResults);
flag = EVALUATE_RESULT_EXIST.equals(modelAtomicResult.getAtomicResult());
}
return flag;
}
/**
*
*
* @param caseId ID
* @param sql
* @param atomicResult
* @return
*/
private boolean dbIndexAnalysis(String caseId, String sql, ModelAtomicResult atomicResult) {
Map<String, Object> params = new HashMap<>();
params.put("caseId", caseId);
List<Map> mapList = rowSqlMapper.selectList(sql, params, Map.class);
boolean flag = false;
if (mapList != null && !mapList.isEmpty()) {
flag = true;
String evidenceIds = mapList.stream().map(map -> map.get("id").toString()).collect(Collectors.joining(","));
atomicResult.setEvidenceId(evidenceIds);
atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode());
}
modelAtomicResultService.saveOrUpdate(atomicResult);
return flag;
}
/**
*
*
* @param casePersonName
* @param queryLang
* @param caseId ID
* @param ruleCondition
* @param atomicResult
* @return
*/
private boolean graphIndexAnalysis(String casePersonName, String queryLang, String caseId, RuleCondition ruleCondition, ModelAtomicResult atomicResult) {
boolean flag = false;
Session session = driver.session();
//图谱
Map<String, Object> params = new HashMap<>();
// 行为人
params.put("lawActor", casePersonName);
// 案号
params.put("caseId", caseId);
Result run;
try {
run = session.run(queryLang, params);
} catch (Exception e) {
log.error("图数据库查询出现错误,查询语句{},参数{}", queryLang, JSONUtil.toJsonStr(params), e);
return flag;
}
List<ResultDTO> res = Neo4jUtils.getResultDTOList(run);
int count = 0;
if (!res.isEmpty()) {
// 进行遍历,如果有存在的,就设置为有
for (ResultDTO resultDTO : res) {
if (StringUtils.isNotEmpty(resultDTO.getRelId())) {
//存在关系
count++;
atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode());
atomicResult.setRecordId(resultDTO.getRecordId());
// 在退出循环之前先合并相关文本分片id
String recordSplitIdJoin = res.stream().filter(r ->
StringUtils.isNotEmpty(r.getRelId())
&& StringUtils.isNotEmpty(r.getRecordSplitId()))
.map(ResultDTO::getRecordSplitId).collect(Collectors.joining(","));
atomicResult.setRecordSplitId(recordSplitIdJoin);
}
}
}
if (CalculationUtil.evaluateExpression(String.valueOf(count), ruleCondition.getOperator(), ruleCondition.getValue())) {
flag = true;
}
modelAtomicResultService.saveOrUpdate(atomicResult);
return flag;
}
/**
*
*
* @param operandUnit
7 months ago
* @param modelAtomicIndexId ID
* @param atomicIndices
* @param notePrompts
* @param evidenceDirectories
* @param caseEvidences
* @param atomicResult
* @return
*/
7 months ago
private boolean structureIndexAnalysis(OperandUnit operandUnit, String modelAtomicIndexId, List<ModelAtomicIndex> atomicIndices, List<NotePrompt> notePrompts, List<EvidenceDirectory> evidenceDirectories, List<CaseEvidence> caseEvidences, ModelAtomicResult atomicResult) {
Operand left = operandUnit.getLeftOperand();
String operator = operandUnit.getOperator();
Operand right = operandUnit.getRightOperand();
boolean flag = false;
7 months ago
ModelAtomicIndex modelAtomicIndex = atomicIndices.stream().filter(atomicIndex -> atomicIndex.getId().equals(modelAtomicIndexId)).findAny().orElse(null);
if (modelAtomicIndex == null) {
log.error("原子指标不存在。原子指标ID:{}", modelAtomicIndexId);
return flag;
}
List<CaseEvidence> evidences = getEvidencesByPromptId(modelAtomicIndex.getPromptId(), caseEvidences, evidenceDirectories, notePrompts);
ModelAtomicIndex rightModelAtomicIndex = null;
if (OPERAND_TYPE_STRUCTURE.equals(right.getOperandType())) {
log.info("右操作数为结构化查询,提前查好对应的原子指标");
rightModelAtomicIndex = atomicIndices.stream().filter(atomicIndex -> atomicIndex.getId().equals(left.getAtomicIndexId())).findAny().orElse(null);
if (rightModelAtomicIndex == null || StringUtils.isEmpty(rightModelAtomicIndex.getPromptId())) {
log.error("原子指标不存在。原子指标ID:{}", left.getAtomicIndexId());
return flag;
}
}
if (!evidences.isEmpty()) {
log.info("聚合类型为【{}】,右操作数操作类型为:【{}】", AGGREGATE_TYPE_SUM.equals(left.getAggregateType()) ? "求和" : AGGREGATE_TYPE_COUNT.equals(left.getAggregateType()) ? "计数" : "任一", OPERAND_TYPE_STRUCTURE.equals(right.getOperandType()) ? "结构化查询" : "值");
switch (left.getAggregateType()) {
case AGGREGATE_TYPE_SUM:
if (OPERAND_TYPE_STRUCTURE.equals(right.getOperandType())) {
List<CaseEvidence> rightEvidences = getEvidencesByPromptId(rightModelAtomicIndex.getPromptId(), caseEvidences, evidenceDirectories, notePrompts);
if (CalculationUtil.evaluateExpression(String.valueOf(getSumFromEvidences(left.getPropertyKey(), evidences)), operator, String.valueOf(getSumFromEvidences(right.getPropertyKey(), rightEvidences)))) {
atomicResult.setEvidenceId(evidences.stream().map(CaseEvidence::getId).collect(Collectors.joining(",")));
atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode());
modelAtomicResultService.saveOrUpdate(atomicResult);
return true;
}
} else if (OPERAND_TYPE_VALUE.equals(right.getOperandType())) {
if (CalculationUtil.evaluateExpression(String.valueOf(getSumFromEvidences(left.getPropertyKey(), evidences)), operator, right.getValue())) {
atomicResult.setEvidenceId(evidences.stream().map(CaseEvidence::getId).collect(Collectors.joining(",")));
atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode());
modelAtomicResultService.saveOrUpdate(atomicResult);
return true;
}
}
break;
case AGGREGATE_TYPE_COUNT:
if (OPERAND_TYPE_STRUCTURE.equals(right.getOperandType())) {
List<CaseEvidence> rightEvidences = getEvidencesByPromptId(rightModelAtomicIndex.getPromptId(), caseEvidences, evidenceDirectories, notePrompts);
if (CalculationUtil.evaluateExpression(String.valueOf(evidences.size()), operator, String.valueOf(rightEvidences.size()))) {
atomicResult.setEvidenceId(evidences.stream().map(CaseEvidence::getId).collect(Collectors.joining(",")));
atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode());
modelAtomicResultService.saveOrUpdate(atomicResult);
return true;
}
} else if (OPERAND_TYPE_VALUE.equals(right.getOperandType())) {
if (CalculationUtil.evaluateExpression(String.valueOf(evidences.size()), operator, right.getValue())) {
atomicResult.setEvidenceId(evidences.stream().map(CaseEvidence::getId).collect(Collectors.joining(",")));
atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode());
modelAtomicResultService.saveOrUpdate(atomicResult);
return true;
}
}
break;
case AGGREGATE_TYPE_ANY:
if (OPERAND_TYPE_STRUCTURE.equals(right.getOperandType())) {
List<CaseEvidence> rightEvidences = getEvidencesByPromptId(rightModelAtomicIndex.getPromptId(), caseEvidences, evidenceDirectories, notePrompts);
Set<String> leftValueSet = getValueSetFromEvidences(left, evidences);
Set<String> rightValueSet = getValueSetFromEvidences(right, rightEvidences);
// 使用CalculationUtil.evaluateExpression方法遍历比较leftValueSet和rightValueSet的任一值一旦有一个满足返回true则return true
if (leftValueSet.stream().anyMatch(leftValue -> rightValueSet.stream().anyMatch(rightValue -> CalculationUtil.evaluateExpression(leftValue, operator, rightValue)))) {
atomicResult.setEvidenceId(evidences.stream().map(CaseEvidence::getId).collect(Collectors.joining(",")));
atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode());
modelAtomicResultService.saveOrUpdate(atomicResult);
return true;
}
} else if (OPERAND_TYPE_VALUE.equals(right.getOperandType())) {
Set<String> leftValueSet = getValueSetFromEvidences(left, evidences);
if (leftValueSet.stream().anyMatch(leftValue -> CalculationUtil.evaluateExpression(leftValue, operator, right.getValue()))) {
atomicResult.setEvidenceId(evidences.stream().map(CaseEvidence::getId).collect(Collectors.joining(",")));
atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode());
modelAtomicResultService.saveOrUpdate(atomicResult);
return true;
}
}
break;
default:
break;
}
} else {
log.error("证据不存在。提示词ID:{}", modelAtomicIndex.getPromptId());
}
return flag;
}
private Double getSumFromEvidences(String propertyKey, List<CaseEvidence> evidences) {
AtomicReference<Double> sum = new AtomicReference<>(0.0);
if (evidences != null && !evidences.isEmpty()) {
evidences.forEach(e -> {
List<NotePromptExtractAttributesDto> properties = e.getProperty();
if (properties != null && !properties.isEmpty()) {
properties.forEach(p -> {
if (p.getAttrName().equals(propertyKey)) {
if (StringUtils.isNotEmpty(p.getAttrValue())) {
sum.updateAndGet(v -> v + NumberUtil.parseDouble(p.getAttrValue()));
}
}
});
}
});
}
return sum.get();
}
private Set<String> getValueSetFromEvidences(Operand operand, List<CaseEvidence> evidences) {
Set<String> valueSet = new HashSet<>();
evidences.forEach(e -> {
List<NotePromptExtractAttributesDto> properties = e.getProperty();
if (properties != null && !properties.isEmpty()) {
properties.forEach(p -> {
if (p.getAttrName().equals(operand.getPropertyKey())) {
if (StringUtils.isNotEmpty(p.getAttrValue())) {
valueSet.add(p.getAttrValue());
}
}
});
}
});
return valueSet;
}
/**
* ID
*
* @param promptId ID
* @param caseEvidences
* @param evidenceDirectories
* @param notePrompts
* @return
*/
private static List<CaseEvidence> getEvidencesByPromptId(String promptId, List<CaseEvidence> caseEvidences, List<EvidenceDirectory> evidenceDirectories, List<NotePrompt> notePrompts) {
List<CaseEvidence> evidences = new ArrayList<>();
NotePrompt notePrompt = notePrompts.stream().filter(n -> n.getId().equals(promptId)).findAny().orElse(null);
if (notePrompt == null) {
log.error("提示词不存在。提示词ID:{}", promptId);
return evidences;
}
List<EvidenceDirectory> directories = evidenceDirectories.stream().filter(e -> e.getCategoryId().equals(notePrompt.getEvidenceCategoryId())).toList();
List<String> directoryIds = directories.stream().map(EvidenceDirectory::getId).toList();
evidences = caseEvidences.stream().filter(e -> directoryIds.contains(e.getDirectoryId())).toList();
return evidences;
}
/**
*
9 months ago
*
* @param analyseCaseDTO
* @param result
* @param atomicIndex
*/
private void manuallyDefinedCase(AnalyseCaseDTO analyseCaseDTO, ModelAtomicResult result, ModelAtomicIndex atomicIndex) {
List<ModelAtomicResult> modelAtomicResults = modelAtomicResultMapper.selectList(
new LambdaQueryWrapper<ModelAtomicResult>().eq(ModelAtomicResult::getCaseId, analyseCaseDTO.getCaseId())
.eq(ModelAtomicResult::getAtomicId, atomicIndex.getId()));
9 months ago
if (CollUtil.isEmpty(modelAtomicResults)) {
log.info("manuallyDefinedCase:根据caseId:{},atomicId:{}未找到原子指标结果", analyseCaseDTO.getCaseId(), atomicIndex.getId());
return;
}
9 months ago
if (CollUtil.size(modelAtomicResults) > 0) {
log.warn("manuallyDefinedCase:根据caseId:{},atomicId:{}找到多个原子指标结果", analyseCaseDTO.getCaseId(), atomicIndex.getId());
}
ModelAtomicResult modelAtomicResult = CollUtil.getFirst(modelAtomicResults);
9 months ago
result.setAtomicResult(modelAtomicResult.getAtomicResult());
}
@Override
public CaseScoreDetailDTO caseScoreDetail(String caseId) {
Assert.notEmpty(caseId, "案件id不能为空");
CaseScoreDetailBuilder caseScoreDetailBuilder = new CaseScoreDetailBuilder()
.setOllamaChatClient(null)
.setMapper(modelCaseMapper, casePersonMapper, modelAtomicIndexMapper,
modelIndexResultMapper, modelIndexMapper, modelAtomicResultMapper);
caseScoreDetailBuilder.loadCaseScoreDetail(caseId);
List<EvidenceDirectoryDTO> evidenceDirectoryDTOS = evidenceDirectoryService.listDirectoryTree(caseId);
List<EvidenceCategoryDTO> evidenceCategoryDTOS = evidenceCategoryService.listCategoryTree(caseScoreDetailBuilder.getCaseType());
caseScoreDetailBuilder.setEvidence(new EvidenceDirectoryDTO(evidenceDirectoryDTOS), new EvidenceCategoryDTO(evidenceCategoryDTOS));
return caseScoreDetailBuilder.build();
}
@Override
public CaseScore caseScoreByCaseId(String caseId) {
CaseScoreDetailBuilder caseScoreDetailBuilder = new CaseScoreDetailBuilder()
.setOllamaChatClient(null)
.setMapper(modelCaseMapper, casePersonMapper, modelAtomicIndexMapper,
modelIndexResultMapper, modelIndexMapper, modelAtomicResultMapper);
caseScoreDetailBuilder.loadCaseScoreDetail(caseId);
CaseScore caseScore = new CaseScore();
caseScore.setCommonScore(caseScoreDetailBuilder.getCommonScore());
caseScore.setCrimeScore(caseScoreDetailBuilder.getCrimeScore());
caseScore.setCrimeOutScore(caseScoreDetailBuilder.getCrimeOutScore());
return caseScore;
}
@Override
public CaseStatus getCaseDateStatus(String caseId) {
Assert.notEmpty(caseId, "案件id不能为空");
ModelCase modelCase = modelCaseMapper.selectById(caseId);
Assert.notNull(modelCase, "案件不存在");
return new CaseStatus(modelCase.getCaseDataStatus(), modelCase.getCaseAnalysisStatus());
}
@Override
public void exportCaseScoreDetail(String caseId, HttpServletResponse response) {
CaseScoreDetailDTO caseScoreDetailDTO = caseScoreDetail(caseId);
caseScoreDetailDTO.buildDesc();
// 加载模板
Resource resource = resourceLoader.getResource("classpath:template/case_detail.docx");
InputStream inputStream = null;
try {
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
9 months ago
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(caseScoreDetailDTO.getCaseName() + ".docx", StandardCharsets.UTF_8));
inputStream = resource.getInputStream();
XWPFTemplate template = XWPFTemplate.compile(inputStream).render(caseScoreDetailDTO);
template.writeAndClose(response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
9 months ago
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error("exportCaseScoreDetail: inputStream.close() error", e);
}
}
}
}
/**
*
*/
private void calculateFinalScore(AnalyseCaseDTO analyseCaseDTO, ModelCase modelCase, Map<String, Map<String, String>> atomicResultMap) {
// 根据案件类型获取所有的指标
List<ModelIndex> modelIndices = modelIndexService.list(new LambdaQueryWrapper<ModelIndex>().eq(ModelIndex::getDataStatus, "1").eq(ModelIndex::getCaseType, modelCase.getCaseType()));
Map<String, Integer> typeScoreMap = new HashMap<>();
10 months ago
for (ModelIndex modelIndex : modelIndices) {
ModelIndexResult result = new ModelIndexResult();
result.setCaseId(analyseCaseDTO.getCaseId());
result.setIndexId(modelIndex.getId());
Set<String> atomicIds = new HashSet<>();
// 判断逻辑是否为空,如果不为空,就根据判断逻辑进行判断
10 months ago
if (StringUtils.isNotEmpty(modelIndex.getJudgeLogic())) {
List<JudgeLogic> judgeLogics = JSONUtil.toList(modelIndex.getJudgeLogic(), JudgeLogic.class);
if (CollUtil.isNotEmpty(judgeLogics)) {
boolean finalJudgeResult = false;
// 遍历组
for (int i = 0; i < judgeLogics.size(); i++) {
// 组内结果
boolean innerGroupJudge = false;
JudgeLogic logic = judgeLogics.get(i);
// 获取组之间的的判断逻辑
String rowLogic = logic.getRowLogic();
// 首先对组内进行判断,判断组内的结果
List<AtomicData> atomicData = logic.getAtomicData();
for (int j = 0; j < atomicData.size(); j++) {
AtomicData data = atomicData.get(j);
atomicIds.add(data.getAtomicIndex());
// 先找到原子指标对应的大指标的结果
Map<String, String> atomicIndexMap = atomicResultMap.get(data.getAtomicIndex());
String atomicIndexResult;
if (CollUtil.isEmpty(atomicIndexMap)) {
atomicIndexResult = JudgeResultEnum.UNKNOWN.getCode();
} else {
// 这里可能不存在,如果未找到,就默认为false
atomicIndexResult = atomicIndexMap.getOrDefault(modelIndex.getId(), JudgeResultEnum.UNKNOWN.getCode());
}
String relationalSymbol = data.getRelationalSymbol();
9 months ago
JudgeResultEnum instance = JudgeResultEnum.getInstance(relationalSymbol);
boolean ato = StrUtil.equals(atomicIndexResult, instance.getCode());
if (j == 0) {
innerGroupJudge = ato;
} else {
if ("1".equals(rowLogic)) {
innerGroupJudge = innerGroupJudge && ato;
} else if ("2".equals(rowLogic)) {
innerGroupJudge = innerGroupJudge || ato;
}
}
10 months ago
}
9 months ago
// 组间进行判断
String groupLogic = logic.getGroupLogic();
if (i == 0) {
finalJudgeResult = innerGroupJudge;
10 months ago
} else {
// 如果组间判断为1 与,则进行与操作
if ("1".equals(groupLogic)) {
finalJudgeResult = finalJudgeResult && innerGroupJudge;
// 如果组间判断为或,则进行或操作
} else if ("2".equals(groupLogic)) {
finalJudgeResult = finalJudgeResult || innerGroupJudge;
10 months ago
}
}
}
result.setIndexResult(finalJudgeResult ? "true" : "false");
result.setAtomicIds(StringUtils.join(atomicIds, ","));
10 months ago
}
}
// 最后保存结果
10 months ago
ModelIndexResult exist = modelIndexResultMapper.selectByCaseIdAndIndexId(analyseCaseDTO.getCaseId(), modelIndex.getId());
if (exist == null) {
modelIndexResultMapper.insert(result);
} else {
result.setId(exist.getId());
modelIndexResultMapper.updateById(result);
}
if ("true".equals(result.getIndexResult())) {
Integer orDefault = typeScoreMap.getOrDefault(modelIndex.getIndexType(), 0);
typeScoreMap.put(modelIndex.getIndexType(), orDefault + modelIndex.getIndexScore());
10 months ago
}
}
// 计算分数 共性+入罪/共性+出罪 取最大值
Integer gx = typeScoreMap.getOrDefault("1", 0);
Integer rz = typeScoreMap.getOrDefault("2", 0);
Integer cz = typeScoreMap.getOrDefault("3", 0);
int max = Integer.max(gx + rz, gx + cz);
modelCase.setTotalScore(max);
10 months ago
modelCaseMapper.updateById(modelCase);
}
9 months ago
private void analyseGraphCase(AnalyseCaseDTO analyseCaseDTO, ModelAtomicResult result, String ql, String caseActorName) {
Session session = driver.session();
//图谱
int i = 1;
Map<String, Object> params = new HashMap<>();
// 行为人
9 months ago
params.put("lawActor", caseActorName);
// 案号
params.put("caseId", analyseCaseDTO.getCaseId());
// 参数中是否传了受害人
String lawPartys = analyseCaseDTO.getLawParty();
// 如果有受害人的话就进行分割
String[] split = StringUtils.isEmpty(lawPartys) ? new String[0] : lawPartys.split(",");
if (ql.contains("$lawParty") && split.length > 1) {
i = split.length;
}
10 months ago
// 只有有符合的,就认为符合,不进行遍历了
judge:
for (int j = 0; j < i; j++) {
if (split.length > 0) {
params.put("lawParty", split[j]);
}
Result run;
try {
run = session.run(ql, params);
} catch (Exception e) {
9 months ago
result.setAtomicResult("-1");
9 months ago
log.error("图数据库查询出现错误,查询语句{},参数{}", ql, JSONUtil.toJsonStr(params), e);
return;
}
List<ResultDTO> res = Neo4jUtils.getResultDTOList(run);
if (res.isEmpty()) {
result.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode());
} else {
9 months ago
// 设置为0,不存在
result.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode());
10 months ago
// 进行遍历,如果有存在的,就设置为有
for (ResultDTO resultDTO : res) {
if (StringUtils.isNotEmpty(resultDTO.getRelId())) {
//存在关系
result.setAtomicResult(JudgeResultEnum.EXIST.getCode());
10 months ago
result.setRecordId(resultDTO.getRecordId());
// 在退出循环之前先合并相关文本分片id
String recordSplitIdJoin = res.stream().filter(r ->
StringUtils.isNotEmpty(r.getRelId())
&& StringUtils.isNotEmpty(r.getRecordSplitId()))
.map(ResultDTO::getRecordSplitId).collect(Collectors.joining(","));
result.setRecordSplitId(recordSplitIdJoin);
10 months ago
// 如果只要存在,就不进行校验了,直接跳出循环
break judge;
}
}
}
}
}
/**
*
9 months ago
*
* @param analyseCaseDTO
* @param result
* @param sql
*/
private void analyseDataBaseCase(AnalyseCaseDTO analyseCaseDTO, ModelAtomicResult result, String sql, String caseActorName) {
Map<String, Object> params = new HashMap<>();
params.put("caseId", result.getCaseId());
params.put("evidenceName", analyseCaseDTO.getEvidenceName());
params.put("provider", null);
9 months ago
params.put("party_a", caseActorName);
params.put("party_b", analyseCaseDTO.getLawParty());
boolean success = false;
9 months ago
if (modelIndexService.checkSql(sql)) {
success = parseResult(rowSqlMapper.selectList(sql, params, Map.class));
}
result.setAtomicResult(success ? JudgeResultEnum.EXIST.getCode() : JudgeResultEnum.NOT_EXIST.getCode());
}
/**
*
* 1. 11=100=0
9 months ago
* 2.
*
* @param mapList
* @return
*/
private boolean parseResult(List<Map> mapList) {
if (CollUtil.isEmpty(mapList)) {
return false;
}
9 months ago
if (CollUtil.size(mapList) > 1) {
return true;
}
Map firstRow = CollUtil.getFirst(mapList);
9 months ago
if (firstRow.size() == 1 && CollUtil.size(firstRow.values()) == 1) {
Object first = CollUtil.getFirst(firstRow.values());
if (NumberUtil.isNumber(first.toString())) {
return NumberUtil.parseInt(first.toString()) > 0;
}
}
return true;
}
10 months ago
}