Merge branch 'dev_schedule' into dev_1.0.0

# Conflicts:
#	docker/docker-compose/init.sql
#	src/main/java/com/supervision/police/service/NoteRecordSplitService.java
#	src/main/java/com/supervision/police/service/impl/NoteRecordSplitServiceImpl.java
topo_dev
xueqingkun 9 months ago
commit aa8d5490f6

@ -90,57 +90,57 @@ CREATE TABLE `com_dictionary` (
-- ----------------------------
-- Records of com_dictionary
-- ----------------------------
INSERT INTO `com_dictionary` VALUES (1, NULL, '案件类型', 0, 'case_type', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (2, '1', '工程类合同诈骗案', 1, 'case_type', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (3, NULL, '指标来源', 0, 'index_source', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (4, '1', '人工定义', 3, 'index_source', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (5, '2', '数据库查询', 3, 'index_source', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (6, '3', '图谱生成', 3, 'index_source', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (7, '4', '大模型', 3, 'index_source', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (8, NULL, '状态', 0, 'connect_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (9, '1', '已关联', 8, 'connect_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (10, '2', '未关联', 8, 'connect_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (11, NULL, '判断结果', 0, 'judge_result', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (14, '3', '存在', 11, 'judge_result', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (15, '4', '不存在', 11, 'judge_result', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (16, '5', '未知', 11, 'judge_result', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (17, NULL, '指标类别', 0, 'index_type', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (18, '1', '共性指标', 17, 'index_type', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (19, '2', '入罪指标', 17, 'index_type', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (20, '3', '出罪指标', 17, 'index_type', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (21, NULL, '作案方式', 0, 'crime_mode', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (22, '1', '自动投案', 21, 'crime_mode', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (23, NULL, '案件状态', 0, 'case_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (24, '1', '已立案', 23, 'case_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (25, NULL, '认定结果', 0, 'identify_result', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (26, '1', '证据不足', 25, 'identify_result', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (27, '2', '事实不清', 25, 'identify_result', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (28, '3', '证据充分', 25, 'identify_result', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (29, NULL, '逻辑运算符', 0, 'logic_symbol', '1', NULL, NULL, NULL, '2024-07-06 15:10:29', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (30, '1', '', 29, 'logic_symbol', '1', NULL, NULL, NULL, '2024-07-06 15:11:02', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (31, '2', '', 29, 'logic_symbol', '1', NULL, NULL, NULL, '2024-07-06 15:11:38', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (32, NULL, '案件角色', 0, 'case_role', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (33, '1', '行为人', 32, 'case_role', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (34, '2', '嫌疑人', 32, 'case_role', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (35, '3', '受害人', 32, 'case_role', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (36, '4', '证人', 32, 'case_role', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (40, NULL, '证据类型', 0, 'evidence_type', '1', NULL, NULL, '2024-07-16 11:28:16', '2024-07-16 11:28:16', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (41, '1', '书证', 40, 'evidence_type', '1', NULL, NULL, '2024-07-16 11:34:18', '2024-07-16 11:34:18', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (42, '2', '物证', 40, 'evidence_type', '1', NULL, NULL, '2024-08-06 15:10:31', '2024-07-16 11:36:33', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (43, '3', '供述', 40, 'evidence_type', '1', NULL, NULL, '2024-08-06 15:23:35', '2024-07-16 11:36:43', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (45, '4', '电子数据', 40, 'evidence_type', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (46, '5', '鉴定意见', 40, 'evidence_type', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (47, '6', '证人证言', 40, 'evidence_type', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (48, '7', '视听资料', 40, 'evidence_type', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (49, '8', '勘验笔录', 40, 'evidence_type', '1', NULL, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (50, '2', '已起诉', 23, 'case_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (51, '3', '未批捕取保', 23, 'case_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (52, '4', '未采取强制', 23, 'case_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (53, '5', '已逮捕未起诉', 23, 'case_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (54, '6', '直保', 23, 'case_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (55, '7', '刑事拘留', 23, 'case_status', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (56, '2', '口头传唤', 21, 'crime_mode', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (57, '3', '强制传唤', 21, 'crime_mode', '1', NULL, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (1, NULL, '案件类型', 0, 'case_type', '1', '1', 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (2, '1', '工程类合同诈骗案', 1, 'case_type', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (3, NULL, '指标来源', 0, 'index_source', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (4, '1', '人工定义', 3, 'index_source', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (5, '2', '数据库查询', 3, 'index_source', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (6, '3', '图谱生成', 3, 'index_source', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (7, '4', '大模型', 3, 'index_source', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (8, NULL, '状态', 0, 'connect_status', '1', 'ere', 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (9, '1', '已关联', 8, 'connect_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (10, '2', '未关联', 8, 'connect_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (11, NULL, '判断结果', 0, 'judge_result', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (14, '3', '存在', 11, 'judge_result', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (15, '4', '不存在', 11, 'judge_result', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (16, '5', '未知', 11, 'judge_result', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (17, NULL, '指标类别', 0, 'index_type', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (18, '1', '共性指标', 17, 'index_type', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (19, '2', '入罪指标', 17, 'index_type', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (20, '3', '出罪指标', 17, 'index_type', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (21, NULL, '作案方式', 0, 'crime_mode', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (22, '1', '自动投案', 21, 'crime_mode', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (23, NULL, '案件状态', 0, 'case_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (24, '1', '已立案', 23, 'case_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (25, NULL, '认定结果', 0, 'identify_result', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (26, '1', '证据不足', 25, 'identify_result', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (27, '2', '事实不清', 25, 'identify_result', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (28, '3', '证据充分', 25, 'identify_result', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (29, NULL, '逻辑运算符', 0, 'logic_symbol', '1', NULL, 0, NULL, NULL, '2024-07-06 15:10:29', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (30, '1', '', 29, 'logic_symbol', '1', NULL, 0, NULL, '2024-08-26 15:53:36', '2024-07-06 15:11:02', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (31, '2', '', 29, 'logic_symbol', '1', NULL, 0, NULL, NULL, '2024-07-06 15:11:38', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (32, NULL, '案件角色', 0, 'case_role', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (33, '1', '行为人', 32, 'case_role', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (34, '2', '嫌疑人', 32, 'case_role', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (35, '3', '受害人', 32, 'case_role', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (36, '4', '证人', 32, 'case_role', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (40, NULL, '证据类型', 0, 'evidence_type', '1', NULL, 0, NULL, '2024-07-16 11:28:16', '2024-07-16 11:28:16', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (41, '1', '书证', 40, 'evidence_type', '1', NULL, 0, NULL, '2024-07-16 11:34:18', '2024-07-16 11:34:18', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (42, '2', '物证', 40, 'evidence_type', '1', NULL, 0, NULL, '2024-08-06 15:10:31', '2024-07-16 11:36:33', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (43, '3', '供述', 40, 'evidence_type', '1', NULL, 0, NULL, '2024-08-06 15:23:35', '2024-07-16 11:36:43', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (45, '4', '电子数据', 40, 'evidence_type', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (46, '5', '鉴定意见', 40, 'evidence_type', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (47, '6', '证人证言', 40, 'evidence_type', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (48, '7', '视听资料', 40, 'evidence_type', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (49, '8', '勘验笔录', 40, 'evidence_type', '1', NULL, 0, NULL, NULL, NULL, NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (50, '2', '已起诉', 23, 'case_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (51, '3', '未批捕取保', 23, 'case_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (52, '4', '未采取强制', 23, 'case_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (53, '5', '已逮捕未起诉', 23, 'case_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (54, '6', '直保', 23, 'case_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (55, '7', '刑事拘留', 23, 'case_status', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (56, '2', '口头传唤', 21, 'crime_mode', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
INSERT INTO `com_dictionary` VALUES (57, '3', '强制传唤', 21, 'crime_mode', '1', NULL, 0, NULL, NULL, '2024-07-01 11:24:22', NULL, '1', NULL, NULL);
-- ----------------------------
-- Table structure for evidence_file

@ -3,5 +3,9 @@ package com.supervision.police.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.police.domain.NotePrompt;
import java.util.List;
public interface NotePromptService extends IService<NotePrompt> {
List<NotePrompt> listPromptBySplitId(String recordSplitId);
}

@ -11,4 +11,7 @@ public interface NoteRecordService extends IService<NoteRecord> {
List<NoteRecordDTO> selectNoteRecordDTOList(NoteRecord noteRecord);
void uploadFileToLangChainChat(String caseId);
String saveOrUpdRecord(NoteRecord noteRecord);
}

@ -6,6 +6,7 @@ import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.police.vo.NoteRecordReqVO;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public interface NoteRecordSplitService extends IService<NoteRecordSplit> {
@ -16,5 +17,8 @@ public interface NoteRecordSplitService extends IService<NoteRecordSplit> {
void delRecords(String id);
NoteRecordSplit saveRecordSplit(NoteRecord record, String fileName, String question, String answer);
List<NoteRecordSplit> batchSaveRecordSplit(NoteRecord record, String fileId);
Map<String, Object> queryRecordList(NoteRecord noteRecord, Integer page, Integer size);
}

@ -0,0 +1,16 @@
package com.supervision.police.service;
import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NoteRecordSplit;
import java.util.List;
public interface RecordSplitClassifyService {
/**
*
* @param allTypeList
* @param splitList
*/
void classify(List<ModelRecordType> allTypeList, List<NoteRecordSplit> splitList);
}

@ -1,11 +0,0 @@
package com.supervision.police.service;
import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NoteRecordSplit;
import java.util.List;
public interface RecordSplitTypeService {
void type(List<ModelRecordType> allTypeList, List<NoteRecordSplit> splitList);
}

@ -3,33 +3,22 @@ package com.supervision.police.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.druid.util.StringUtils;
import com.supervision.police.domain.*;
import com.supervision.police.mapper.NotePromptMapper;
import com.supervision.police.mapper.NoteRecordSplitMapper;
import com.supervision.police.mapper.TripleInfoMapper;
import com.supervision.police.service.*;
import com.supervision.thread.TripleExtractThread;
import com.supervision.thread.TripleExtractThreadPool;
import com.supervision.thread.TripleExtractTask;
import com.supervision.thread.TripleExtractTaskPool;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.function.Consumer;
@Slf4j
@Service
@ -38,8 +27,6 @@ public class ExtractTripleInfoServiceImpl implements ExtractTripleInfoService {
private final CaseTaskRecordService caseTaskRecordService;
private final ModelRecordTypeService modelRecordTypeService;
private final NotePromptService notePromptService;
private final TripleInfoService tripleInfoService;
@ -49,125 +36,81 @@ public class ExtractTripleInfoServiceImpl implements ExtractTripleInfoService {
@Autowired
private NoteRecordSplitService noteRecordSplitService;
private final NotePromptTypeRelService notePromptTypeRelService;
@Async
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public void extractTripleInfo(String caseId, String name, String recordSplitId) {
// 首先获取所有切分后的笔录
Optional<NoteRecordSplit> optById = noteRecordSplitService.getOptById(recordSplitId);
if (optById.isEmpty()) {
log.info("{} 切分笔录不存在,跳过", recordSplitId);
log.warn("extractTripleInfo根据笔录片段id{}未找到切分笔录数据,不进行后续操作...", recordSplitId);
return;
}
NoteRecordSplit recordSplit = optById.get();
// 获取所有的分类
List<ModelRecordType> allTypeList = modelRecordTypeService.list();
Map<String, String> allTypeMap = allTypeList.stream().collect(Collectors.toMap(ModelRecordType::getRecordType, ModelRecordType::getId, (k1, k2) -> k1));
List<TripleInfo> tripleInfos = new ArrayList<>();
List<Future<TripleInfo>> futures = new ArrayList<>();
// 对切分后的笔录进行遍历
String recordType = recordSplit.getRecordType();
if (StrUtil.isBlank(recordType)) {
log.info("{} 切分笔录不属于任何类型,跳过", recordSplit.getId());
if (StrUtil.isEmpty(recordType)) {
log.warn("extractTripleInfo:笔录片段:{} 不存在任何分类信息,不进行后续操作...", recordSplit.getId());
return;
}
String[] split = recordType.split(";");
for (String typeName : split) {
String typeId = allTypeMap.get(typeName);
if (StrUtil.isBlank(typeId)) {
log.info("{} 切分笔录类型:{}未找到,跳过", recordSplit.getId(), typeName);
} else {
// 根据笔录类型找到所有的提取三元组的提示词
// 一个提示词可能关联多个类型,要进行拆分操作
List<NotePromptTypeRel> promptTypeRelList = notePromptTypeRelService.lambdaQuery().eq(NotePromptTypeRel::getTypeId, typeId).select(NotePromptTypeRel::getPromptId).list();
if (CollUtil.isEmpty(promptTypeRelList)) {
log.info("{} 切分笔录类型:{}无对应的提示词,跳过", recordSplit.getId(), typeName);
continue;
}
List<NotePrompt> prompts = notePromptService.lambdaQuery()
.in(NotePrompt::getId, promptTypeRelList.stream().map(NotePromptTypeRel::getPromptId).collect(Collectors.toSet()))
.list();
if (CollUtil.isEmpty(prompts)) {
log.info("{} 切分笔录类型:{}无对应的提示词,跳过", recordSplit.getId(), typeName);
} else {
// 遍历提示词进行提取
for (NotePrompt prompt : prompts) {
if (StringUtils.isEmpty(prompt.getPrompt())) {
log.info("{} 切分笔录类型:{}对应的提示词:{} 提示词模板为空,跳过", recordSplit.getId(), typeName, prompt.getId());
continue;
}
// task+1
caseTaskRecordService.taskCountIncrement(caseId, recordSplit.getNoteRecordId());
try {
log.info("提交任务到线程池中进行三元组提取");
TripleExtractThread tripleExtractThread = new TripleExtractThread(chatClient, caseId, recordSplit.getNoteRecordId(), recordSplit.getId(), prompt, recordSplit.getQuestion(), recordSplit.getAnswer());
Future<TripleInfo> submit = TripleExtractThreadPool.chatExecutor.submit(tripleExtractThread);
futures.add(submit);
log.info("三元组提取任务提交成功");
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
}
List<NotePrompt> notePromptList = notePromptService.listPromptBySplitId(recordSplitId);
if (CollUtil.isEmpty(notePromptList)){
log.warn("extractTripleInfo:笔录片段:{},笔录分类:{} 不属于任何提示词,不进行后续操作...", recordSplit.getId(),recordSplit.getRecordType());
return;
}
try {
log.info("休眠5秒,5秒之后再去查询三元组的结果,需要查询的任务数量为:{}", futures.size());
Thread.sleep(1000 * 5);
} catch (Exception e) {
log.error(e.getMessage(), e);
List<TripleExtractTask> taskList = notePromptList.stream()
.filter(prompt -> StrUtil.isNotBlank(prompt.getPrompt()))
.peek(prompt -> {
caseTaskRecordService.taskCountIncrement(caseId, recordSplit.getNoteRecordId());
log.info("extractTripleInfo:三元组抽取任务数量加1,笔录片段id:{}",prompt.getId());
})
.map(prompt -> new TripleExtractTask(chatClient, prompt, recordSplit,postExtractTriple())).toList();
if (CollUtil.isEmpty(taskList)){
log.info("extractTripleInfo:笔录片段:{} 没有可用的提示词,不提交任何任务...", recordSplit.getId());
return;
}
// 计数器
AtomicInteger atomicInteger = new AtomicInteger(0);
while (futures.size() > 0) {
Iterator<Future<TripleInfo>> iterator = futures.iterator();
while (iterator.hasNext()) {
Future<TripleInfo> future = iterator.next();
List<TripleInfo> tripleInfos = new ArrayList<>();
try {
log.info("extractTripleInfo:笔录片段:{}抽取任务成功提交{}个任务....",recordSplitId,taskList.size());
List<Future<TripleInfo>> futures = TripleExtractTaskPool.executor.invokeAll(taskList);
for (Future<TripleInfo> future : futures) {
try {
// 如果提取到结果,且不为空,就进行保存
if (future.isDone()) {
// 完成+1
caseTaskRecordService.finishCountIncrement(caseId, recordSplit.getNoteRecordId());
TripleInfo tripleInfo = future.get();
if (tripleInfo != null) {
tripleInfos.add(tripleInfo);
}
iterator.remove();
TripleInfo tripleInfo = future.get();
if (Objects.nonNull(tripleInfo)){
tripleInfos.add(tripleInfo);
}
} catch (Exception e) {
log.info("从线程中获取任务失败");
iterator.remove();
}
}
try {
int currentCount = atomicInteger.incrementAndGet();
if (currentCount > 1000) {
log.info("任务执行超时,遍历任务已执行:{}次,任务还剩余:{}个,不再继续执行", currentCount, futures.size());
// 将还在执行的线程中断
futures.forEach(future -> {
future.cancel(true);
// 完成+1
caseTaskRecordService.finishCountIncrement(caseId, recordSplit.getNoteRecordId());
});
break;
} catch (ExecutionException e) {
log.error("extractTripleInfo:笔录片段:{}三元组提取任务执行失败...",recordSplitId,e);
}
log.info("已检查{}遍,任务剩余{}个,休眠5s后继续检查", currentCount, futures.size());
Thread.sleep(1000 * 5);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
} catch (InterruptedException e) {
log.error("extractTripleInfo:笔录片段:{}三元组提取任务提交失败...",recordSplitId,e);
}
// 如果有提取到三元组信息
if (CollUtil.isNotEmpty(tripleInfos)) {
for (TripleInfo tripleInfo : tripleInfos) {
log.info("extractTripleInfo:笔录片段:{}三元组提取任务执行结束...,三元组信息入库:{}", recordSplitId,JSONUtil.toJsonStr(tripleInfo));
tripleInfoService.save(tripleInfo);
log.info("保存三元组信息{}", JSONUtil.toJsonStr(tripleInfo));
}
}else {
log.info("extractTripleInfo:笔录片段:{}三元组提取任务执行结束...,未提取到任何三元组信息...", recordSplitId);
}
log.info("三元组提取任务执行完毕,结束");
}
private Consumer<NoteRecordSplit> postExtractTriple() {
return (recordSplit) -> {
try{
caseTaskRecordService.finishCountIncrement(recordSplit.getCaseId(), recordSplit.getNoteRecordId());
log.info("postExtractTriple:抽取任务完成数量加1,笔录片段id:{}",recordSplit.getId());
}catch (Exception e){
log.error("postExtractTriple:笔录片段:{} 抽取任务执行后更新任务状态失败...",recordSplit.getId(),e);
}
};
}
}

@ -44,7 +44,8 @@ public class ModelRecordTypeServiceImpl extends ServiceImpl<ModelRecordTypeMappe
private final NoteRecordSplitMapper noteRecordSplitMapper;
private final NotePromptService notePromptService;
@Autowired
private NotePromptService notePromptService;
private final TripleInfoService tripleInfoService;
@ -278,7 +279,10 @@ public class ModelRecordTypeServiceImpl extends ServiceImpl<ModelRecordTypeMappe
}
if (caseTaskRecord.getStatus() == 0 || caseTaskRecord.getStatus() == 3) {
// 重新提交
caseTaskRecordService.lambdaUpdate().set(CaseTaskRecord::getStatus, 1).eq(CaseTaskRecord::getId, caseTaskRecord.getId()).update();
caseTaskRecordService.lambdaUpdate().set(CaseTaskRecord::getStatus, 1)
.set(CaseTaskRecord::getTaskCount,0)
.set(CaseTaskRecord::getFinishCount,0)
.eq(CaseTaskRecord::getId, caseTaskRecord.getId()).update();
List<ModelRecordType> allTypeList = modelRecordTypeService.lambdaQuery().list();
// 根据recordId查询所有的分割后的笔录
List<NoteRecordSplit> list = noteRecordSplitService.lambdaQuery().eq(NoteRecordSplit::getNoteRecordId, recordId).list();

@ -1,12 +1,88 @@
package com.supervision.police.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NotePrompt;
import com.supervision.police.domain.NotePromptTypeRel;
import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.police.mapper.NotePromptMapper;
import com.supervision.police.service.ModelRecordTypeService;
import com.supervision.police.service.NotePromptService;
import com.supervision.police.service.NotePromptTypeRelService;
import com.supervision.police.service.NoteRecordSplitService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class NotePromptServiceImpl extends ServiceImpl<NotePromptMapper, NotePrompt> implements NotePromptService {
private final NoteRecordSplitService noteRecordSplitService;
@Autowired
private ModelRecordTypeService modelRecordTypeService;
private final NotePromptTypeRelService notePromptTypeRelService;
@Override
public List<NotePrompt> listPromptBySplitId(String recordSplitId){
List<NotePrompt> notePromptList = new ArrayList<>();
// 首先获取所有切分后的笔录
Optional<NoteRecordSplit> optById = noteRecordSplitService.getOptById(recordSplitId);
if (optById.isEmpty()) {
log.warn("listPromptBySplitId根据笔录片段id{}未找到切分笔录数据...", recordSplitId);
return notePromptList;
}
NoteRecordSplit recordSplit = optById.get();
String recordType = recordSplit.getRecordType();
if (StrUtil.isBlank(recordType)) {
log.info("listPromptBySplitId:笔录片段:{} 不属于任何分类...", recordSplit.getId());
}
// 获取所有的分类
List<ModelRecordType> allTypeList = modelRecordTypeService.list();
Map<String, String> allTypeMap = allTypeList.stream().collect(Collectors.toMap(ModelRecordType::getRecordType, ModelRecordType::getId, (k1, k2) -> k1));
// 对切分后的笔录进行遍历
String[] split = recordType.split(";");
for (String typeName : split) {
String typeId = allTypeMap.get(typeName);
if (StrUtil.isBlank(typeId)) {
log.info("listPromptBySplitId:笔录片段id:{} typeName:{}未在全局分类中找到数据...", recordSplit.getId(),typeName);
continue;
}
// 根据笔录类型找到所有的提取三元组的提示词
// 一个提示词可能关联多个类型,要进行拆分操作
List<NotePromptTypeRel> promptTypeRelList = notePromptTypeRelService.lambdaQuery().eq(NotePromptTypeRel::getTypeId, typeId).select(NotePromptTypeRel::getPromptId).list();
if (CollUtil.isEmpty(promptTypeRelList)) {
log.info("listPromptBySplitId:笔录片段:{}根据typeId:{},typeName:{},未找到对应的提示词信息...", recordSplit.getId(), typeId,typeName);
continue;
}
List<String> promptIdList = promptTypeRelList.stream().map(NotePromptTypeRel::getPromptId).toList();
List<NotePrompt> list = super.lambdaQuery().in(NotePrompt::getId, promptIdList).list();
if (CollUtil.isEmpty(list)){
log.info("listPromptBySplitId:根据 promptIdList:{},未找到对应的提示词信息...",CollUtil.join(promptIdList,","));
continue;
}
notePromptList.addAll(list);
}
return notePromptList;
}
}

@ -102,4 +102,15 @@ public class NoteRecordServiceImpl extends ServiceImpl<NoteRecordMapper, NoteRec
}
}
@Override
public String saveOrUpdRecord(NoteRecord noteRecord) {
if (StringUtils.isEmpty(noteRecord.getId())) {
super.save(noteRecord);
} else {
updateById(noteRecord);
}
return noteRecord.getId();
}
}

@ -1,6 +1,7 @@
package com.supervision.police.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
@ -31,7 +32,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
@ -79,65 +79,30 @@ public class NoteRecordSplitServiceImpl extends ServiceImpl<NoteRecordSplitMappe
@Override
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public String uploadRecords(NoteRecordReqVO records) throws IOException {
int i;
ModelCase modelCase = modelCaseService.getById(records.getCaseId());
if (StringUtils.isEmpty(modelCase.getCaseNo())) {
throw new BusinessException("案件编号不能为空");
}
Assert.notEmpty(modelCase.getCaseNo(), "案件编号不能为空");
NoteRecord record = records.toNoteRecord();
if (StringUtils.isEmpty(records.getId())) {
i = noteRecordService.getBaseMapper().insert(record);
} else {
i = noteRecordService.getBaseMapper().updateById(record);
String recordId = noteRecordService.saveOrUpdRecord(record);
if (CollUtil.isEmpty(records.getFileIdList())){
log.info("uploadRecords:文件内容为空...不进行笔录分析操作...");
return recordId;
}
//所有对话类型
List<ModelRecordType> allTypeList = modelRecordTypeService.lambdaQuery().list();
if (i > 0 && CollUtil.isNotEmpty(records.getFileIdList())) {
// 拆分笔录
for (String fileId : records.getFileIdList()) {
MinioFile minioFile = minioService.getMinioFile(fileId);
InputStream inputStream = null;
try {
inputStream = minioService.getObjectInputStream(minioFile);
} catch (Exception e) {
e.printStackTrace();
log.error("从minio中获取文件失败:{}", e.getMessage());
continue;
}
String context = WordReadUtil.readWord(inputStream);
List<QARecordNodeDTO> qaList = RecordRegexUtil.recordRegex(context, record.getName());
log.info("拆分问答对:{}", qaList.size());
List<NoteRecordSplit> splitList = new ArrayList<>();
for (QARecordNodeDTO qa : qaList) {
try {
NoteRecordSplit noteRecord = new NoteRecordSplit();
noteRecord.setCaseId(record.getCaseId());
noteRecord.setNoteRecordId(record.getId());
noteRecord.setNoteName(minioFile.getFilename());
noteRecord.setPersonName(record.getName());
noteRecord.setQuestion(qa.getQuestion());
noteRecord.setAnswer(qa.getAnswer());
noteRecord.setCreateTime(LocalDateTime.now());
this.save(noteRecord);
splitList.add(noteRecord);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
// 创建任务之后,再开始
boolean taskStatus = saveRecordProcessTask(record.getCaseId(), record.getId(), qaList.size());
// 如果校验结果为true,则说明需要进行分类以及三元组操作
if (taskStatus) {
// 对笔录进行分类,并对笔录进行提取三元组
recordSplitProcessService.process(allTypeList, splitList);
}
}
caseStatusManageService.whenUploadRecord(record.getCaseId());
return "保存成功";
} else {
return "保存笔录失败";
List<NoteRecordSplit> allNoteRecordSplits = records.getFileIdList().stream()
.flatMap(fileId -> batchSaveRecordSplit(record, fileId).stream()).toList();
boolean taskStatus = recordProcessTaskStatusCheck(record.getCaseId(), record.getId(), allNoteRecordSplits.size());
// 如果校验结果为true,则说明需要进行分类以及三元组操作
if (taskStatus) {
// 对笔录进行分类,并对笔录进行提取三元组
List<ModelRecordType> allTypeList = modelRecordTypeService.lambdaQuery().list();
recordSplitProcessService.process(allTypeList, allNoteRecordSplits);
}
caseStatusManageService.whenUploadRecord(record.getCaseId());
return record.getId();
}
/**
@ -145,12 +110,14 @@ public class NoteRecordSplitServiceImpl extends ServiceImpl<NoteRecordSplitMappe
*
* @param caseId
* @param recordId
* @return , true, , false
* @return , true, , false
*/
private boolean saveRecordProcessTask(String caseId, String recordId, Integer splitSize) {
private boolean recordProcessTaskStatusCheck(String caseId, String recordId, Integer splitSize) {
// 首先查询是否存在任务,如果不存在,就新建
Optional<CaseTaskRecord> caseTaskRecordOpt = caseTaskRecordService.lambdaQuery()
.eq(CaseTaskRecord::getCaseId, caseId).eq(CaseTaskRecord::getRecordId, recordId).oneOpt();
if (caseTaskRecordOpt.isEmpty()) {
CaseTaskRecord newCaseTaskRecord = new CaseTaskRecord();
newCaseTaskRecord.setCaseId(caseId);
@ -158,47 +125,60 @@ public class NoteRecordSplitServiceImpl extends ServiceImpl<NoteRecordSplitMappe
newCaseTaskRecord.setStatus(1);
newCaseTaskRecord.setSubmitTime(LocalDateTime.now());
return caseTaskRecordService.save(newCaseTaskRecord);
} else if (0 == splitSize) {
}
if (0 == splitSize) {
// 如果笔录对为0,就直接不需要拆分,直接认为任务成功
CaseTaskRecord caseTaskRecord = caseTaskRecordOpt.get();
caseTaskRecord.setStatus(2);
caseTaskRecord.setSubmitTime(LocalDateTime.now());
caseTaskRecordService.saveOrUpdate(caseTaskRecord);
return false;
} else {
// 如果存在,则校验时间是否已经超过1天,如果超过了1天还没有执行完毕,就重新提交这个任务
CaseTaskRecord caseTaskRecord = caseTaskRecordOpt.get();
// 如果未执行,则提交执行
if (caseTaskRecordOpt.get().getStatus() == 0) {
caseTaskRecord.setStatus(1);
caseTaskRecord.setSubmitTime(LocalDateTime.now());
caseTaskRecordService.updateById(caseTaskRecord);
return true;
}
if (caseTaskRecordOpt.get().getStatus() == 1 && LocalDateTime.now().isAfter(caseTaskRecord.getSubmitTime().plusDays(1))) {
// 如果已经超过1天,则重新提交任务
caseTaskRecord.setStatus(1);
caseTaskRecord.setSubmitTime(LocalDateTime.now());
caseTaskRecordService.updateById(caseTaskRecord);
return true;
} else if (caseTaskRecordOpt.get().getStatus() == 2) {
// 如果执行成功,就不再执行了
return false;
} else if (caseTaskRecordOpt.get().getStatus() == 3) {
// 如果执行失败,就重新执行
caseTaskRecord.setStatus(1);
caseTaskRecord.setSubmitTime(LocalDateTime.now());
caseTaskRecordService.updateById(caseTaskRecord);
return true;
} else {
// 如果都不是就在跑一次
caseTaskRecord.setStatus(1);
caseTaskRecord.setSubmitTime(LocalDateTime.now());
caseTaskRecordService.updateById(caseTaskRecord);
return true;
}
}
if (caseTaskRecordOpt.get().getStatus() == 2) {
return false;
}
// 如果存在,则校验时间是否已经超过1天,如果超过了1天还没有执行完毕,就重新提交这个任务
CaseTaskRecord caseTaskRecord = caseTaskRecordOpt.get();
// 如果未执行,则提交执行
if (caseTaskRecordOpt.get().getStatus() == 0) {
caseTaskRecord.setStatus(1);
caseTaskRecord.setSubmitTime(LocalDateTime.now());
caseTaskRecord.setTaskCount(0);
caseTaskRecord.setFinishCount(0);
caseTaskRecordService.updateById(caseTaskRecord);
return true;
}
if (caseTaskRecordOpt.get().getStatus() == 1 && LocalDateTime.now().isAfter(caseTaskRecord.getSubmitTime().plusDays(1))) {
// 如果已经超过1天,则重新提交任务
caseTaskRecord.setStatus(1);
caseTaskRecord.setTaskCount(0);
caseTaskRecord.setFinishCount(0);
caseTaskRecord.setSubmitTime(LocalDateTime.now());
caseTaskRecordService.updateById(caseTaskRecord);
return true;
}
if (caseTaskRecordOpt.get().getStatus() == 3) {
// 如果执行失败,就重新执行
caseTaskRecord.setStatus(1);
caseTaskRecord.setTaskCount(0);
caseTaskRecord.setFinishCount(0);
caseTaskRecord.setSubmitTime(LocalDateTime.now());
caseTaskRecordService.updateById(caseTaskRecord);
return true;
}
// 如果都不是就在跑一次
caseTaskRecord.setStatus(1);
caseTaskRecord.setTaskCount(0);
caseTaskRecord.setFinishCount(0);
caseTaskRecord.setSubmitTime(LocalDateTime.now());
caseTaskRecordService.updateById(caseTaskRecord);
return true;
}
@ -329,6 +309,43 @@ public class NoteRecordSplitServiceImpl extends ServiceImpl<NoteRecordSplitMappe
modelAtomicResultService.lambdaUpdate().eq(ModelAtomicResult::getRecordId, id).remove();
}
@Override
public NoteRecordSplit saveRecordSplit(NoteRecord record, String fileName, String question, String answer) {
NoteRecordSplit noteRecord = new NoteRecordSplit();
noteRecord.setCaseId(record.getCaseId());
noteRecord.setNoteRecordId(record.getId());
noteRecord.setNoteName(fileName);
noteRecord.setPersonName(record.getName());
noteRecord.setQuestion(question);
noteRecord.setAnswer(answer);
noteRecord.setCreateTime(LocalDateTime.now());
this.save(noteRecord);
return noteRecord;
}
@Override
public List<NoteRecordSplit> batchSaveRecordSplit(NoteRecord record, String fileId) {
String context = WordReadUtil.readWordInMinio(minioService, fileId);
if (StrUtil.isEmpty(context)){
log.info("文件id:{}内容为空,不进行解析...", fileId);
return null;
}
MinioFile minioFile = minioService.getMinioFile(fileId);
List<QARecordNodeDTO> qaList = RecordRegexUtil.recordRegex(context, record.getName());
log.info("文件:{}拆分问答对:{}",minioFile.getFilename(), qaList.size());
List<NoteRecordSplit> splitList = new ArrayList<>();
for (QARecordNodeDTO qa : qaList) {
splitList.add(
saveRecordSplit(record, minioFile.getFilename(), qa.getQuestion(), qa.getAnswer())
);
}
return splitList;
}
@Override
public Map<String, Object> queryRecordList(NoteRecord noteRecord, Integer page, Integer size) {

@ -0,0 +1,98 @@
package com.supervision.police.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.supervision.police.domain.CaseTaskRecord;
import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.police.service.CaseTaskRecordService;
import com.supervision.police.service.ExtractTripleInfoService;
import com.supervision.police.service.NoteRecordSplitService;
import com.supervision.police.service.RecordSplitClassifyService;
import com.supervision.thread.RecordSplitClassifyTask;
import com.supervision.thread.RecordSplitClassifyThreadPool;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@Service
@Slf4j
@RequiredArgsConstructor
public class RecordSplitClassifyServiceImpl implements RecordSplitClassifyService {
private final OllamaChatClient chatClient;
private final NoteRecordSplitService noteRecordSplitService;
private final ExtractTripleInfoService extractTripleInfoService;
private final CaseTaskRecordService caseTaskRecordService;
@Async
@Override
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public void classify(List<ModelRecordType> allTypeList, List<NoteRecordSplit> splitList) {
if (CollUtil.isEmpty(splitList)){
log.warn("classify:没有需要分类的笔录片段,停止分类操作...");
return;
}
log.info("classify:开始执行笔录分类任务,笔录片段个数:{}", splitList.size());
List<RecordSplitClassifyTask> taskList = splitList.stream()
.peek(recordSplit -> {
caseTaskRecordService.taskCountIncrement(recordSplit.getCaseId(), recordSplit.getNoteRecordId());
log.info("classify:分类任务数量加1,笔录片段id:{}", recordSplit.getId());
})
.map(recordSplit -> new RecordSplitClassifyTask(allTypeList, recordSplit, chatClient, postClassifyRecord()))
.toList();
if (CollUtil.isEmpty(taskList)){
log.warn("classify:没有可用的分类任务,停止分类操作...");
return;
}
try {
log.info("classify:提交{}个分类任务....",taskList.size());
RecordSplitClassifyThreadPool.executorService.invokeAll(taskList);
} catch (Exception e) {
log.error("classify:分类任务执行出现异常", e);
}finally {
setFinishStatus(CollUtil.getFirst(splitList));
}
}
private void setFinishStatus(NoteRecordSplit noteRecordSplit) {
caseTaskRecordService.lambdaUpdate().set(CaseTaskRecord::getStatus, 2).eq(CaseTaskRecord::getCaseId, noteRecordSplit.getCaseId())
.eq(CaseTaskRecord::getRecordId, noteRecordSplit.getNoteRecordId()).update();
}
@NotNull
private Consumer<NoteRecordSplit> postClassifyRecord() {
return (noteRecordSplit) -> {
// 更新笔录片段中的分类结果
noteRecordSplitService.lambdaUpdate().set(NoteRecordSplit::getRecordType, noteRecordSplit.getRecordType())
.eq(NoteRecordSplit::getId, noteRecordSplit.getId()).update();
// 提取三元组信息
try {
extractTripleInfoService.extractTripleInfo(noteRecordSplit.getCaseId(), noteRecordSplit.getPersonName(), noteRecordSplit.getId());
} catch (Exception e) {
log.error("postClassifyRecord:提取三元组信息出现异常", e);
}finally {
// 更新分类任务完成数量加1
log.info("postClassifyRecord:分类任务完成数量加1,笔录片段id:{}", noteRecordSplit.getId());
caseTaskRecordService.finishCountIncrement(noteRecordSplit.getCaseId(), noteRecordSplit.getNoteRecordId());
}
};
}
}

@ -3,7 +3,7 @@ package com.supervision.police.service.impl;
import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.police.service.RecordSplitProcessService;
import com.supervision.police.service.RecordSplitTypeService;
import com.supervision.police.service.RecordSplitClassifyService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -13,11 +13,11 @@ import java.util.List;
@RequiredArgsConstructor
public class RecordSplitProcessServiceImpl implements RecordSplitProcessService {
private final RecordSplitTypeService recordSplitTypeService;
private final RecordSplitClassifyService recordSplitClassifyService;
@Override
public void process(List<ModelRecordType> allTypeList, List<NoteRecordSplit> splitList) {
// 通过异步的形式提交分类
recordSplitTypeService.type(allTypeList,splitList);
recordSplitClassifyService.classify(allTypeList,splitList);
}
}

@ -1,117 +0,0 @@
package com.supervision.police.service.impl;
import cn.hutool.core.util.StrUtil;
import com.supervision.police.domain.CaseTaskRecord;
import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.police.service.CaseTaskRecordService;
import com.supervision.police.service.ExtractTripleInfoService;
import com.supervision.police.service.NoteRecordSplitService;
import com.supervision.police.service.RecordSplitTypeService;
import com.supervision.thread.RecordSplitTypeThread;
import com.supervision.thread.RecordSplitTypeThreadPool;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
@Service
@Slf4j
@RequiredArgsConstructor
public class RecordSplitTypeServiceImpl implements RecordSplitTypeService {
private final OllamaChatClient chatClient;
private final NoteRecordSplitService noteRecordSplitService;
private final ExtractTripleInfoService extractTripleInfoService;
private final CaseTaskRecordService caseTaskRecordService;
@Async
@Override
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public void type(List<ModelRecordType> allTypeList, List<NoteRecordSplit> splitList) {
// 这里线程休眠1秒,因为首先报保证消息记录能够插入完成,插入完成之后,再去提交大模型,让大模型去分类.防止分类太快,分类结果出来了,插入还没有插入完成
try {
Thread.sleep(1000);
} catch (Exception e) {
log.error("分类任务线程休眠失败");
}
List<Future<String>> futures = new ArrayList<>();
log.info("开始执行笔录分类任务");
for (NoteRecordSplit recordSplit : splitList) {
// 进行分类
log.info("分类任务提交线程池进行分类");
// 任务+1
caseTaskRecordService.taskCountIncrement(recordSplit.getCaseId(), recordSplit.getNoteRecordId());
RecordSplitTypeThread recordSplitTypeThread = new RecordSplitTypeThread(allTypeList, recordSplit, chatClient, noteRecordSplitService);
// 分类之后的id
Future<String> afterTypeSplitIdFuture = RecordSplitTypeThreadPool.recordSplitTypeExecutor.submit(recordSplitTypeThread);
futures.add(afterTypeSplitIdFuture);
log.info("分类任务线程池提交分类成功");
}
log.info("----------{}-----------", "分类任务全部提交成功了");
// 校验分类任务是否完成,如果分类完成,那么就去提取三元组
AtomicInteger atomicInteger = new AtomicInteger(0);
while (futures.size() > 0) {
Iterator<Future<String>> iterator = futures.iterator();
while (iterator.hasNext()) {
Future<String> future = iterator.next();
try {
// 如果分类成功,就开始提取三元组
if (future.isDone()) {
// 完成+1
splitList.stream().findAny().ifPresent(noteRecordSplit -> caseTaskRecordService.finishCountIncrement(noteRecordSplit.getCaseId(), noteRecordSplit.getNoteRecordId()));
String afterTypeSplitId = future.get();
if (StrUtil.isNotBlank(afterTypeSplitId)) {
Optional<NoteRecordSplit> optById = noteRecordSplitService.getOptById(afterTypeSplitId);
if (optById.isPresent()) {
NoteRecordSplit recordSplit = optById.get();
extractTripleInfoService.extractTripleInfo(recordSplit.getCaseId(), recordSplit.getPersonName(), afterTypeSplitId);
}
}
iterator.remove();
}
} catch (Exception e) {
log.info("分类任务从线程中获取任务失败");
iterator.remove();
}
}
try {
int currentCount = atomicInteger.incrementAndGet();
if (currentCount > 1000) {
log.info("分类任务执行超时,遍历任务已执行:{}次,任务还剩余:{}个,不再继续执行", currentCount, futures.size());
// 将还在执行的线程中断
futures.forEach(future -> {
future.cancel(true);
// 完成+1
splitList.stream().findAny().ifPresent(noteRecordSplit -> caseTaskRecordService.finishCountIncrement(noteRecordSplit.getCaseId(), noteRecordSplit.getNoteRecordId()));
});
break;
}
log.info("分类任务已检查{}遍,任务剩余{}个,休眠5s后继续检查", currentCount, futures.size());
Thread.sleep(1000 * 5);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
log.info("分类任务执行完毕");
Optional<NoteRecordSplit> first = splitList.stream().findFirst();
if (first.isPresent()) {
NoteRecordSplit recordSplit = first.get();
// 分类任务执行完成之后,就将任务进行更新
caseTaskRecordService.lambdaUpdate().set(CaseTaskRecord::getStatus, 2).eq(CaseTaskRecord::getCaseId, recordSplit.getCaseId())
.eq(CaseTaskRecord::getRecordId, recordSplit.getNoteRecordId()).update();
}
}
}

@ -1,14 +1,7 @@
package com.supervision.prompt.thread;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.police.domain.NotePrompt;
import com.supervision.police.domain.TripleInfo;
import com.supervision.prompt.vo.ExecResultDTO;
import com.supervision.thread.TripleExtractThread;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.UserMessage;
@ -16,8 +9,6 @@ import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.util.StopWatch;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

@ -0,0 +1,137 @@
package com.supervision.thread;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NoteRecordSplit;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.util.StopWatch;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* 线
*/
@Slf4j
public class RecordSplitClassifyTask implements Callable<String> {
private final List<ModelRecordType> allTypeList;
private final NoteRecordSplit noteRecordSplit;
private final OllamaChatClient chatClient;
private final Consumer<NoteRecordSplit> consumer;
public RecordSplitClassifyTask(List<ModelRecordType> allTypeList, NoteRecordSplit noteRecordSplit,
OllamaChatClient chatClient,Consumer<NoteRecordSplit> consumer) {
this.allTypeList = allTypeList;
this.chatClient = chatClient;
this.noteRecordSplit = noteRecordSplit;
this.consumer = consumer;
}
private static final String NEW_TEMPLATE = """
:
:
{typeContext}
:
---
:
XXX
: {"result":[{"type":"合同和协议","explain":"行为人XXX提到签订合同"},{"type":"虚假信息和伪造","explain":"行为人XXX提到合同是假合同"}]}
---
:
1. ,
2. ,
2. ,
3. {"result":[]}
---
:
{question}
{answer}
---
json,:{"result":[{"type":"分类1","explain":"分类原因"},{"type":"分类2","explain":"分类原因"}]}
""";
private static final String TYPE_CONTEXT_TEMPLATE = "{分类type:{type},区别点(分类释义):{typeExt}}";
@Override
public String call() throws Exception {
String type = null;
try {
String answer = chat4Classify(this.noteRecordSplit);
TypeResultDTO result = JSONUtil.toBean(answer, TypeResultDTO.class);
List<TypeNodeDTO> typeList = result.getResult();
type = typeList.stream().map(TypeNodeDTO::getType).distinct().collect(Collectors.joining(";"));
} catch (Throwable e) {
log.error("分类任务执行失败:{}", e.getMessage(), e);
}
noteRecordSplit.setRecordType(StrUtil.isEmpty(type) ? "无" : type);
// 后续操作
try {
consumer.accept(noteRecordSplit);
} catch (Exception e) {
log.error("分类任务后置操作失败",e);
}
return noteRecordSplit.getId();
}
/**
*
* @param noteRecordSplit
* @return
*/
private String chat4Classify(NoteRecordSplit noteRecordSplit) {
StopWatch stopWatch = new StopWatch();
// 首先拼接分类模板
List<String> typeContextList = new ArrayList<>();
for (ModelRecordType modelRecordType : allTypeList) {
String format = StrUtil.format(TYPE_CONTEXT_TEMPLATE, Map.of("type", modelRecordType.getRecordType(), "typeExt", modelRecordType.getRecordTypeExt()));
typeContextList.add(format);
}
// 开始对笔录进行分类
Map<String, String> paramMap = new HashMap<>();
paramMap.put("typeContext", CollUtil.join(typeContextList, ";"));
paramMap.put("question", noteRecordSplit.getQuestion());
paramMap.put("answer", noteRecordSplit.getAnswer());
Prompt prompt = new Prompt(new UserMessage(StrUtil.format(NEW_TEMPLATE, paramMap)));
stopWatch.start();
log.info("chat4Classify:开始分析 prompt:{}:", prompt.getContents());
ChatResponse call = chatClient.call(prompt);
stopWatch.stop();
log.info("chat4Classify:分析结束耗时:{}", stopWatch.getTotalTimeSeconds());
String answer = call.getResult().getOutput().getContent();
log.info("chat4Classify:问:{}, 答:{},结果:{}", noteRecordSplit.getQuestion(), noteRecordSplit.getAnswer(),answer);
return answer;
}
@Data
public static class TypeNodeDTO {
private String type;
private String explain;
}
@Data
public static class TypeResultDTO {
private List<TypeNodeDTO> result;
}
}

@ -13,15 +13,15 @@ import java.util.concurrent.ExecutorService;
*/
@Slf4j
@Component
public class RecordSplitTypeThreadPool {
public class RecordSplitClassifyThreadPool {
@Value("${fu-hsi-config.thread-pool.type.core:2}")
private int core;
public static ExecutorService recordSplitTypeExecutor;
public static ExecutorService executorService;
@PostConstruct
public void init() {
log.info("RecordSplitType线程池初始化。线程数:{}", core);
recordSplitTypeExecutor = ThreadUtil.newFixedExecutor(core, Integer.MAX_VALUE, "recordSplitType", false);
log.info("recordSplitClassify线程池初始化。线程数:{}", core);
executorService = ThreadUtil.newFixedExecutor(core, Integer.MAX_VALUE, "recordSplitType", false);
}
}

@ -1,144 +0,0 @@
package com.supervision.thread;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.police.service.NoteRecordSplitService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.util.StopWatch;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
/**
* 线
*/
@Slf4j
public class RecordSplitTypeThread implements Callable<String> {
private final List<ModelRecordType> allTypeList;
private final NoteRecordSplit noteRecordSplit;
private final OllamaChatClient chatClient;
private final NoteRecordSplitService noteRecordSplitService;
public RecordSplitTypeThread(List<ModelRecordType> allTypeList, NoteRecordSplit noteRecordSplit, OllamaChatClient chatClient,
NoteRecordSplitService noteRecordSplitService) {
this.allTypeList = allTypeList;
this.chatClient = chatClient;
this.noteRecordSplitService = noteRecordSplitService;
this.noteRecordSplit = noteRecordSplit;
}
private static final String TYPE_TEMPLATE = """
: : {allTypes}"
:
: :
便QQ
: { type: '' }
:
1.
2.
3.
{question} {answer}
""";
private static final String NEW_TEMPLATE = """
:
:
{typeContext}
:
---
:
XXX
: {"result":[{"type":"合同和协议","explain":"行为人XXX提到签订合同"},{"type":"虚假信息和伪造","explain":"行为人XXX提到合同是假合同"}]}
---
:
1. ,
2. ,
2. ,
3. {"result":[]}
---
:
{question}
{answer}
---
json,:{"result":[{"type":"分类1","explain":"分类原因"},{"type":"分类2","explain":"分类原因"}]}
""";
private static final String TYPE_CONTEXT_TEMPLATE = "{分类type:{type},区别点(分类释义):{typeExt}}";
@Override
public String call() throws Exception {
String type;
try {
StopWatch stopWatch = new StopWatch();
// 首先拼接分类模板
List<String> typeContextList = new ArrayList<>();
for (ModelRecordType modelRecordType : allTypeList) {
String format = StrUtil.format(TYPE_CONTEXT_TEMPLATE, Map.of("type", modelRecordType.getRecordType(), "typeExt", modelRecordType.getRecordTypeExt()));
typeContextList.add(format);
}
// 开始对笔录进行分类
Map<String, String> paramMap = new HashMap<>();
paramMap.put("typeContext", CollUtil.join(typeContextList, ";"));
paramMap.put("question", noteRecordSplit.getQuestion());
paramMap.put("answer", noteRecordSplit.getAnswer());
Prompt prompt = new Prompt(new UserMessage(StrUtil.format(NEW_TEMPLATE, paramMap)));
stopWatch.start();
log.info("开始分析:");
ChatResponse call = chatClient.call(prompt);
stopWatch.stop();
log.info("耗时:{}", stopWatch.getTotalTimeSeconds());
String content = call.getResult().getOutput().getContent();
log.info("问:{}, 答:{}", noteRecordSplit.getQuestion(), noteRecordSplit.getAnswer());
log.info("分析的结果是:{}", content);
TypeResultDTO result = JSONUtil.toBean(content, TypeResultDTO.class);
List<TypeNodeDTO> typeList = result.getResult();
if (CollUtil.isNotEmpty(typeList)) {
// 将type进行拼接,并以分号进行分割
type = CollUtil.join(typeList.stream().map(TypeNodeDTO::getType).collect(Collectors.toSet()), ";");
} else {
// 如果没有提取到,就是无
type = "无";
}
} catch (Exception e) {
log.error("分类任务执行失败:{}", e.getMessage(), e);
type = "无";
}
noteRecordSplitService.lambdaUpdate().set(NoteRecordSplit::getRecordType, type).eq(NoteRecordSplit::getId, noteRecordSplit.getId()).update();
return noteRecordSplit.getId();
}
@Data
public static class TypeNodeDTO {
private String type;
private String explain;
}
@Data
public static class TypeResultDTO {
private List<TypeNodeDTO> result;
}
}

@ -5,49 +5,38 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.police.domain.NotePrompt;
import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.police.domain.TripleInfo;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.util.StopWatch;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
@Slf4j
public class TripleExtractThread implements Callable<TripleInfo> {
public class TripleExtractTask implements Callable<TripleInfo> {
private final OllamaChatClient chatClient;
private final NotePrompt prompt;
private final String question;
private final NoteRecordSplit noteRecordSplit;
private final String answer;
private final Consumer<NoteRecordSplit> consumer;
private final String recordSplitId;
private final String caseId;
private final String recordId;
public TripleExtractThread(OllamaChatClient chatClient, String caseId, String recordId, String recordSplitId,
NotePrompt prompt, String question, String answer) {
this.question = question;
public TripleExtractTask(OllamaChatClient chatClient, NotePrompt prompt, NoteRecordSplit noteRecordSplit, Consumer<NoteRecordSplit> consumer) {
this.chatClient = chatClient;
this.answer = answer;
this.noteRecordSplit = noteRecordSplit;
this.prompt = prompt;
this.recordSplitId = recordSplitId;
this.caseId = caseId;
this.recordId = recordId;
this.consumer = consumer;
}
@ -79,33 +68,14 @@ public class TripleExtractThread implements Callable<TripleInfo> {
@Override
public TripleInfo call() {
try {
StopWatch stopWatch = new StopWatch();
// 分析三元组
stopWatch.start();
HashMap<String, String> paramMap = new HashMap<>();
paramMap.put("headEntityType", prompt.getStartEntityType());
paramMap.put("relation", prompt.getRelType());
paramMap.put("tailEntityType", prompt.getEndEntityType());
paramMap.put("question", question);
paramMap.put("answer", answer);
String format = StrUtil.format(prompt.getPrompt(), paramMap);
// // 对format进行切分,把前面两个---作为systemPrompt
// String[] split = format.split("---");
// SystemMessage systemMessage = new SystemMessage(split[0]);
// UserMessage userMessage = new UserMessage(split[1]);
// Prompt ask = new Prompt(List.of(systemMessage, userMessage));
// ChatResponse call = chatClient.call(ask);
log.info("prompt:{}", format);
ChatResponse call = chatClient.call(new Prompt(new UserMessage(format)));
stopWatch.stop();
String content = call.getResult().getOutput().getContent();
log.info("耗时:{},分析的结果是:{}", stopWatch.getTotalTimeSeconds(), content);
TripleRecord tripleRecord = chat4Triple(prompt, noteRecordSplit);
// 获取从提示词中提取到的三元组信息
TripleExtractResult extractResult = JSONUtil.toBean(content, TripleExtractResult.class);
TripleExtractResult extractResult = JSONUtil.toBean(tripleRecord.answer, TripleExtractResult.class);
if (ObjectUtil.isEmpty(extractResult) || CollUtil.isEmpty(extractResult.getResult())) {
log.info("提取三元组信息为空,忽略.提取的内容为:{}", content);
log.info("提取三元组信息为空,忽略.提取的内容为:{}", tripleRecord.answer);
return null;
}
for (TripleExtractNode tripleExtractNode : extractResult.getResult()) {
TripleEntity headEntity = tripleExtractNode.getHeadEntity();
TripleEntity tailEntity = tripleExtractNode.getTailEntity();
@ -119,20 +89,46 @@ public class TripleExtractThread implements Callable<TripleInfo> {
tripleInfo.setStartNode(headEntity.getName());
tripleInfo.setEndNode(tailEntity.getName());
tripleInfo.setRelation(relation);
tripleInfo.setCaseId(caseId);
tripleInfo.setRecordId(recordId);
tripleInfo.setRecordSplitId(recordSplitId);
tripleInfo.setSubmitPrompt(format);
tripleInfo.setCaseId(noteRecordSplit.getCaseId());
tripleInfo.setRecordId(noteRecordSplit.getNoteRecordId());
tripleInfo.setRecordSplitId(noteRecordSplit.getId());
tripleInfo.setSubmitPrompt(tripleRecord.question);
tripleInfo.setStartNodeType(prompt.getStartEntityType());
tripleInfo.setEndNodeType(prompt.getEndEntityType());
return tripleInfo;
}
} catch (Exception e) {
log.error("提取三元组出现错误", e);
}finally {
consumer.accept(noteRecordSplit);
}
return null;
}
private TripleRecord chat4Triple(NotePrompt prompt,NoteRecordSplit noteRecordSplit) {
StopWatch stopWatch = new StopWatch();
// 分析三元组
stopWatch.start();
HashMap<String, String> paramMap = new HashMap<>();
paramMap.put("headEntityType", prompt.getStartEntityType());
paramMap.put("relation", prompt.getRelType());
paramMap.put("tailEntityType", prompt.getEndEntityType());
paramMap.put("question", noteRecordSplit.getQuestion());
paramMap.put("answer", noteRecordSplit.getAnswer());
String format = StrUtil.format(prompt.getPrompt(), paramMap);
log.info("提示词内容:{}", format);
ChatResponse call = chatClient.call(new Prompt(new UserMessage(format)));
stopWatch.stop();
String content = call.getResult().getOutput().getContent();
log.info("问题:{}耗时:{},三元组提取结果是:{}",noteRecordSplit.getQuestion(),stopWatch.getTotalTimeSeconds(), content);
return new TripleRecord(format, content);
}
record TripleRecord(String question, String answer){}
@Data
public static class TripleExtractResult {
private List<TripleExtractNode> result;

@ -10,15 +10,15 @@ import java.util.concurrent.ExecutorService;
@Slf4j
@Component
public class TripleExtractThreadPool {
public class TripleExtractTaskPool {
@Value("${fu-hsi-config.thread-pool.triple.core:2}")
private int core;
public static ExecutorService chatExecutor;
public static ExecutorService executor;
@PostConstruct
public void init() {
log.info("tripleExtract线程池初始化。线程数{}", core);
chatExecutor = ThreadUtil.newFixedExecutor(core, Integer.MAX_VALUE, "tripleExtract", false);
executor = ThreadUtil.newFixedExecutor(core, Integer.MAX_VALUE, "tripleExtract", false);
}
}

@ -1,5 +1,7 @@
package com.supervision.utils;
import com.supervision.minio.domain.MinioFile;
import com.supervision.minio.service.MinioService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
@ -71,4 +73,14 @@ public class WordReadUtil {
return stringBuilder.toString();
}
public static String readWordInMinio(MinioService minioService, String fileId) {
try (InputStream inputStream = minioService.getObjectInputStream(fileId)){
return readWord(inputStream);
} catch (Exception e) {
log.error("从minio中获取文件失败", e);
return null;
}
}
}

@ -11,7 +11,8 @@ import com.supervision.police.domain.ModelRecordType;
import com.supervision.police.domain.NoteRecordSplit;
import com.supervision.police.service.ModelRecordTypeService;
import com.supervision.police.service.NoteRecordSplitService;
import com.supervision.thread.RecordSplitTypeThread;
import com.supervision.police.service.RecordSplitClassifyService;
import com.supervision.thread.RecordSplitClassifyTask;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.ChatResponse;
@ -132,11 +133,11 @@ public class FuHsiApplicationTests {
String content = call.getResult().getOutput().getContent();
log.info("问:{}, 答:{}", noteRecordSplit.getQuestion(), noteRecordSplit.getAnswer());
log.info("分析的结果是:{}", content);
RecordSplitTypeThread.TypeResultDTO result = JSONUtil.toBean(content, RecordSplitTypeThread.TypeResultDTO.class);
List<RecordSplitTypeThread.TypeNodeDTO> typeList = result.getResult();
RecordSplitClassifyTask.TypeResultDTO result = JSONUtil.toBean(content, RecordSplitClassifyTask.TypeResultDTO.class);
List<RecordSplitClassifyTask.TypeNodeDTO> typeList = result.getResult();
if (CollUtil.isNotEmpty(typeList)) {
// 将type进行拼接,并以分号进行分割
type = CollUtil.join(typeList.stream().map(RecordSplitTypeThread.TypeNodeDTO::getType).collect(Collectors.toSet()), ";");
type = CollUtil.join(typeList.stream().map(RecordSplitClassifyTask.TypeNodeDTO::getType).collect(Collectors.toSet()), ";");
} else {
// 如果没有提取到,就是无
type = "无";
@ -152,4 +153,16 @@ public class FuHsiApplicationTests {
}
@Autowired
private RecordSplitClassifyService recordSplitClassifyService;
@Test
public void classificationTest2() {
List<ModelRecordType> typeList = modelRecordTypeService.lambdaQuery().list();
List<NoteRecordSplit> noteRecordSplits = noteRecordSplitService.lambdaQuery().eq(NoteRecordSplit::getId, "1824729361214418946").list();
recordSplitClassifyService.classify(typeList,noteRecordSplits);
log.info("分类结果:{}",noteRecordSplits);
}
}

Loading…
Cancel
Save