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; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.deepoove.poi.XWPFTemplate; import com.supervision.common.constant.IndexRuleConstants; import com.supervision.common.domain.R; import com.supervision.common.utils.StringUtils; import com.supervision.constant.JudgeResultEnum; 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; import com.supervision.police.mapper.*; import com.supervision.police.mybatis.RowSqlMapper; import com.supervision.police.service.*; import com.supervision.utils.CalculationUtil; import com.supervision.utils.DifyApiUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; 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; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import static com.supervision.common.constant.IndexRuleConstants.*; import static com.supervision.common.constant.NotePromptConstants.TYPE_STRUCTURAL_REASONING; @Slf4j @Service @RequiredArgsConstructor public class ModelServiceImpl implements ModelService { private final ResourceLoader resourceLoader; private final Driver driver; private final ModelCaseMapper modelCaseMapper; private final ModelAtomicIndexMapper modelAtomicIndexMapper; private final ModelAtomicResultMapper modelAtomicResultMapper; private final ModelIndexMapper modelIndexMapper; private final ModelIndexResultMapper modelIndexResultMapper; 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; private final CaseEvidencePropertyService caseEvidencePropertyService; private final DifyApiUtil difyApiUtil; @Autowired private ModelCaseService modelCaseService; @Override @Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class) public R analyseCase(AnalyseCaseDTO analyseCaseDTO) { ModelCase modelCase = modelCaseMapper.selectById(analyseCaseDTO.getCaseId()); // 获取案件行为人ID CasePerson casePerson = casePersonMapper.selectOne(new LambdaQueryWrapper() .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()); } // 首先将原先的值进行赋值,设置到pre_result modelIndexResultMapper.updatePreResult(analyseCaseDTO.getCaseId()); //原子指标 List atomicIndices = modelAtomicIndexMapper.selectByCaseType(modelCase.getCaseType()); // 存放原子指标的结果,key:原子指标ID,value:(key大指标ID,value:结果) Map> atomicResultMap = new HashMap<>(); for (ModelAtomicIndex atomicIndex : atomicIndices) { //原子指标结果 ModelAtomicResult result = new ModelAtomicResult(); result.setCasePersonId(casePerson.getId()); result.setCaseId(analyseCaseDTO.getCaseId()); result.setAtomicId(atomicIndex.getId()); //查询语句 String ql = atomicIndex.getQueryLang(); //原子指标结果表 try { //查询图谱 index_source: 1人工定义 2数据库查询 3图谱生成 4大模型 if ("1".equals(atomicIndex.getIndexSource())) { // list manuallyDefinedCase(analyseCaseDTO, result, atomicIndex); } else if ("2".equals(atomicIndex.getIndexSource()) && StringUtils.isNotEmpty(ql)) { // analyseDataBaseCase(analyseCaseDTO, result, ql, casePerson.getName()); } else if ("3".equals(atomicIndex.getIndexSource()) && StringUtils.isNotEmpty(ql)) { // 使用知识图谱进行计算 analyseGraphCase(analyseCaseDTO, result, ql, casePerson.getName()); } else if ("4".equals(atomicIndex.getIndexSource())) { // } else if ("5".equals(atomicIndex.getIndexSource())) { // todo: 结构化推理 //analyseStructuredInference(analyseCaseDTO, result); } } catch (Exception e) { log.error(e.getMessage(), e); } // 根据原子指标ID查model_index_atomic_relation表所有的指标ID List 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 indexMap = atomicResultMap.computeIfAbsent( result.getAtomicId(), k -> new HashMap<>() // 如果不存在则创建一个新的 HashMap ); indexMap.put(relation.getModelIndexId(), result.getAtomicResult()); } } // 最终计算得分 calculateFinalScore(analyseCaseDTO, modelCase, atomicResultMap); caseStatusManageService.whenAnalyseCaseSuccess(analyseCaseDTO.getCaseId(), modelCase.getTotalScore()); // 计算完成之后,把所有的笔录上传到模型 difyApiUtil.syncCaseFileToDifyKnowledgeBase(modelCase, modelCaseService.listCaseFileIds(analyseCaseDTO.getCaseId())); return R.ok(); } @Override public R analyseCaseNew(AnalyseCaseDTO analyseCaseDTO) { log.info("数据准备阶段"); String caseId = analyseCaseDTO.getCaseId(); Map typeScoreMap = new HashMap<>(); ModelCase modelCase = modelCaseMapper.selectById(caseId); if (modelCase == null) { log.error("未找到案件信息:【{}】", caseId); return R.fail("未找到案件信息"); } CasePerson casePerson = casePersonMapper.selectOne(new LambdaQueryWrapper() .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)) { log.error("未找到的行为人:【{}】", analyseCaseDTO.getLawActorName()); return R.fail("未找到的行为人"); } List modelIndices = modelIndexService.list(new LambdaQueryWrapper().eq(ModelIndex::getDataStatus, "1").eq(ModelIndex::getCaseType, modelCase.getCaseType())); if (modelIndices.isEmpty()) { log.error("未找到指标信息:【{}】", modelCase.getCaseType()); return R.fail("未找到指标信息"); } List atomicIndices = modelAtomicIndexMapper.selectByCaseType(modelCase.getCaseType()); if (atomicIndices.isEmpty()) { log.error("未找到原子指标信息:【{}】", modelCase.getCaseType()); return R.fail("未找到原子指标信息"); } List notePrompts = notePromptService.list(new LambdaQueryWrapper().eq(NotePrompt::getType, TYPE_STRUCTURAL_REASONING)); if (notePrompts.isEmpty()) { log.error("未找到提示词信息:【{}】", TYPE_STRUCTURAL_REASONING); return R.fail("未找到提示词信息"); } // 查询提示词对应的属性 for (NotePrompt notePrompt : notePrompts) { notePrompt.setExtractAttributes(caseEvidencePropertyService.findExtractAttributes(notePrompt.getEvidenceCategoryId())); } List evidenceDirectories = evidenceDirectoryService.list(new LambdaQueryWrapper().eq(EvidenceDirectory::getCaseId, caseId)); if (evidenceDirectories.isEmpty()) { log.error("未找到证据目录信息:【{}】", caseId); return R.fail("未找到证据目录信息"); } List caseEvidences = caseEvidenceService.list(new LambdaQueryWrapper().eq(CaseEvidence::getCaseId, caseId)); caseEvidenceService.redoExtractAttributes(caseId, caseEvidences); List modelIndexAtomicRelations = modelIndexAtomicRelationService.list(); if (modelIndexAtomicRelations.isEmpty()) { log.error("未找到指标原子关系信息"); return R.fail("未找到指标原子关系信息"); } List modelAtomicResultList = modelAtomicResultService.lambdaQuery().eq(ModelAtomicResult::getCaseId, caseId).list(); log.info("开始计算指标结果"); // 遍历指标集合,处理每个指标的判断逻辑,得出结果 modelIndices.forEach(modelIndex -> { log.info("开始计算指标【{}】,ID:{}", modelIndex.getId(), modelIndex.getName()); IndexRule indexRule = modelIndex.getIndexRule(); Set ruleConditionGroupResultList = new HashSet<>(); if (indexRule != null) { indexRule.getRuleConditionGroupList().forEach(ruleConditionGroup -> { Set ruleConditionResultSet = new HashSet<>(); ruleConditionGroup.getRuleConditionList().forEach(ruleCondition -> { Set 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); if (modelAtomicIndex == null && !OPERAND_TYPE_STRUCTURE.equals(ruleCondition.getIndexSource())) { log.error("原子指标不存在,跳出当前循环。原子指标ID:{}", ruleCondition.getAtomicIndexId()); return; } // 定义原子指标结果共有属性 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, evidenceDirectories, result)); break; case OPERAND_TYPE_GRAPH: operandUnitResultSet.add(relationSymbol == graphIndexAnalysis(casePerson.getName(), modelAtomicIndex.getQueryLang(), analyseCaseDTO.getCaseId(), ruleCondition, result)); break; case OPERAND_TYPE_STRUCTURE: if (ruleCondition.getOperandUnitList().isEmpty()) { log.info("结构化查询条件为空,直接设置为不存在并更新原子指标结果"); result.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode()); modelAtomicResultService.saveOrUpdate(result); } 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.setAtomicIds(modelIndexAtomicRelations.stream().filter(relation -> relation.getModelIndexId().equals(modelIndex.getId())).map(ModelIndexAtomicRelation::getAtomicIndexId).collect(Collectors.joining(","))); ModelIndexResult exist = modelIndexResultMapper.selectByCaseIdAndIndexId(analyseCaseDTO.getCaseId(), modelIndex.getId()); if (exist != null) { modelIndexResult.setId(exist.getId()); } modelIndexResult.setIndexResult(result ? "true" : "false"); // 先清除掉与指标失去关联的原子指标对应的结果 removeAtomicResultWithNoReference(modelIndex.getId(), modelIndexAtomicRelations, modelAtomicResultList); 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()); difyApiUtil.syncCaseFileToDifyKnowledgeBase(modelCase, modelCaseService.listCaseFileIds(caseId)); return R.ok(); } private void removeAtomicResultWithNoReference(String modelIndexId, List modelIndexAtomicRelations, List modelAtomicResultList) { List atomicIds = modelIndexAtomicRelations.stream() .filter(relation -> StrUtil.equals(relation.getModelIndexId(), modelIndexId)) .map(ModelIndexAtomicRelation::getAtomicIndexId).toList(); List modelAtomicResults = modelAtomicResultList.stream() .filter(atomicResult -> StrUtil.equals(atomicResult.getIndexId(), modelIndexId) && !atomicIds.contains(atomicResult.getAtomicId())).toList(); for (ModelAtomicResult modelAtomicResult : modelAtomicResults) { log.info("删除无引用的原子指标结果,指标id:{},原子指标ID:{}", modelIndexId,modelAtomicResult.getAtomicId()); modelAtomicResultMapper.deleteById(modelAtomicResult.getId()); } } /** * 人工定义指标分析 * * @param atomicIndexId 原子指标ID * @param caseId 案件ID */ private boolean manualIndexAnalysis(String atomicIndexId, String caseId) { boolean flag = false; List modelAtomicResults = modelAtomicResultMapper.selectList( new LambdaQueryWrapper().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 modelAtomicIndex 原子指标 * @param evidenceDirectories 证据目录 * @param atomicResult 原子指标结果 * @return */ private boolean dbIndexAnalysis(String caseId, ModelAtomicIndex modelAtomicIndex, List evidenceDirectories, ModelAtomicResult atomicResult) { Map params = new HashMap<>(); params.put("caseId", caseId); List mapList = rowSqlMapper.selectList(modelAtomicIndex.getQueryLang(), params, Map.class); boolean flag = false; if (mapList != null && !mapList.isEmpty()) { flag = evidenceDirectories.stream().anyMatch(evidenceDirectory -> StrUtil.equals(evidenceDirectory.getCategoryId(), modelAtomicIndex.getCategoryId())); 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 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 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 (StringUtils.isNotEmpty(ruleCondition.getOperator()) && StringUtils.isNotEmpty(ruleCondition.getValue()) && CalculationUtil.evaluateExpression(String.valueOf(count), ruleCondition.getOperator(), ruleCondition.getValue())) { flag = true; } modelAtomicResultService.saveOrUpdate(atomicResult); return flag; } /** * 结构化查询指标分析 * * @param operandUnit 操作单元 * @param modelAtomicIndexId 原子指标ID * @param atomicIndices 原子指标集合 * @param notePrompts 提示词集合 * @param evidenceDirectories 证据目录集合 * @param caseEvidences 证据集合 * @param atomicResult 原子指标结果 * @return 是否存在 */ private boolean structureIndexAnalysis(OperandUnit operandUnit, String modelAtomicIndexId, List atomicIndices, List notePrompts, List evidenceDirectories, List caseEvidences, ModelAtomicResult atomicResult) { Operand left = operandUnit.getLeftOperand(); String operator = operandUnit.getOperator(); Operand right = operandUnit.getRightOperand(); boolean flag = false; ModelAtomicIndex modelAtomicIndex = atomicIndices.stream().filter(atomicIndex -> atomicIndex.getId().equals(modelAtomicIndexId)).findAny().orElse(null); if (modelAtomicIndex == null) { log.error("原子指标不存在。原子指标ID:{}", modelAtomicIndexId); atomicResult.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); return flag; } List evidences = getEvidencesByPromptId(modelAtomicIndex.getPromptId(), caseEvidences, evidenceDirectories, notePrompts); atomicResult.setEvidenceId(evidences.stream().map(CaseEvidence::getId).collect(Collectors.joining(","))); 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()); atomicResult.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); 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())) { log.info("左操作数总和:【{}】,操作符:【{}】,右操作数:【{}】", getSumFromEvidences(left.getPropertyKey(), evidences), operator, right.getValue()); List rightEvidences = getEvidencesByPromptId(rightModelAtomicIndex.getPromptId(), caseEvidences, evidenceDirectories, notePrompts); if (CalculationUtil.evaluateExpression(String.valueOf(getSumFromEvidences(left.getPropertyKey(), evidences)), operator, String.valueOf(getSumFromEvidences(right.getPropertyKey(), rightEvidences)))) { atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); return true; } } else if (OPERAND_TYPE_VALUE.equals(right.getOperandType())) { log.info("左操作数总和:【{}】,操作符:【{}】,右操作数:【{}】", getSumFromEvidences(left.getPropertyKey(), evidences), operator, right.getValue()); if (CalculationUtil.evaluateExpression(String.valueOf(getSumFromEvidences(left.getPropertyKey(), evidences)), operator, right.getValue())) { atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); return true; } } break; case AGGREGATE_TYPE_COUNT: if (OPERAND_TYPE_STRUCTURE.equals(right.getOperandType())) { log.info("左操作数数量:【{}】,操作符:【{}】,右操作数:【{}】", evidences.size(), operator, right.getValue()); List rightEvidences = getEvidencesByPromptId(rightModelAtomicIndex.getPromptId(), caseEvidences, evidenceDirectories, notePrompts); if (CalculationUtil.evaluateExpression(String.valueOf(evidences.size()), operator, String.valueOf(rightEvidences.size()))) { atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); return true; } } else if (OPERAND_TYPE_VALUE.equals(right.getOperandType())) { log.info("左操作数数量:【{}】,操作符:【{}】,右操作数:【{}】", evidences.size(), operator, right.getValue()); if (CalculationUtil.evaluateExpression(String.valueOf(evidences.size()), operator, right.getValue())) { atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); return true; } } break; case AGGREGATE_TYPE_ANY: if (OPERAND_TYPE_STRUCTURE.equals(right.getOperandType())) { List rightEvidences = getEvidencesByPromptId(rightModelAtomicIndex.getPromptId(), caseEvidences, evidenceDirectories, notePrompts); Set leftValueSet = getValueSetFromEvidences(left, evidences); Set rightValueSet = getValueSetFromEvidences(right, rightEvidences); log.info("左操作数值集合:【{}】,操作符:【{}】,右操作数:【{}】", leftValueSet, operator, right.getValue()); // 使用CalculationUtil.evaluateExpression方法遍历比较leftValueSet和rightValueSet的任一值,一旦有一个满足(返回true),则return true if (leftValueSet.stream().anyMatch(leftValue -> rightValueSet.stream().anyMatch(rightValue -> CalculationUtil.evaluateExpression(leftValue, operator, rightValue)))) { atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); return true; } } else if (OPERAND_TYPE_VALUE.equals(right.getOperandType())) { Set leftValueSet = getValueSetFromEvidences(left, evidences); log.info("左操作数值集合:【{}】,操作符:【{}】,右操作数:【{}】", leftValueSet, operator, right.getValue()); if (leftValueSet.stream().anyMatch(leftValue -> CalculationUtil.evaluateExpression(leftValue, operator, right.getValue()))) { atomicResult.setAtomicResult(JudgeResultEnum.EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); return true; } } break; default: atomicResult.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); break; } atomicResult.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); } else { log.error("证据不存在。提示词ID:{}", modelAtomicIndex.getPromptId()); atomicResult.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode()); modelAtomicResultService.saveOrUpdate(atomicResult); } return flag; } private Double getSumFromEvidences(String propertyKey, List evidences) { AtomicReference sum = new AtomicReference<>(0.0); if (evidences != null && !evidences.isEmpty()) { evidences.forEach(e -> { List 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 getValueSetFromEvidences(Operand operand, List evidences) { Set valueSet = new HashSet<>(); evidences.forEach(e -> { List 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 getEvidencesByPromptId(String promptId, List caseEvidences, List evidenceDirectories, List notePrompts) { List 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 directories = evidenceDirectories.stream().filter(e -> e.getCategoryId().equals(notePrompt.getEvidenceCategoryId())).toList(); List directoryIds = directories.stream().map(EvidenceDirectory::getId).toList(); evidences = caseEvidences.stream().filter(e -> directoryIds.contains(e.getDirectoryId())).toList(); return evidences; } /** * 手动定义原子指标处理 * * @param analyseCaseDTO 案件信息 * @param result 原子指标结果 * @param atomicIndex 原子指标 */ private void manuallyDefinedCase(AnalyseCaseDTO analyseCaseDTO, ModelAtomicResult result, ModelAtomicIndex atomicIndex) { List modelAtomicResults = modelAtomicResultMapper.selectList( new LambdaQueryWrapper().eq(ModelAtomicResult::getCaseId, analyseCaseDTO.getCaseId()) .eq(ModelAtomicResult::getAtomicId, atomicIndex.getId())); if (CollUtil.isEmpty(modelAtomicResults)) { log.info("manuallyDefinedCase:根据caseId:{},atomicId:{}未找到原子指标结果", analyseCaseDTO.getCaseId(), atomicIndex.getId()); return; } if (CollUtil.size(modelAtomicResults) > 0) { log.warn("manuallyDefinedCase:根据caseId:{},atomicId:{}找到多个原子指标结果", analyseCaseDTO.getCaseId(), atomicIndex.getId()); } ModelAtomicResult modelAtomicResult = CollUtil.getFirst(modelAtomicResults); 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 evidenceDirectoryDTOS = evidenceDirectoryService.listDirectoryTree(caseId); List 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"); 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); } 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> atomicResultMap) { // 根据案件类型获取所有的指标 List modelIndices = modelIndexService.list(new LambdaQueryWrapper().eq(ModelIndex::getDataStatus, "1").eq(ModelIndex::getCaseType, modelCase.getCaseType())); Map typeScoreMap = new HashMap<>(); for (ModelIndex modelIndex : modelIndices) { ModelIndexResult result = new ModelIndexResult(); result.setCaseId(analyseCaseDTO.getCaseId()); result.setIndexId(modelIndex.getId()); Set atomicIds = new HashSet<>(); // 判断逻辑是否为空,如果不为空,就根据判断逻辑进行判断 if (StringUtils.isNotEmpty(modelIndex.getJudgeLogic())) { List 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 = logic.getAtomicData(); for (int j = 0; j < atomicData.size(); j++) { AtomicData data = atomicData.get(j); atomicIds.add(data.getAtomicIndex()); // 先找到原子指标对应的大指标的结果 Map 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(); 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; } } } // 组间进行判断 String groupLogic = logic.getGroupLogic(); if (i == 0) { finalJudgeResult = innerGroupJudge; } else { // 如果组间判断为1 与,则进行与操作 if ("1".equals(groupLogic)) { finalJudgeResult = finalJudgeResult && innerGroupJudge; // 如果组间判断为或,则进行或操作 } else if ("2".equals(groupLogic)) { finalJudgeResult = finalJudgeResult || innerGroupJudge; } } } result.setIndexResult(finalJudgeResult ? "true" : "false"); result.setAtomicIds(StringUtils.join(atomicIds, ",")); } } // 最后保存结果 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()); } } // 计算分数 共性+入罪/共性+出罪 取最大值 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); modelCaseMapper.updateById(modelCase); } private void analyseGraphCase(AnalyseCaseDTO analyseCaseDTO, ModelAtomicResult result, String ql, String caseActorName) { Session session = driver.session(); //图谱 int i = 1; Map params = new HashMap<>(); // 行为人 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; } // 只有有符合的,就认为符合,不进行遍历了 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) { result.setAtomicResult("-1"); log.error("图数据库查询出现错误,查询语句{},参数{}", ql, JSONUtil.toJsonStr(params), e); return; } List res = Neo4jUtils.getResultDTOList(run); if (res.isEmpty()) { result.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode()); } else { // 设置为0,不存在 result.setAtomicResult(JudgeResultEnum.NOT_EXIST.getCode()); // 进行遍历,如果有存在的,就设置为有 for (ResultDTO resultDTO : res) { if (StringUtils.isNotEmpty(resultDTO.getRelId())) { //存在关系 result.setAtomicResult(JudgeResultEnum.EXIST.getCode()); 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); // 如果只要存在,就不进行校验了,直接跳出循环 break judge; } } } } } /** * 分析数据库类型的原子信息 * * @param analyseCaseDTO * @param result * @param sql */ private void analyseDataBaseCase(AnalyseCaseDTO analyseCaseDTO, ModelAtomicResult result, String sql, String caseActorName) { Map params = new HashMap<>(); params.put("caseId", result.getCaseId()); params.put("evidenceName", analyseCaseDTO.getEvidenceName()); params.put("provider", null); params.put("party_a", caseActorName); params.put("party_b", analyseCaseDTO.getLawParty()); boolean success = false; if (modelIndexService.checkSql(sql)) { success = parseResult(rowSqlMapper.selectList(sql, params, Map.class)); } result.setAtomicResult(success ? JudgeResultEnum.EXIST.getCode() : JudgeResultEnum.NOT_EXIST.getCode()); } /** * 执行结果分析: * 1. 如果查询出的结果只有一行,判断列数是否大于1,如果大于1,返回真,如果=1,继续判断值是否大于0,如果大于0,返回真,如果=0,返回假 * 2. 如果查询出的结果大于一行,则返回真 * * @param mapList 查询结果 * @return */ private boolean parseResult(List mapList) { if (CollUtil.isEmpty(mapList)) { return false; } if (CollUtil.size(mapList) > 1) { return true; } Map firstRow = CollUtil.getFirst(mapList); 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; } }