package com.supervision.police.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.supervision.chat.client.LangChainChatService; import com.supervision.chat.client.dto.chat.ChatReqDTO; import com.supervision.chat.client.dto.chat.ChatResDTO; import com.supervision.common.domain.R; import com.supervision.constant.CaseAnalysisStatusEnum; import com.supervision.police.domain.Conversation; import com.supervision.police.domain.ConversationQa; import com.supervision.police.domain.ModelCase; import com.supervision.police.domain.ModelIndex; import com.supervision.police.dto.AnalyseCaseDTO; import com.supervision.police.dto.IndexDetail; import com.supervision.police.dto.IndexResultQuery; import com.supervision.police.service.*; import com.supervision.police.vo.ChatReqVO; import com.supervision.police.vo.ChatResVO; import com.supervision.police.vo.ConversationResVo; import com.supervision.police.vo.dify.DifyChatReqVO; import com.supervision.police.vo.dify.DifyChatResVO; import com.supervision.police.vo.dify.KnowledgeBaseSegmentVO; import com.supervision.utils.DifyApiUtil; import com.supervision.utils.UserUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; import static com.supervision.common.constant.DifyConstants.*; @Slf4j @Service @RequiredArgsConstructor public class ChatServiceImpl implements ChatService { private final LangChainChatService langChainChatService; private final ModelCaseService modelCaseService; private final ModelService modelService; private final ConversationService conversationService; private final ConversationQaService conversationQaService; private final ModelIndexService modelIndexService; private final DifyApiUtil difyApiUtil; private final NoteRecordService noteRecordService; @Override public ChatResVO chat(ChatReqVO chatReqVO) { Assert.notEmpty(chatReqVO.getQuery(), "query 不能为空"); Assert.notEmpty(chatReqVO.getCaseId(), "caseId 不能为空"); ModelCase modelCase = modelCaseService.getById(chatReqVO.getCaseId()); Assert.notNull(modelCase, "案件不存在"); log.info("chat: caseNo:{},query{}", modelCase.getCaseNo(), chatReqVO.getQuery()); ChatResDTO chat = null; try { chat = langChainChatService.chat( ChatReqDTO.create(chatReqVO.getQuery(), modelCase.getCaseNo(), chatReqVO.getHistory())); } catch (Exception e) { log.error("chat: caseNo:{},query{},error:{}", modelCase.getCaseNo(), chatReqVO.getQuery(), e.getMessage(), e); chat = new ChatResDTO(); chat.setAnswer("服务繁忙,请稍后重试!"); } if (null == chat) { chat = new ChatResDTO(); } if (StrUtil.isEmpty(chat.getAnswer())) { chat.setAnswer("我暂时还不知道怎么回答,您可以尝试换一种问法!"); chat.setDocs(new ArrayList<>(1)); } log.info("chat: caseNo:{},query{},answer:{}", modelCase.getCaseNo(), chatReqVO.getQuery(), chat.getAnswer()); return new ChatResVO(chat); } @Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class) @Override public R chatNew(ChatReqVO chatReqVO) { ChatResVO chatResVO = new ChatResVO(); Map answerMap = new HashMap<>(); String query = chatReqVO.getQuery(); String caseId = chatReqVO.getCaseId(); String userId = UserUtil.getUser().getId(); String type = chatReqVO.getType(); String intentType = chatReqVO.getIntentType(); long startTime = System.currentTimeMillis(); if (StringUtils.isEmpty(chatReqVO.getConversationId())) { Conversation conversation = new Conversation(); conversation.setId(UUID.randomUUID().toString()); conversation.setCaseId(caseId); conversation.setUserId(userId); conversationService.save(conversation); chatReqVO.setConversationId(conversation.getId()); log.info("会话已创建,conversationId:{}", conversation.getId()); } else { Conversation conversation = conversationService.getById(chatReqVO.getConversationId()); conversation.setUpdateTime(new Date()); conversationService.updateById(conversation); log.info("会话已更新,conversationId:{}", conversation.getId()); } List modelIndices = modelIndexService.list(); switch (type) { case QA_TYPE_DIFY: if (modelIndices.stream().map(ModelIndex::getName).anyMatch(query::equals)) { type = QA_TYPE_NX_LLM; intentType = INTENT_TYPE_INDEX_RESULT; handleIndexResultQA(modelIndices, query, caseId, answerMap); } else if (INTENT_TYPE_TEXT_CASE_RESULT.equals(query) || INTENT_TYPE_CASE_RESULT.equals(intentType)) { type = QA_TYPE_NX_LLM; intentType = INTENT_TYPE_CASE_RESULT; ModelCase modelCase = modelCaseService.getById(caseId); if (modelCase.getTotalScore() == null) { log.info("案件【{}】尚未执行模型分析,现在开始执行", modelCase.getCaseName()); AnalyseCaseDTO analyseCaseDTO = new AnalyseCaseDTO(); analyseCaseDTO.setCaseId(caseId); modelService.analyseCaseNew(analyseCaseDTO); } answerMap = JSON.parseObject(JSON.toJSONString(modelService.caseScoreDetail(caseId)), Map.class); } else if (INTENT_TYPE_TEXT_CASE_OVERVIEW.equals(query) || INTENT_TYPE_CASE_OVERVIEW.equals(intentType)) { type = QA_TYPE_NX_LLM; intentType = INTENT_TYPE_CASE_OVERVIEW; answerMap.put("answerText", modelCaseService.getById(caseId).getCaseDetail()); } else if (INTENT_TYPE_TEXT_CASE_EVIDENCE_GUIDE.equals(query) || INTENT_TYPE_CASE_EVIDENCE_GUIDE.equals(intentType)) { type = QA_TYPE_NX_LLM; intentType = INTENT_TYPE_CASE_EVIDENCE_GUIDE; answerMap.put("guideDesc", modelService.caseScoreDetail(caseId).getGuideDesc()); } else { ModelCase modelCase = modelCaseService.getById(caseId); DifyChatReqVO difyChatReqVO = new DifyChatReqVO(); difyChatReqVO.setUser(userId); difyChatReqVO.setConversationId(chatReqVO.getConversationId()); difyChatReqVO.setQuery(query); difyChatReqVO.setInputs(Map.of("dataset_id", modelCase.getKnowledgeBaseId(), "participator", modelCase.getLawActor())); DifyChatResVO chat = difyApiUtil.chat(difyChatReqVO); JSONObject json = JSON.parseObject(chat.getAnswer()); chatResVO.setAnswer(json.getString("answerText")); chatResVO.setSegmentList(JSONArray.parseArray(json.getString("quote"), KnowledgeBaseSegmentVO.class)); } break; case QA_TYPE_NX_LLM: switch (intentType) { case INTENT_TYPE_INDEX_RESULT: if (modelIndices.stream().map(ModelIndex::getName).anyMatch(query::equals)) { handleIndexResultQA(modelIndices, query, caseId, answerMap); } else { answerMap.put("answerText", "暂无相关指标信息"); } break; case INTENT_TYPE_CASE_RESULT: ModelCase modelCase = modelCaseService.getById(caseId); if (modelCase.getTotalScore() == null) { log.info("案件【{}】尚未执行模型分析,现在开始执行", modelCase.getCaseName()); AnalyseCaseDTO analyseCaseDTO = new AnalyseCaseDTO(); analyseCaseDTO.setCaseId(caseId); modelService.analyseCaseNew(analyseCaseDTO); } answerMap = JSON.parseObject(JSON.toJSONString(modelService.caseScoreDetail(caseId)), Map.class); break; case INTENT_TYPE_CASE_OVERVIEW: answerMap.put("answerText", modelCaseService.getById(caseId).getCaseDetail()); break; case INTENT_TYPE_CASE_EVIDENCE_GUIDE: answerMap.put("guideDesc", modelService.caseScoreDetail(caseId).getGuideDesc()); break; default: break; } break; default: break; } if (StringUtils.isEmpty(chatResVO.getAnswer()) && "{}".equals(JSON.toJSONString(answerMap))) { log.error("chatNew: 未找到答案,query:【{}】", query); return R.fail("未找到答案"); } long end = System.currentTimeMillis(); ConversationQa qa = new ConversationQa(); qa.setId(UUID.randomUUID().toString()); qa.setQuestion(query); qa.setQuestionTime(new Date(startTime)); qa.setAnswer(chatResVO.getAnswer()); qa.setAnswerMap(JSON.toJSONString(answerMap)); qa.setSegmentList(chatResVO.getSegmentList()); qa.setAnswerTime(new Date(end)); qa.setType(type); qa.setIntentType(intentType); qa.setTimeInterval(String.valueOf(end - startTime)); qa.setCaseId(caseId); qa.setUserId(userId); qa.setConversationId(chatReqVO.getConversationId()); conversationQaService.save(qa); log.info("QA已保存,qaId:【{}】,question:【{}】,answer:【{}】", qa.getId(), query, JSON.toJSONString(answerMap)); chatResVO.setAnswwerMap(answerMap); chatResVO.setType(type); chatResVO.setIntentType(intentType); chatResVO.setConversationId(chatReqVO.getConversationId()); return R.ok(chatResVO); } @Override public IPage queryConversationInfoList(String conversationId, int page, int size) { Assert.notEmpty(conversationId, "会话id不能为空"); IPage qaPage = conversationQaService.lambdaQuery().eq(ConversationQa::getConversationId, conversationId) .orderBy(true, true, ConversationQa::getQuestionTime).page(Page.of(page, size)); return qaPage.convert(ChatResVO::new); } @Override public IPage queryUserConversationList(String userId, int page, int size) { Assert.notEmpty(userId, "用户id不能为空"); return conversationService.queryUserConversationList(userId, DateUtil.offsetDay(DateUtil.date(), -180), null, new Page<>(page, size)); } @Override @Transactional(rollbackFor = Exception.class, transactionManager = "dataSourceTransactionManager") public void deleteConversation(List conversationIdList) { if (CollUtil.isEmpty(conversationIdList)) { return; } for (String conversationId : conversationIdList) { boolean success = conversationService.removeById(conversationId); if (success) { conversationQaService.lambdaUpdate().eq(ConversationQa::getConversationId, conversationId).remove(); } } } /** * 处理指标结果问答 * * @param modelIndices 指标列表 * @param query 问题 * @param caseId 案件id * @param answerMap 答案map */ private void handleIndexResultQA(List modelIndices, String query, String caseId, Map answerMap) { //如果案件分析状态不是分析成功,则先执行案件分析 ModelCase modelCase = modelCaseService.getById(caseId); ModelIndex modelIndex = modelIndices.stream().filter(index -> query.contains(index.getName())).findFirst().get(); IndexResultQuery indexResultQuery = new IndexResultQuery(); indexResultQuery.setCaseId(caseId); indexResultQuery.setIndexType(modelIndex.getIndexType()); indexResultQuery.setIndexName(modelIndex.getName()); IPage indexDetailPage = modelCaseService.getIndexDetail(indexResultQuery, 1, 1); if (indexDetailPage.getRecords().isEmpty() || (modelCase.getTotalScore() == null && modelCase.getCaseAnalysisStatus() != CaseAnalysisStatusEnum.ANALYZED.getCode())) { log.info("案件【{}】尚未执行模型分析,现在开始执行", modelCase.getCaseName()); AnalyseCaseDTO analyseCaseDTO = new AnalyseCaseDTO(); analyseCaseDTO.setCaseId(caseId); modelService.analyseCaseNew(analyseCaseDTO); } indexDetailPage = modelCaseService.getIndexDetail(indexResultQuery, 1, 1); if (!indexDetailPage.getRecords().isEmpty()) { IndexDetail indexDetail = indexDetailPage.getRecords().get(0); answerMap.put("indexName", modelIndex.getName()); answerMap.put("indexType", modelIndex.getIndexType()); answerMap.put("result", Boolean.parseBoolean(indexDetail.getIndexResult()) ? "符合" : "不符合"); List> qaSplitList = new ArrayList<>(); if (!indexDetail.getChildren().isEmpty()) { indexDetail.getChildren().forEach(atomicIndexDTO -> { if (!atomicIndexDTO.getRecordSegmentationList().isEmpty()) { atomicIndexDTO.getRecordSegmentationList().forEach(split -> { Map qaMap = new HashMap<>(); qaMap.put("question", split.getQuestion()); qaMap.put("answer", split.getAnswer()); qaMap.put("noteRecordId", split.getNoteRecordId()); qaMap.put("splitId", split.getId()); qaMap.put("noteName", split.getNoteName()); qaMap.put("noteFileId", split.getNoteFileId()); qaSplitList.add(qaMap); }); } }); } answerMap.put("qaSplitList", qaSplitList); List> evidenceList = new ArrayList<>(); if (!indexDetail.getChildren().isEmpty()) { indexDetail.getChildren().forEach(atomicIndexDTO -> { if (!atomicIndexDTO.getEvidentResultList().isEmpty()) { atomicIndexDTO.getEvidentResultList().forEach(evidentIndexResultDTO -> { Map evidenceMap = new HashMap<>(); evidenceMap.put("evidenceName", evidentIndexResultDTO.getEvidenceName()); evidenceMap.put("evidenceId", evidentIndexResultDTO.getEvidenceId()); evidenceList.add(evidenceMap); }); } }); } answerMap.put("evidenceNames", evidenceList); } } }