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

241 lines
11 KiB
Java

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<String, Object> 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<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)) {
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<ChatResVO> queryConversationInfoList(String conversationId, int page, int size) {
Assert.notEmpty(conversationId, "会话id不能为空");
IPage<ConversationQa> 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<ConversationResVo> 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<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);
}
}
}