package com.supervision.police.service.impl; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; 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.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.IndexDetail; import com.supervision.police.dto.IndexResultQuery; import com.supervision.police.dto.caseScore.CaseScoreDetailDTO; 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.utils.DifyApiUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; 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; @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); } @Override public ChatResVO chatNew(ChatReqVO chatReqVO) { ChatResVO chatResVO = new ChatResVO(); Map answerMap = new HashMap<>(); String query = chatReqVO.getQuery(); String caseId = chatReqVO.getCaseId(); String userId = chatReqVO.getUserId(); 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()); } else { conversationService.updateById(conversationService.getById(chatReqVO.getConversationId())); } List modelIndices = modelIndexService.list(); // 问答类型判断 switch (type) { case QA_TYPE_DIFY: if (modelIndices.stream().map(ModelIndex::getName).anyMatch(query::contains)) { handleIndexResultQA(modelIndices, query, caseId, answerMap); } else if (INTENT_TYPE_TEXT_CASE_RESULT.equals(query)) { answerMap = JSON.parseObject(JSON.toJSONString(modelService.caseScoreDetail(caseId)), Map.class); } else if (INTENT_TYPE_CASE_OVERVIEW.equals(query)) { ModelCase modelCase = modelCaseService.getById(caseId); answerMap.put("answerText", modelCase.getCaseDetail()); } else if (INTENT_TYPE_CASE_EVIDENCE_GUIDE.equals(query)) { CaseScoreDetailDTO caseScoreDetailDTO = modelService.caseScoreDetail(caseId); answerMap.put("guideDesc", caseScoreDetailDTO.getGuideDesc()); } else { ModelCase modelCase = modelCaseService.getById(caseId); DifyChatReqVO difyChatReqVO = new DifyChatReqVO(); difyChatReqVO.setUser(chatReqVO.getUserId()); difyChatReqVO.setConversationId(chatReqVO.getConversationId()); difyChatReqVO.setQuery(chatReqVO.getQuery()); difyChatReqVO.setInputs(Map.of("dataset_id", "13c60b8c-341f-43ea-b3cc-5289a518abd9")); System.out.println(difyApiUtil.chat(difyChatReqVO)); } break; case QA_TYPE_NX_LLM: // 意图判断 switch (intentType) { case INTENT_TYPE_INDEX_RESULT: if (modelIndices.stream().map(ModelIndex::getName).anyMatch(query::contains)) { handleIndexResultQA(modelIndices, query, caseId, answerMap); } else { answerMap.put("answerText", "暂无相关指标信息"); } break; case INTENT_TYPE_CASE_RESULT: answerMap = JSON.parseObject(JSON.toJSONString(modelService.caseScoreDetail(caseId)), Map.class); break; case INTENT_TYPE_CASE_OVERVIEW: ModelCase modelCase = modelCaseService.getById(caseId); answerMap.put("answerText", modelCase.getCaseDetail()); break; case INTENT_TYPE_CASE_EVIDENCE_GUIDE: CaseScoreDetailDTO caseScoreDetailDTO = modelService.caseScoreDetail(caseId); answerMap.put("guideDesc", caseScoreDetailDTO.getGuideDesc()); break; default: break; } break; default: break; } long end = System.currentTimeMillis(); ConversationQa qa = new ConversationQa(); qa.setId(UUID.randomUUID().toString()); qa.setQuestion(query); qa.setQuestionTime(new Date(startTime)); qa.setAnswer(JSON.toJSONString(answerMap)); 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); chatResVO.setAnswwerMap(answerMap); chatResVO.setType(type); chatResVO.setIntentType(intentType); return 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, new Page<>(page,size)); } /** * 处理指标结果问答 * * @param modelIndices 指标列表 * @param query 问题 * @param caseId 案件id * @param answerMap 答案map */ private void handleIndexResultQA(List modelIndices, String query, String caseId, Map answerMap) { 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()) { IndexDetail indexDetail = indexDetailPage.getRecords().get(0); answerMap.put("indexName", modelIndex.getName()); 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("noteRecordName", split.getNoteName()); qaSplitList.add(qaMap); }); } }); } answerMap.put("qaSplitList", qaSplitList); List evidenceNames = new ArrayList<>(); if (!indexDetail.getChildren().isEmpty()) { indexDetail.getChildren().forEach(atomicIndexDTO -> { if (!atomicIndexDTO.getEvidentResultList().isEmpty()) { atomicIndexDTO.getEvidentResultList().forEach(evidentIndexResultDTO -> { evidenceNames.add(evidentIndexResultDTO.getEvidenceName()); }); } }); } answerMap.put("evidenceNames", evidenceNames); } } }