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.
virtual-patient/virtual-patient-web/src/main/java/com/supervision/service/impl/AskServiceImpl.java

171 lines
8.9 KiB
Java

package com.supervision.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.supervision.exception.BusinessException;
import com.supervision.model.AskPatientAnswer;
import com.supervision.model.AskTemplateQuestionLibrary;
import com.supervision.model.DiagnosisQaRecord;
import com.supervision.model.Process;
import com.supervision.pojo.vo.TalkReqVO;
import com.supervision.pojo.vo.TalkResultResVO;
import com.supervision.service.AskPatientAnswerService;
import com.supervision.service.AskTemplateQuestionLibraryService;
import com.supervision.service.ProcessService;
import com.supervision.util.*;
import com.supervision.service.AskService;
import com.supervision.pojo.vo.ActionDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.Random;
@Slf4j
@Service
@RequiredArgsConstructor
public class AskServiceImpl implements AskService {
private final ProcessService processService;
private final AskTemplateQuestionLibraryService askTemplateQuestionLibraryService;
private final AskPatientAnswerService askPatientAnswerService;
@Override
public String receiveVoiceFile(MultipartFile file) {
if (file.getSize() <= 0) {
throw new BusinessException("语音内容为空");
}
// 获取音频对应的文字
String text = null;
try {
text = AsrUtil.asrTransformByBytes(file.getBytes());
} catch (Exception e) {
throw new BusinessException("获取语音失败");
}
if (StrUtil.isEmpty(text)) {
throw new BusinessException("语音内容为空");
}
return text;
}
@Override
@Transactional(rollbackFor = Exception.class)
public TalkResultResVO talk(TalkReqVO talkReqVO) {
// 根据processId找到对应的病人
Process process = Optional.ofNullable(processService.getById(talkReqVO.getProcessId())).orElseThrow(() -> new BusinessException("未找到诊疗进程"));
// 调用rasa获取文字内容
String rasaResult = RasaUtil.talkRasa(talkReqVO.getText(), UserUtil.getUser().getId(), process.getPatientId());
// 如果rasa没有识别出来,则返回默认值
if (StrUtil.isBlank(rasaResult)) {
// 这里调用京东数字人接口首先根据token获取房间号
String roomId = HumanUtil.queryRoomId(talkReqVO.getRoomKey(), talkReqVO.getRoomToken());
HumanUtil.textDriven("您好,我没有听懂您说什么", roomId);
}
TalkResultResVO talkResultResVO = new TalkResultResVO();
// 这里校验,rasa回复的结果是不是action
// 这里设置的模板,对于action的动作全部是用ancillary_ | tool_进行标记,详情看生成rasa的yml的代码:RasaServiceImpl.generateDomain
// ancillary_ | tool_
if (rasaResult.startsWith("ancillary_") || rasaResult.startsWith("tool_")) {
log.info("呼出语句:{}", rasaResult);
List<String> actionList = StrUtil.split(rasaResult, '_');
if (actionList.size() > 1) {
// 在这里给socket回复,设置为动作
talkResultResVO.setActionId(actionList.get(1));
talkResultResVO.setType("ancillary".equals(actionList.get(0)) ? 3 : 2);
return talkResultResVO;
}
} else {
String roomId = HumanUtil.queryRoomId(talkReqVO.getRoomKey(), talkReqVO.getRoomToken());
AskTemplateQuestionLibrary library = askTemplateQuestionLibraryService.getById(rasaResult);
if (ObjectUtil.isEmpty(library)) {
log.info("{}:未从问题库中找到,回答未识别语句", rasaResult);
HumanUtil.textDriven("您好,我没有听懂您说什么", roomId);
} else {
AskPatientAnswer askPatientAnswer = askPatientAnswerService.lambdaQuery().eq(AskPatientAnswer::getPatientId, process.getPatientId())
.eq(AskPatientAnswer::getLibraryQuestionId, library.getId()).last("limit 1").one();
// 如果没有找到回答,去默认回答里面看看有没有
if (ObjectUtil.isEmpty(askPatientAnswer)) {
log.info("{}:病历配置的回答:{}:为空,尝试回答默认答案", rasaResult, askPatientAnswer.getId());
// 首先看看default里面是不是存在,如果存在,就从default里面去找
if (CollUtil.isNotEmpty(library.getDefaultAnswer())) {
String resText = library.getDefaultAnswer().get(RandomUtil.randomInt(0, library.getDefaultAnswer().size()));
HumanUtil.textDriven(resText, roomId);
// 保存记录
DiagnosisQaRecord record = new DiagnosisQaRecord();
record.setProcessId(talkReqVO.getProcessId());
record.setAnswerType("default");
// 注意,这里如果有默认回答,回答的结果是默认结果ID
record.setAnswerId(library.getId());
record.setQuestion(talkReqVO.getText());
record.setAnswer(resText);
record.setCreateUserId(UserUtil.getUser().getId());
record.insert();
log.info("{}:找到了默认答案:{}", rasaResult, talkReqVO.getText());
} else {
log.info("{}:没有从默认答案中找到找到默认内容,回复未识别语句", rasaResult);
HumanUtil.textDriven("您好,我没有听懂您说什么", roomId);
}
} else {
if (CollUtil.isEmpty(askPatientAnswer.getAnswer())) {
log.info("{}:病历配置的回答:{}:为空不为空,但在获取的时候,答案为空,尝试回复默认语句", rasaResult, askPatientAnswer.getId());
if (CollUtil.isNotEmpty(library.getDefaultAnswer())) {
String resText = library.getDefaultAnswer().get(RandomUtil.randomInt(0, library.getDefaultAnswer().size()));
log.info("{}:病历配置的回答:{}:为空不为空不为空,但在获取的时候,答案为空,开始回复默认语句,默认语句内容:{}", rasaResult, askPatientAnswer.getId(), resText);
HumanUtil.textDriven(resText, roomId);
// 保存记录
DiagnosisQaRecord record = new DiagnosisQaRecord();
record.setProcessId(talkReqVO.getProcessId());
record.setAnswerType("default");
// 注意,这里如果有默认回答,回答的结果是默认结果ID
record.setAnswerId(library.getId());
record.setQuestion(talkReqVO.getText());
record.setAnswer(resText);
record.setCreateUserId(UserUtil.getUser().getId());
record.insert();
} else {
log.info("{}:病历配置的回答:{}:为空不为空,但在获取的时候,答案为空,但是获取默认语句也为空,那么回复未识别语句", rasaResult, askPatientAnswer.getId());
HumanUtil.textDriven("您好,我没有听懂您说什么", roomId);
}
} else {
String resText = askPatientAnswer.getAnswer().get(RandomUtil.randomInt(0, askPatientAnswer.getAnswer().size()));
log.info("{}:找到了病历配置的回答语句:{},回答内容:{}", rasaResult, askPatientAnswer.getId(), resText);
HumanUtil.textDriven(resText, roomId);
// 保存记录
DiagnosisQaRecord record = new DiagnosisQaRecord();
record.setProcessId(talkReqVO.getProcessId());
record.setAnswerType("patient");
record.setAnswerId(askPatientAnswer.getId());
record.setQuestion(talkReqVO.getText());
record.setAnswer(resText);
record.setCreateUserId(UserUtil.getUser().getId());
record.insert();
}
}
}
}
talkResultResVO.setType(1);
return talkResultResVO;
}
@Override
public String replyVoice() {
String text = "测试:这是文字转语音的测试,测试是否OK";
return TtsUtil.ttsTransform(text);
}
}