You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fu-hsi-service/src/main/java/com/supervision/police/service/impl/ChatServiceImpl.java

234 lines
11 KiB
Java

package com.supervision.police.service.impl;
import cn.hutool.core.lang.Assert;
9 months ago
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.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.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.*;
9 months ago
@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) {
9 months ago
chat = new ChatResDTO();
}
if (StrUtil.isEmpty(chat.getAnswer())) {
9 months ago
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 ChatResVO chatNew(ChatReqVO chatReqVO) {
ChatResVO chatResVO = new ChatResVO();
Map<String, Object> 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<ModelIndex> 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) || INTENT_TYPE_CASE_RESULT.equals(intentType)) {
answerMap = JSON.parseObject(JSON.toJSONString(modelService.caseScoreDetail(caseId)), Map.class);
} else if (INTENT_TYPE_CASE_OVERVIEW.equals(query) || INTENT_TYPE_CASE_OVERVIEW.equals(intentType)) {
ModelCase modelCase = modelCaseService.getById(caseId);
answerMap.put("answerText", modelCase.getCaseDetail());
} else if (INTENT_TYPE_CASE_EVIDENCE_GUIDE.equals(query) || INTENT_TYPE_CASE_EVIDENCE_GUIDE.equals(intentType)) {
CaseScoreDetailDTO caseScoreDetailDTO = modelService.caseScoreDetail(caseId);
answerMap.put("guideDesc", caseScoreDetailDTO.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()));
DifyChatResVO chat = difyApiUtil.chat(difyChatReqVO);
JSONObject json = JSON.parseObject(chat.getAnswer());
chatResVO.setAnswer(json.getString("answerText"));
chatResVO.setSegmentVOList(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::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);
log.info("QA已保存qaId:{}", qa.getId());
chatResVO.setAnswwerMap(answerMap);
chatResVO.setType(type);
chatResVO.setIntentType(intentType);
return chatResVO;
}
/**
*
*
* @param modelIndices
* @param query
* @param caseId id
* @param answerMap map
*/
private void handleIndexResultQA(List<ModelIndex> modelIndices, String query, String caseId, Map<String, Object> 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<IndexDetail> 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<Map<String, String>> qaSplitList = new ArrayList<>();
if (!indexDetail.getChildren().isEmpty()) {
indexDetail.getChildren().forEach(atomicIndexDTO -> {
if (!atomicIndexDTO.getRecordSegmentationList().isEmpty()) {
atomicIndexDTO.getRecordSegmentationList().forEach(split -> {
Map<String, String> 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<String> 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);
}
}
}