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

312 lines
16 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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<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::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<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, DateUtil.offsetDay(DateUtil.date(), -180), null, new Page<>(page, size));
}
@Override
@Transactional(rollbackFor = Exception.class, transactionManager = "dataSourceTransactionManager")
public void deleteConversation(List<String> 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<ModelIndex> modelIndices, String query, String caseId, Map<String, Object> 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<IndexDetail> 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<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("splitId", split.getId());
qaMap.put("noteName", split.getNoteName());
qaMap.put("noteFileId", split.getNoteFileId());
qaSplitList.add(qaMap);
});
}
});
}
answerMap.put("qaSplitList", qaSplitList);
List<Map<String, String>> evidenceList = new ArrayList<>();
if (!indexDetail.getChildren().isEmpty()) {
indexDetail.getChildren().forEach(atomicIndexDTO -> {
if (!atomicIndexDTO.getEvidentResultList().isEmpty()) {
atomicIndexDTO.getEvidentResultList().forEach(evidentIndexResultDTO -> {
Map<String, String> evidenceMap = new HashMap<>();
evidenceMap.put("evidenceName", evidentIndexResultDTO.getEvidenceName());
evidenceMap.put("evidenceId", evidentIndexResultDTO.getEvidenceId());
evidenceList.add(evidenceMap);
});
}
});
}
answerMap.put("evidenceNames", evidenceList);
}
}
}