dev_2.1.0
liu 1 year ago
parent 660097c1d8
commit f77e013d96

@ -47,6 +47,7 @@ public class WebConfig implements WebMvcConfigurer {
paths.add("/fileManage/downloadFile");
paths.add("/aqLibrary/downloadQuestionLibraryTemplate");
paths.add("/medicalRecManage/downloadMedicalAnswerTemplate");
paths.add("/qaKnowledge/**");
// 开发环境,放开不校验token.每次修改这里需要重启(热部署不行)
// paths.add("/**");
return paths;

@ -0,0 +1,25 @@
package com.supervision.manage.controller.qaKnowledge;
import com.supervision.dto.QaKnowledgeDTO;
import com.supervision.service.AskTemplateQuestionLibraryService;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("qaKnowledge")
@RequiredArgsConstructor
public class QaKnowledgeManageController {
private final AskTemplateQuestionLibraryService askTemplateQuestionLibraryService;
@ApiOperation("获取问答知识库")
@GetMapping("queryQaKnowledge")
public List<QaKnowledgeDTO> queryQaKnowledge() {
return askTemplateQuestionLibraryService.queryQaKnowledge();
}
}

@ -0,0 +1,18 @@
package com.supervision.manage.feign;
import com.supervision.dto.QaKnowledgeDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient(name = "qaKnowledgeManageClient", url = "${qaSimilarity}")
public interface QaKnowledgeManageClient {
@PostMapping("updateDatabase")
void refreshQuestionList(@RequestBody List<QaKnowledgeDTO> qaKnowledgeVOList);
}

@ -0,0 +1,13 @@
package com.supervision.manage.pojo.vo;
import lombok.Data;
import java.util.List;
@Data
public class QaKnowledgeVO {
private String questionCode;
private List<String> questionList;
}

@ -0,0 +1,6 @@
package com.supervision.manage.service;
public interface QaKnowledgeManageService {
void refreshQaKnowledge();
}

@ -15,7 +15,10 @@ import com.supervision.manage.dto.UploadQuestionLibraryDTO;
import com.supervision.manage.pojo.vo.UploadQuestionLibraryResVo;
import com.supervision.manage.service.AskQuestionLibraryManageService;
import com.supervision.manage.service.FileManageService;
import com.supervision.model.*;
import com.supervision.manage.service.QaKnowledgeManageService;
import com.supervision.model.AskTemplateQuestionLibrary;
import com.supervision.model.CommonDic;
import com.supervision.model.FileResource;
import com.supervision.service.AskTemplateQuestionLibraryService;
import com.supervision.service.CommonDicService;
import com.supervision.util.RedisSequenceUtil;
@ -53,8 +56,11 @@ public class AskQuestionLibraryManageServiceImpl implements AskQuestionLibraryMa
private final FileManageService fileManageService;
private final QaKnowledgeManageService qaKnowledgeManageService;
private final String ASK_QUESTION_LIBRARY_TEMPLATE_ERROR_EXCEL_PATH = "classpath:template/ask_question_library_template_error.xlsx";
private final String ASK_QUESTION_LIBRARY_TEMPLATE_EXCEL_PATH = "classpath:template/ask_question_library_template.xlsx";
@Override
public List<AskQuestionLibraryResVo> queryList(AskQuestionLibraryReqVo askQuestionLibraryReqVo) {
@ -93,14 +99,16 @@ public class AskQuestionLibraryManageServiceImpl implements AskQuestionLibraryMa
if (CollUtil.isEmpty(question)){
question = CollUtil.newArrayList(askTemplateQuestionLibrary.getDescription());
one.setDefaultAnswer(askTemplateQuestionLibrary.getDefaultAnswer());
}else if (!question.contains(askTemplateQuestionLibrary.getDescription())){
question.add(0,askTemplateQuestionLibrary.getDescription());
} else if (!question.contains(askTemplateQuestionLibrary.getDescription())) {
question.add(0, askTemplateQuestionLibrary.getDescription());
}
if (StrUtil.isNotEmpty(askTemplateQuestionLibrary.getDefaultAnswer())){
if (StrUtil.isNotEmpty(askTemplateQuestionLibrary.getDefaultAnswer())) {
one.setDefaultAnswer(askTemplateQuestionLibrary.getDefaultAnswer());
}
one.setQuestion(question);
askTemplateQuestionLibraryService.updateById(one);
// 对问题库进行更新操作
qaKnowledgeManageService.refreshQaKnowledge();
return one.getId();
}else {
// 新增数据
@ -131,29 +139,36 @@ public class AskQuestionLibraryManageServiceImpl implements AskQuestionLibraryMa
askTemplateQuestionLibrary.setDefaultAnswerCode(nextDefaultCode);
askTemplateQuestionLibraryService.save(askTemplateQuestionLibrary);
// 对问题库进行更新操作
qaKnowledgeManageService.refreshQaKnowledge();
return askTemplateQuestionLibrary.getId();
}
}
@Override
public boolean updateQuestionLibrary(AskTemplateQuestionLibrary askTemplateQuestionLibrary) {
Assert.notEmpty(askTemplateQuestionLibrary.getId(),"id不能为空");
Assert.notEmpty(askTemplateQuestionLibrary.getId(), "id不能为空");
assertSave(askTemplateQuestionLibrary);
// 不允许修改类目 fix bug 197
AskTemplateQuestionLibrary library = askTemplateQuestionLibraryService.getById(askTemplateQuestionLibrary.getId());
Assert.notNull(library,"知识库不存在");
Assert.isTrue(askTemplateQuestionLibrary.getDictId().equals(library.getDictId()),"不允许修改类目");
Assert.notNull(library, "知识库不存在");
Assert.isTrue(askTemplateQuestionLibrary.getDictId().equals(library.getDictId()), "不允许修改类目");
this.saveQuestionLibrary(askTemplateQuestionLibrary);
// 对问题库进行更新操作
qaKnowledgeManageService.refreshQaKnowledge();
return true;
}
@Override
public boolean deleteQuestionLibrary(String id) {
Assert.notEmpty(id,"id不能为空");
Assert.notEmpty(id, "id不能为空");
return askTemplateQuestionLibraryService.removeById(id);
askTemplateQuestionLibraryService.removeById(id);
// 对问题库进行更新操作
qaKnowledgeManageService.refreshQaKnowledge();
return true;
}
@Override
@ -174,16 +189,18 @@ public class AskQuestionLibraryManageServiceImpl implements AskQuestionLibraryMa
// 更新知识库
List<UploadQuestionLibraryDTO> currentDTOS = uploadQuestionLibraryDTOS.stream().filter(dto -> CollUtil.isEmpty(dto.getErrorCodeEnums())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(currentDTOS)){
if (CollUtil.isNotEmpty(currentDTOS)) {
for (UploadQuestionLibraryDTO currentDTO : currentDTOS) {
AskTemplateQuestionLibrary questionLibrary = new AskTemplateQuestionLibrary();
if (StrUtil.isNotEmpty(currentDTO.getDictId())){
if (StrUtil.isNotEmpty(currentDTO.getDictId())) {
questionLibrary.setDictId(Long.parseLong(currentDTO.getDictId()));
}
questionLibrary.setDescription(currentDTO.getQuestion());
questionLibrary.setDefaultAnswer(currentDTO.getAnswer());
this.saveQuestionLibrary(questionLibrary);
}
// 对问题库进行更新操作
qaKnowledgeManageService.refreshQaKnowledge();
}
timer.restart();
@ -261,6 +278,7 @@ public class AskQuestionLibraryManageServiceImpl implements AskQuestionLibraryMa
// 查询类目字段
List<CommonDic> questionTypeDicList = commonDicService.lambdaQuery().eq(CommonDic::getGroupCode, "AQT").list();
uploadQuestionLibraryDTOS.forEach(dto->dto.doAction(questionLibraryList,questionTypeDicList));
}
/**

@ -0,0 +1,26 @@
package com.supervision.manage.service.impl;
import com.supervision.dto.QaKnowledgeDTO;
import com.supervision.manage.feign.QaKnowledgeManageClient;
import com.supervision.manage.service.QaKnowledgeManageService;
import com.supervision.service.AskTemplateQuestionLibraryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
@Slf4j
public class QaKnowledgeManageServiceImpl implements QaKnowledgeManageService {
private final AskTemplateQuestionLibraryService askTemplateQuestionLibraryService;
private final QaKnowledgeManageClient qaKnowledgeManageClient;
public void refreshQaKnowledge() {
List<QaKnowledgeDTO> queryQaKnowledge = askTemplateQuestionLibraryService.queryQaKnowledge();
qaKnowledgeManageClient.refreshQuestionList(queryQaKnowledge);
}
}

@ -1,5 +1,5 @@
spring:
profiles:
active: test
active: dev
application:
name: virtual-patient-manage

@ -0,0 +1,13 @@
package com.supervision.dto;
import lombok.Data;
import java.util.List;
@Data
public class QaKnowledgeDTO {
private String questionCode;
private List<String> questionList;
}

@ -1,8 +1,9 @@
package com.supervision.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.model.AskTemplateQuestionLibrary;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.dto.QaKnowledgeDTO;
import com.supervision.model.AskTemplateQuestionLibrary;
import com.supervision.vo.manage.AskQuestionLibraryReqVo;
import com.supervision.vo.manage.AskQuestionLibraryResVo;
@ -23,4 +24,11 @@ public interface AskTemplateQuestionLibraryService extends IService<AskTemplateQ
String getMaxCode();
String getMaxDefaultAnswerCode();
/**
* ,ID,便使
*
* @return
*/
List<QaKnowledgeDTO> queryQaKnowledge();
}

@ -1,26 +1,41 @@
package com.supervision.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.dto.QaKnowledgeDTO;
import com.supervision.mapper.AskTemplateQuestionLibraryMapper;
import com.supervision.model.AskTemplateQuestionLibrary;
import com.supervision.model.ConfigAncillaryItem;
import com.supervision.model.ConfigPhysicalTool;
import com.supervision.service.AskTemplateQuestionLibraryService;
import com.supervision.mapper.AskTemplateQuestionLibraryMapper;
import com.supervision.service.ConfigAncillaryItemService;
import com.supervision.service.ConfigPhysicalToolService;
import com.supervision.vo.manage.AskQuestionLibraryReqVo;
import com.supervision.vo.manage.AskQuestionLibraryResVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author flevance
* @description vp_ask_template_question_library()Service
* @createDate 2023-11-03 11:13:26
*/
* @author flevance
* @description vp_ask_template_question_library()Service
* @createDate 2023-11-03 11:13:26
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class AskTemplateQuestionLibraryServiceImpl extends ServiceImpl<AskTemplateQuestionLibraryMapper, AskTemplateQuestionLibrary>
implements AskTemplateQuestionLibraryService{
implements AskTemplateQuestionLibraryService {
private final ConfigPhysicalToolService configPhysicalToolService;
private final ConfigAncillaryItemService configAncillaryItemService;
@Override
public List<AskQuestionLibraryResVo> queryList(AskQuestionLibraryReqVo askQuestionLibraryReqVo) {
@ -44,16 +59,69 @@ public class AskTemplateQuestionLibraryServiceImpl extends ServiceImpl<AskTempla
}
return askTemplateQuestionLibrary.getCode();
}
@Override
public String getMaxDefaultAnswerCode() {
AskTemplateQuestionLibrary askTemplateQuestionLibrary = super.getBaseMapper()
.selectOne(new QueryWrapper<AskTemplateQuestionLibrary>()
.select("max(default_answer_code) as default_answer_code"));
if (Objects.isNull(askTemplateQuestionLibrary)){
if (Objects.isNull(askTemplateQuestionLibrary)) {
return null;
}
return askTemplateQuestionLibrary.getDefaultAnswerCode();
}
@Override
public List<QaKnowledgeDTO> queryQaKnowledge() {
// 查询所有的问题,忽略错误和静默视频
List<AskTemplateQuestionLibrary> libraryList = this.lambdaQuery()
.ne(AskTemplateQuestionLibrary::getDictId, 180).ne(AskTemplateQuestionLibrary::getDictId, 182).list();
List<QaKnowledgeDTO> knowledgeList = new ArrayList<>();
for (AskTemplateQuestionLibrary library : libraryList) {
QaKnowledgeDTO qaKnowledgeDTO = new QaKnowledgeDTO();
qaKnowledgeDTO.setQuestionCode(library.getId());
qaKnowledgeDTO.setQuestionList(library.getQuestion());
knowledgeList.add(qaKnowledgeDTO);
}
// 这里处理呼出体格检查的问题
List<ConfigPhysicalTool> physicalToolList = configPhysicalToolService.lambdaQuery()
.isNotNull(ConfigPhysicalTool::getCode)
.isNotNull(ConfigPhysicalTool::getCallOutQuestion).list();
for (ConfigPhysicalTool tool : physicalToolList) {
if (CollUtil.isEmpty(tool.getCallOutQuestion())) {
log.warn("getIntentCodeAndIdMap: toolId:{},toolName:{},tool.getCallOutQuestion() is empty", tool.getId(), tool.getToolName());
continue;
}
// 把呼出的问题全部加进去
String toolIntent = "tool_" + tool.getCode();
QaKnowledgeDTO qaKnowledgeDTO = new QaKnowledgeDTO();
qaKnowledgeDTO.setQuestionCode(toolIntent);
qaKnowledgeDTO.setQuestionList(tool.getCallOutQuestion());
knowledgeList.add(qaKnowledgeDTO);
}
// 生成呼出的辅助检查的问题
List<ConfigAncillaryItem> ancillaryItemList = configAncillaryItemService.lambdaQuery()
.isNotNull(ConfigAncillaryItem::getCode)
.isNotNull(ConfigAncillaryItem::getCallOutQuestion).list();
for (ConfigAncillaryItem ancillary : ancillaryItemList) {
if (CollUtil.isEmpty(ancillary.getCallOutQuestion())) {
log.warn("getIntentCodeAndIdMap: ancillaryId:{},itemName:{},ancillary.getCallOutQuestion() is empty", ancillary.getId(), ancillary.getItemName());
continue;
}
// 把辅助问诊的问题全部加进去
String ancillaryIntent = "ancillary_" + ancillary.getCode();
QaKnowledgeDTO qaKnowledgeDTO = new QaKnowledgeDTO();
qaKnowledgeDTO.setQuestionCode(ancillaryIntent);
qaKnowledgeDTO.setQuestionList(ancillary.getCallOutQuestion());
knowledgeList.add(qaKnowledgeDTO);
}
return knowledgeList;
}
}

@ -0,0 +1,19 @@
package com.supervision.feign;
import com.supervision.domain.GlobalResult;
import com.supervision.pojo.qaSimilarity.QaSimilarityQuestion;
import com.supervision.pojo.qaSimilarity.QaSimilarityQuestionAnswer;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient(name = "askQaSimilarityFeignClient", url = "${qaSimilarity}")
public interface AskQaSimilarityFeignClient {
@PostMapping("matchQuestion")
GlobalResult<List<QaSimilarityQuestionAnswer>> askQuestionSimilarityAnswer(@RequestBody QaSimilarityQuestion question);
}

@ -0,0 +1,11 @@
package com.supervision.pojo.qaSimilarity;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class QaSimilarityQuestion {
private String question;
}

@ -0,0 +1,13 @@
package com.supervision.pojo.qaSimilarity;
import lombok.Data;
@Data
public class QaSimilarityQuestionAnswer {
private String matchQuestion;
private String matchQuestionCode;
private Double matchScore;
}

@ -9,17 +9,21 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import com.supervision.domain.GlobalResult;
import com.supervision.exception.BusinessException;
import com.supervision.feign.AskQaSimilarityFeignClient;
import com.supervision.feign.RasaManageFeignClient;
import com.supervision.model.Process;
import com.supervision.model.*;
import com.supervision.pojo.qaSimilarity.QaSimilarityQuestion;
import com.supervision.pojo.qaSimilarity.QaSimilarityQuestionAnswer;
import com.supervision.pojo.vo.TalkResultResVO;
import com.supervision.pojo.vo.TalkVideoReqVO;
import com.supervision.service.*;
import com.supervision.util.*;
import com.supervision.util.AsrUtil;
import com.supervision.util.MinioUtil;
import com.supervision.util.UserUtil;
import com.supervision.vo.rasa.RasaTalkVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@ -46,6 +50,8 @@ public class AskServiceImpl implements AskService {
private final RasaManageFeignClient rasaManageFeignClient;
private final AskQaSimilarityFeignClient askQaSimilarityFeignClient;
private final CommonDicService commonDicService;
@Override
@ -117,12 +123,13 @@ public class AskServiceImpl implements AskService {
// 根据processId找到对应的病人
Process process = Optional.ofNullable(processService.getById(talkReqVO.getProcessId())).orElseThrow(() -> new BusinessException("未找到诊疗进程"));
String talkResult = talkQaSimilarity(talkReqVO.getText(), UserUtil.getUser().getId());
// 调用rasa获取文字内容
String rasaResult = talkRasa(talkReqVO.getText(), UserUtil.getUser().getId());
log.info("rasa的回复是:{}", rasaResult);
//String rasaResult = talkRasa(talkReqVO.getText(), UserUtil.getUser().getId());
log.info("rasa的回复是:{}", talkResult);
TalkResultResVO talkResultResVO = new TalkResultResVO();
// 如果rasa没有识别出来,则返回默认值
if (StrUtil.isBlank(rasaResult)) {
if (StrUtil.isBlank(talkResult)) {
AskPatientAnswer medicalRecErrorAnswer = getMedicalRecErrorAnswer(process.getMedicalRecId());
talkResultResVO.setVideoBase64(getAnswerVideoBase64OrDefault(medicalRecErrorAnswer.getAnswerResourceId()));
talkResultResVO.setAnswerMessage(medicalRecErrorAnswer.getAnswer());
@ -134,20 +141,20 @@ public class AskServiceImpl implements AskService {
// 这里校验,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 (talkResult.startsWith("ancillary_") || talkResult.startsWith("tool_")) {
log.info("呼出语句:{}", talkResult);
List<String> actionList = StrUtil.split(talkResult, '_');
if (actionList.size() > 1) {
// 在这里给socket回复,设置为动作
// 在这里设置为动作
talkResultResVO.setActionId(actionList.get(1));
talkResultResVO.setType("ancillary".equals(actionList.get(0)) ? 3 : 2);
setActionRelation(talkResultResVO);
return talkResultResVO;
}
} else {
AskTemplateQuestionLibrary library = askTemplateQuestionLibraryService.getById(rasaResult);
AskTemplateQuestionLibrary library = askTemplateQuestionLibraryService.getById(talkResult);
if (ObjectUtil.isEmpty(library)) {
log.info("{}:未从问题库中找到,回答未识别语句", rasaResult);
log.info("{}:未从问题库中找到,回答未识别语句", talkResult);
AskPatientAnswer medicalRecErrorAnswer = getMedicalRecErrorAnswer(process.getMedicalRecId());
talkResultResVO.setVideoBase64(getAnswerVideoBase64OrDefault(medicalRecErrorAnswer.getAnswerResourceId()));
talkResultResVO.setAnswerMessage(medicalRecErrorAnswer.getAnswer());
@ -157,15 +164,15 @@ public class AskServiceImpl implements AskService {
AskPatientAnswer askPatientAnswer = askPatientAnswerService.lambdaQuery().eq(AskPatientAnswer::getMedicalId, process.getMedicalRecId())
.eq(AskPatientAnswer::getLibraryQuestionId, library.getId()).last("limit 1").one();
if (ObjectUtil.isNotEmpty(askPatientAnswer) && StrUtil.isNotEmpty(askPatientAnswer.getAnswerResourceId())){
if (ObjectUtil.isNotEmpty(askPatientAnswer) && StrUtil.isNotEmpty(askPatientAnswer.getAnswerResourceId())) {
String resText = askPatientAnswer.getAnswer();
log.info("{}:找到了病历配置的回答语句:{},回答内容:{}", rasaResult, askPatientAnswer.getId(), resText);
log.info("{}:找到了病历配置的回答语句:{},回答内容:{}", talkResult, askPatientAnswer.getId(), resText);
talkResultResVO.setVideoBase64(getAnswerVideoBase64OrDefault(askPatientAnswer.getAnswerResourceId()));
talkResultResVO.setAnswerMessage(askPatientAnswer.getAnswer());
// 保存记录
saveQaRecord(talkReqVO.getProcessId(), "patient", askPatientAnswer.getId(), talkReqVO.getText(), library, resText);
}else {
log.info("{}:病历配置,从AskPatientAnswer中未找到回答结果,回复未识别到语句", rasaResult);
} else {
log.info("{}:病历配置,从AskPatientAnswer中未找到回答结果,回复未识别到语句", talkResult);
AskPatientAnswer medicalRecErrorAnswer = getMedicalRecErrorAnswer(process.getMedicalRecId());
talkResultResVO.setVideoBase64(getAnswerVideoBase64OrDefault(medicalRecErrorAnswer.getAnswerResourceId()));
talkResultResVO.setAnswerMessage(medicalRecErrorAnswer.getAnswer());
@ -196,6 +203,14 @@ public class AskServiceImpl implements AskService {
return null;
}
public String talkQaSimilarity(String question, String sessionId) {
GlobalResult<List<QaSimilarityQuestionAnswer>> result = askQaSimilarityFeignClient.askQuestionSimilarityAnswer(new QaSimilarityQuestion(question));
if (200 != result.getCode()) {
throw new BusinessException("相似度匹配失败");
}
return CollUtil.getFirst(result.getData()).getMatchQuestionCode();
}
private AskPatientAnswer getMedicalRecErrorAnswer(String medicalRecId) {
//Optional.ofNullable(medicalRecErrorAnswer).orElseGet(() ->new AskPatientAnswer()).getAnswer()
Assert.notEmpty(medicalRecId, "病历id不能为空");

@ -1,5 +1,5 @@
spring:
profiles:
active: dev
active: test
application:
name: virtual-patient-web
Loading…
Cancel
Save