package com.supervision.police.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.supervision.common.constant.NotePromptConstants; import com.supervision.common.utils.StringUtils; import com.supervision.demo.dto.QARecordNodeDTO; import com.supervision.minio.domain.MinioFile; import com.supervision.minio.service.MinioService; import com.supervision.police.domain.*; import com.supervision.police.dto.LLMExtractDto; import com.supervision.police.dto.NotePromptDTO; import com.supervision.police.mapper.NotePromptMapper; import com.supervision.police.service.*; import com.supervision.utils.RecordRegexUtil; import com.supervision.utils.WordReadUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; @Slf4j @Service @RequiredArgsConstructor public class NotePromptServiceImpl extends ServiceImpl implements NotePromptService { private final NoteRecordSplitService noteRecordSplitService; @Autowired private ModelRecordTypeService modelRecordTypeService; @Autowired private NotePromptMapper notePromptMapper; private final NotePromptTypeRelService notePromptTypeRelService; @Autowired private MinioService minioService; @Autowired private LLMExtractService llmExtractService; @Autowired private ChatClient chatClient; @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; } @Override public IPage listPrompt(int page, int size, NotePrompt notePrompt) { return notePromptMapper.selectNotePromptWithMatchNum(new Page<>(page, size), notePrompt); } @Override public String promptDebugging(NotePromptDTO notePromptDTO) { String result = ""; String text = notePromptDTO.getText(); String fileId = notePromptDTO.getFileId(); if (StringUtils.isNotEmpty(fileId)) { MinioFile minioFile = minioService.getMinioFile(fileId); if (minioFile != null) { if (minioFile.getFilename().endsWith(".doc") || minioFile.getFilename().endsWith(".docx")) { log.info("当前文件名为:{},当做word文件处理...", minioFile.getFilename()); text = WordReadUtil.readWord(minioService.getObjectInputStream(minioFile)); } else if (minioFile.getFilename().endsWith(".txt")) { log.info("当前文件名为:{},当做txt文件处理...", minioFile.getFilename()); InputStream inputStream = minioService.getObjectInputStream(minioFile); try (inputStream) { BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); text = reader.lines().collect(Collectors.joining("\n")); } catch (IOException e) { log.error("读取文件内容失败", e); } } } } if (StringUtils.isEmpty(text)) { log.info("未上传文件且调试文本为空..."); return result; } String type = notePromptDTO.getType(); if (NotePromptConstants.TYPE_GRAPH_REASONING.equals(type)) { List qaList = RecordRegexUtil.recordRegex(text, ""); log.info("拆分问答对:{}", qaList.size()); if (qaList.isEmpty()) { return "未找到问答对"; } QARecordNodeDTO qaRecordNodeDTO = qaList.get(0); HashMap paramMap = new HashMap<>(); paramMap.put("headEntityType", notePromptDTO.getStartEntityType()); paramMap.put("relation", notePromptDTO.getRelType()); paramMap.put("tailEntityType", notePromptDTO.getEndEntityType()); paramMap.put("question", qaRecordNodeDTO.getQuestion()); paramMap.put("answer", qaRecordNodeDTO.getAnswer()); paramMap.put("requirement", ""); log.info("开始尝试提取三元组:{}-{}-{}", notePromptDTO.getStartEntityType(), notePromptDTO.getRelType(), notePromptDTO.getEndEntityType()); String format = StrUtil.format(notePromptDTO.getPrompt(), paramMap); log.info("提示词内容:{}", format); ChatResponse call = chatClient.call(new Prompt(new UserMessage(format))); String content = call.getResult().getOutput().getContent(); log.info("三元组提取结果:{}", content); result = content; } else if (NotePromptConstants.TYPE_STRUCTURAL_REASONING.equals(type)) { LLMExtractDto llmExtractDto = new LLMExtractDto(); llmExtractDto.setText(text); llmExtractDto.setPrompt(notePromptDTO.getPrompt()); llmExtractDto.setExtractAttributes(notePromptDTO.getExtractAttributes()); List llmExtractDtos = llmExtractService.extractAttribute(Collections.singletonList(llmExtractDto)); if (CollUtil.isNotEmpty(llmExtractDtos)) { result = llmExtractDtos.get(0).toString(); } } else { log.info("未找到对应的调试类型...【{}】", type); } return result; } }