diff --git a/docker/docker-compose/init.sql b/docker/docker-compose/init.sql index ce3d12c..b07185b 100644 --- a/docker/docker-compose/init.sql +++ b/docker/docker-compose/init.sql @@ -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 diff --git a/src/main/java/com/supervision/police/service/NotePromptService.java b/src/main/java/com/supervision/police/service/NotePromptService.java index d122688..5ab9a9c 100644 --- a/src/main/java/com/supervision/police/service/NotePromptService.java +++ b/src/main/java/com/supervision/police/service/NotePromptService.java @@ -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 { + + List listPromptBySplitId(String recordSplitId); } diff --git a/src/main/java/com/supervision/police/service/NoteRecordService.java b/src/main/java/com/supervision/police/service/NoteRecordService.java index 9f5d272..08ea553 100644 --- a/src/main/java/com/supervision/police/service/NoteRecordService.java +++ b/src/main/java/com/supervision/police/service/NoteRecordService.java @@ -11,4 +11,7 @@ public interface NoteRecordService extends IService { List selectNoteRecordDTOList(NoteRecord noteRecord); void uploadFileToLangChainChat(String caseId); + + + String saveOrUpdRecord(NoteRecord noteRecord); } diff --git a/src/main/java/com/supervision/police/service/NoteRecordSplitService.java b/src/main/java/com/supervision/police/service/NoteRecordSplitService.java index bb234aa..3a34fec 100644 --- a/src/main/java/com/supervision/police/service/NoteRecordSplitService.java +++ b/src/main/java/com/supervision/police/service/NoteRecordSplitService.java @@ -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 { @@ -16,5 +17,8 @@ public interface NoteRecordSplitService extends IService { void delRecords(String id); + NoteRecordSplit saveRecordSplit(NoteRecord record, String fileName, String question, String answer); + + List batchSaveRecordSplit(NoteRecord record, String fileId); Map queryRecordList(NoteRecord noteRecord, Integer page, Integer size); } diff --git a/src/main/java/com/supervision/police/service/RecordSplitClassifyService.java b/src/main/java/com/supervision/police/service/RecordSplitClassifyService.java new file mode 100644 index 0000000..9eb780b --- /dev/null +++ b/src/main/java/com/supervision/police/service/RecordSplitClassifyService.java @@ -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 allTypeList, List splitList); +} diff --git a/src/main/java/com/supervision/police/service/RecordSplitTypeService.java b/src/main/java/com/supervision/police/service/RecordSplitTypeService.java deleted file mode 100644 index 897ce90..0000000 --- a/src/main/java/com/supervision/police/service/RecordSplitTypeService.java +++ /dev/null @@ -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 allTypeList, List splitList); -} diff --git a/src/main/java/com/supervision/police/service/impl/ExtractTripleInfoServiceImpl.java b/src/main/java/com/supervision/police/service/impl/ExtractTripleInfoServiceImpl.java index b0d3510..e9dabab 100644 --- a/src/main/java/com/supervision/police/service/impl/ExtractTripleInfoServiceImpl.java +++ b/src/main/java/com/supervision/police/service/impl/ExtractTripleInfoServiceImpl.java @@ -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 optById = noteRecordSplitService.getOptById(recordSplitId); if (optById.isEmpty()) { - log.info("{} 切分笔录不存在,跳过", recordSplitId); + log.warn("extractTripleInfo:根据笔录片段id{}未找到切分笔录数据,不进行后续操作...", recordSplitId); return; } NoteRecordSplit recordSplit = optById.get(); - // 获取所有的分类 - List allTypeList = modelRecordTypeService.list(); - Map allTypeMap = allTypeList.stream().collect(Collectors.toMap(ModelRecordType::getRecordType, ModelRecordType::getId, (k1, k2) -> k1)); - - List tripleInfos = new ArrayList<>(); - List> 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 promptTypeRelList = notePromptTypeRelService.lambdaQuery().eq(NotePromptTypeRel::getTypeId, typeId).select(NotePromptTypeRel::getPromptId).list(); - if (CollUtil.isEmpty(promptTypeRelList)) { - log.info("{} 切分笔录类型:{}无对应的提示词,跳过", recordSplit.getId(), typeName); - continue; - } - List 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 submit = TripleExtractThreadPool.chatExecutor.submit(tripleExtractThread); - futures.add(submit); - log.info("三元组提取任务提交成功"); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - } - } - } + List 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 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> iterator = futures.iterator(); - while (iterator.hasNext()) { - Future future = iterator.next(); + + List tripleInfos = new ArrayList<>(); + try { + log.info("extractTripleInfo:笔录片段:{}抽取任务成功提交{}个任务....",recordSplitId,taskList.size()); + List> futures = TripleExtractTaskPool.executor.invokeAll(taskList); + + for (Future 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 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); + } + }; + } } diff --git a/src/main/java/com/supervision/police/service/impl/ModelRecordTypeServiceImpl.java b/src/main/java/com/supervision/police/service/impl/ModelRecordTypeServiceImpl.java index e96481d..9f2fa21 100644 --- a/src/main/java/com/supervision/police/service/impl/ModelRecordTypeServiceImpl.java +++ b/src/main/java/com/supervision/police/service/impl/ModelRecordTypeServiceImpl.java @@ -44,7 +44,8 @@ public class ModelRecordTypeServiceImpl extends ServiceImpl allTypeList = modelRecordTypeService.lambdaQuery().list(); // 根据recordId查询所有的分割后的笔录 List list = noteRecordSplitService.lambdaQuery().eq(NoteRecordSplit::getNoteRecordId, recordId).list(); diff --git a/src/main/java/com/supervision/police/service/impl/NotePromptServiceImpl.java b/src/main/java/com/supervision/police/service/impl/NotePromptServiceImpl.java index 0ad8661..8f5fd88 100644 --- a/src/main/java/com/supervision/police/service/impl/NotePromptServiceImpl.java +++ b/src/main/java/com/supervision/police/service/impl/NotePromptServiceImpl.java @@ -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 implements NotePromptService { + private final NoteRecordSplitService noteRecordSplitService; + + @Autowired + private ModelRecordTypeService modelRecordTypeService; + + + private final NotePromptTypeRelService notePromptTypeRelService; + @Override + public List listPromptBySplitId(String recordSplitId){ + + List notePromptList = new ArrayList<>(); + // 首先获取所有切分后的笔录 + Optional 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 allTypeList = modelRecordTypeService.list(); + Map 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 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 promptIdList = promptTypeRelList.stream().map(NotePromptTypeRel::getPromptId).toList(); + List 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; + } } diff --git a/src/main/java/com/supervision/police/service/impl/NoteRecordServiceImpl.java b/src/main/java/com/supervision/police/service/impl/NoteRecordServiceImpl.java index 15242c6..54f3720 100644 --- a/src/main/java/com/supervision/police/service/impl/NoteRecordServiceImpl.java +++ b/src/main/java/com/supervision/police/service/impl/NoteRecordServiceImpl.java @@ -102,4 +102,15 @@ public class NoteRecordServiceImpl extends ServiceImpl 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 qaList = RecordRegexUtil.recordRegex(context, record.getName()); - log.info("拆分问答对:{}", qaList.size()); - List 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 allNoteRecordSplits = records.getFileIdList().stream() + .flatMap(fileId -> batchSaveRecordSplit(record, fileId).stream()).toList(); + + boolean taskStatus = recordProcessTaskStatusCheck(record.getCaseId(), record.getId(), allNoteRecordSplits.size()); + // 如果校验结果为true,则说明需要进行分类以及三元组操作 + if (taskStatus) { + // 对笔录进行分类,并对笔录进行提取三元组 + List allTypeList = modelRecordTypeService.lambdaQuery().list(); + recordSplitProcessService.process(allTypeList, allNoteRecordSplits); } + caseStatusManageService.whenUploadRecord(record.getCaseId()); + return record.getId(); } /** @@ -145,12 +110,14 @@ public class NoteRecordSplitServiceImpl extends ServiceImpl 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 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 qaList = RecordRegexUtil.recordRegex(context, record.getName()); + log.info("文件:{}拆分问答对:{}",minioFile.getFilename(), qaList.size()); + + List splitList = new ArrayList<>(); + for (QARecordNodeDTO qa : qaList) { + splitList.add( + saveRecordSplit(record, minioFile.getFilename(), qa.getQuestion(), qa.getAnswer()) + ); + } + return splitList; + } + @Override public Map queryRecordList(NoteRecord noteRecord, Integer page, Integer size) { diff --git a/src/main/java/com/supervision/police/service/impl/RecordSplitClassifyServiceImpl.java b/src/main/java/com/supervision/police/service/impl/RecordSplitClassifyServiceImpl.java new file mode 100644 index 0000000..07545a0 --- /dev/null +++ b/src/main/java/com/supervision/police/service/impl/RecordSplitClassifyServiceImpl.java @@ -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 allTypeList, List splitList) { + + if (CollUtil.isEmpty(splitList)){ + log.warn("classify:没有需要分类的笔录片段,停止分类操作..."); + return; + } + + log.info("classify:开始执行笔录分类任务,笔录片段个数:{}", splitList.size()); + List 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 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()); + } + + + }; + } +} diff --git a/src/main/java/com/supervision/police/service/impl/RecordSplitProcessServiceImpl.java b/src/main/java/com/supervision/police/service/impl/RecordSplitProcessServiceImpl.java index 5bdeb42..58efaa4 100644 --- a/src/main/java/com/supervision/police/service/impl/RecordSplitProcessServiceImpl.java +++ b/src/main/java/com/supervision/police/service/impl/RecordSplitProcessServiceImpl.java @@ -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 allTypeList, List splitList) { // 通过异步的形式提交分类 - recordSplitTypeService.type(allTypeList,splitList); + recordSplitClassifyService.classify(allTypeList,splitList); } } diff --git a/src/main/java/com/supervision/police/service/impl/RecordSplitTypeServiceImpl.java b/src/main/java/com/supervision/police/service/impl/RecordSplitTypeServiceImpl.java deleted file mode 100644 index ec95e0a..0000000 --- a/src/main/java/com/supervision/police/service/impl/RecordSplitTypeServiceImpl.java +++ /dev/null @@ -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 allTypeList, List splitList) { - // 这里线程休眠1秒,因为首先报保证消息记录能够插入完成,插入完成之后,再去提交大模型,让大模型去分类.防止分类太快,分类结果出来了,插入还没有插入完成 - try { - Thread.sleep(1000); - } catch (Exception e) { - log.error("分类任务线程休眠失败"); - } - List> 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 afterTypeSplitIdFuture = RecordSplitTypeThreadPool.recordSplitTypeExecutor.submit(recordSplitTypeThread); - futures.add(afterTypeSplitIdFuture); - log.info("分类任务线程池提交分类成功"); - } - log.info("----------{}-----------", "分类任务全部提交成功了"); - // 校验分类任务是否完成,如果分类完成,那么就去提取三元组 - AtomicInteger atomicInteger = new AtomicInteger(0); - while (futures.size() > 0) { - Iterator> iterator = futures.iterator(); - while (iterator.hasNext()) { - Future 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 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 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(); - } - - - } -} diff --git a/src/main/java/com/supervision/prompt/thread/PromptTestThread.java b/src/main/java/com/supervision/prompt/thread/PromptTestThread.java index 781ff05..6f56c0d 100644 --- a/src/main/java/com/supervision/prompt/thread/PromptTestThread.java +++ b/src/main/java/com/supervision/prompt/thread/PromptTestThread.java @@ -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; diff --git a/src/main/java/com/supervision/thread/RecordSplitClassifyTask.java b/src/main/java/com/supervision/thread/RecordSplitClassifyTask.java new file mode 100644 index 0000000..74cc8f1 --- /dev/null +++ b/src/main/java/com/supervision/thread/RecordSplitClassifyTask.java @@ -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 { + + private final List allTypeList; + + private final NoteRecordSplit noteRecordSplit; + + private final OllamaChatClient chatClient; + + private final Consumer consumer; + + + public RecordSplitClassifyTask(List allTypeList, NoteRecordSplit noteRecordSplit, + OllamaChatClient chatClient,Consumer 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 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 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 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 result; + } +} diff --git a/src/main/java/com/supervision/thread/RecordSplitTypeThreadPool.java b/src/main/java/com/supervision/thread/RecordSplitClassifyThreadPool.java similarity index 62% rename from src/main/java/com/supervision/thread/RecordSplitTypeThreadPool.java rename to src/main/java/com/supervision/thread/RecordSplitClassifyThreadPool.java index 8b58675..93b198c 100644 --- a/src/main/java/com/supervision/thread/RecordSplitTypeThreadPool.java +++ b/src/main/java/com/supervision/thread/RecordSplitClassifyThreadPool.java @@ -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); } } diff --git a/src/main/java/com/supervision/thread/RecordSplitTypeThread.java b/src/main/java/com/supervision/thread/RecordSplitTypeThread.java deleted file mode 100644 index 7400d72..0000000 --- a/src/main/java/com/supervision/thread/RecordSplitTypeThread.java +++ /dev/null @@ -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 { - - - private final List allTypeList; - - private final NoteRecordSplit noteRecordSplit; - - private final OllamaChatClient chatClient; - - private final NoteRecordSplitService noteRecordSplitService; - - - - public RecordSplitTypeThread(List 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 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 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 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 result; - } -} diff --git a/src/main/java/com/supervision/thread/TripleExtractThread.java b/src/main/java/com/supervision/thread/TripleExtractTask.java similarity index 67% rename from src/main/java/com/supervision/thread/TripleExtractThread.java rename to src/main/java/com/supervision/thread/TripleExtractTask.java index 269b4a2..3f489a6 100644 --- a/src/main/java/com/supervision/thread/TripleExtractThread.java +++ b/src/main/java/com/supervision/thread/TripleExtractTask.java @@ -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 { +public class TripleExtractTask implements Callable { private final OllamaChatClient chatClient; private final NotePrompt prompt; - private final String question; + private final NoteRecordSplit noteRecordSplit; - private final String answer; + private final Consumer 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 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 { @Override public TripleInfo call() { try { - StopWatch stopWatch = new StopWatch(); - // 分析三元组 - stopWatch.start(); - HashMap 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.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 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 result; diff --git a/src/main/java/com/supervision/thread/TripleExtractThreadPool.java b/src/main/java/com/supervision/thread/TripleExtractTaskPool.java similarity index 73% rename from src/main/java/com/supervision/thread/TripleExtractThreadPool.java rename to src/main/java/com/supervision/thread/TripleExtractTaskPool.java index adbcb6f..e7b1978 100644 --- a/src/main/java/com/supervision/thread/TripleExtractThreadPool.java +++ b/src/main/java/com/supervision/thread/TripleExtractTaskPool.java @@ -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); } } diff --git a/src/main/java/com/supervision/utils/WordReadUtil.java b/src/main/java/com/supervision/utils/WordReadUtil.java index 04f446c..ede7468 100644 --- a/src/main/java/com/supervision/utils/WordReadUtil.java +++ b/src/main/java/com/supervision/utils/WordReadUtil.java @@ -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; + } + } + } diff --git a/src/test/java/com/supervision/demo/FuHsiApplicationTests.java b/src/test/java/com/supervision/demo/FuHsiApplicationTests.java index d227d53..bb73086 100644 --- a/src/test/java/com/supervision/demo/FuHsiApplicationTests.java +++ b/src/test/java/com/supervision/demo/FuHsiApplicationTests.java @@ -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 typeList = result.getResult(); + RecordSplitClassifyTask.TypeResultDTO result = JSONUtil.toBean(content, RecordSplitClassifyTask.TypeResultDTO.class); + List 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 typeList = modelRecordTypeService.lambdaQuery().list(); + List noteRecordSplits = noteRecordSplitService.lambdaQuery().eq(NoteRecordSplit::getId, "1824729361214418946").list(); + + + recordSplitClassifyService.classify(typeList,noteRecordSplits); + log.info("分类结果:{}",noteRecordSplits); + } }