微服务改造
parent
e5b92b5759
commit
1e2b755174
@ -0,0 +1,17 @@
|
||||
package com.supervision.feign;
|
||||
|
||||
import com.supervision.domain.GlobalResult;
|
||||
import com.supervision.vo.rasa.RasaTalkVo;
|
||||
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 = "virtual-patient-rasa", contextId = "VirtualPatientRasa")
|
||||
public interface RasaManageFeignClient {
|
||||
@PostMapping("/rasa/talkRasa")
|
||||
GlobalResult<List<String>> talk(@RequestBody RasaTalkVo rasaTalkVo);
|
||||
|
||||
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package com.supervision.service;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.supervision.domain.GlobalResult;
|
||||
|
||||
public interface RasaService {
|
||||
|
||||
GlobalResult<String> generateRasaYml(String diseaseId);
|
||||
|
||||
GlobalResult<String> trainRasa(String patientId) throws JsonProcessingException;
|
||||
|
||||
GlobalResult<String> runRasa(String patientId) throws JsonProcessingException;
|
||||
}
|
@ -1,247 +0,0 @@
|
||||
package com.supervision.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.supervision.domain.GlobalResult;
|
||||
import com.supervision.exception.BusinessException;
|
||||
import com.supervision.model.*;
|
||||
import com.supervision.pojo.rasa.train.DomainYmlTemplate;
|
||||
import com.supervision.pojo.rasa.train.NluYmlTemplate;
|
||||
import com.supervision.pojo.rasa.train.QuestionAnswerDTO;
|
||||
import com.supervision.pojo.rasa.train.RuleYmlTemplate;
|
||||
import com.supervision.service.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RasaServiceImpl implements RasaService {
|
||||
|
||||
private final ConfigPhysicalToolService configPhysicalToolService;
|
||||
|
||||
private final ConfigAncillaryItemService configAncillaryItemService;
|
||||
|
||||
private final AskTemplateQuestionLibraryService askTemplateQuestionLibraryService;
|
||||
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Value("${rasa.base-url}${rasa.saveRasaFile}")
|
||||
private String saveRasaFileUrl;
|
||||
|
||||
@Value("${rasa.base-url}${rasa.train}")
|
||||
private String trainRasaUrl;
|
||||
|
||||
@Value("${rasa.base-url}${rasa.run}")
|
||||
private String runRasaUrl;
|
||||
|
||||
@Override
|
||||
public GlobalResult<String> generateRasaYml(String patientId) {
|
||||
|
||||
Map<String, File> ymalFileMap = new HashMap<>();
|
||||
// 默认问答MAP
|
||||
Map<String, QuestionAnswerDTO> questionCodeAndIdMap = new HashMap<>();
|
||||
|
||||
List<RuleYmlTemplate.Rule> ruleList = new ArrayList<>();
|
||||
|
||||
// 开始生成各种yaml文件
|
||||
generateNlu(patientId, questionCodeAndIdMap, ymalFileMap);
|
||||
generateDomain(questionCodeAndIdMap, ruleList, ymalFileMap);
|
||||
generateRule(ruleList, ymalFileMap);
|
||||
// 生成压缩文件
|
||||
List<File> tempFile = new ArrayList<>();
|
||||
File tempZipFile = FileUtil.createTempFile(".zip", true);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(bos)) {
|
||||
for (Map.Entry<String, File> fileEntry : ymalFileMap.entrySet()) {
|
||||
zipOutputStream.putNextEntry(new ZipEntry(fileEntry.getKey()));
|
||||
IoUtil.copy(FileUtil.getInputStream(fileEntry.getValue()), zipOutputStream);
|
||||
zipOutputStream.closeEntry();
|
||||
tempFile.add(fileEntry.getValue());
|
||||
}
|
||||
zipOutputStream.finish();
|
||||
// 调用接口传文件
|
||||
HttpRequest request = HttpRequest.post(saveRasaFileUrl);
|
||||
IoUtil.copy(new ByteArrayInputStream(bos.toByteArray()), FileUtil.getOutputStream(tempZipFile));
|
||||
request.form("file", tempZipFile);
|
||||
request.form("modelId", patientId);
|
||||
HttpResponse response = request.execute();
|
||||
String responseBody = response.body();
|
||||
log.info(responseBody);
|
||||
return objectMapper.readValue(responseBody, new TypeReference<GlobalResult<String>>() {
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("生成ZIP文件失败", e);
|
||||
throw new BusinessException("生成ZIP文件失败");
|
||||
} finally {
|
||||
// 最后把临时文件删除
|
||||
tempFile.forEach(FileUtil::del);
|
||||
FileUtil.del(tempZipFile);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateNlu(String patientId,
|
||||
Map<String, QuestionAnswerDTO> intentCodeAndIdMap,
|
||||
Map<String, File> ymalFileMap) {
|
||||
// 首先生成根据意图查找到nlu文件
|
||||
List<NluYmlTemplate.Nlu> nluList = new ArrayList<>();
|
||||
|
||||
// 默认意图
|
||||
List<AskTemplateQuestionLibrary> askTemplateQuestionLibraryList = askTemplateQuestionLibraryService.lambdaQuery().list();
|
||||
// 生成默认意图的nlu
|
||||
for (AskTemplateQuestionLibrary questionLibrary : askTemplateQuestionLibraryList) {
|
||||
// 开始生成
|
||||
NluYmlTemplate.Nlu nlu = new NluYmlTemplate.Nlu();
|
||||
// 拼接格式:code_id(防止重复)
|
||||
String intentCode = questionLibrary.getCode() + "_" + questionLibrary.getId();
|
||||
nlu.setIntent(intentCode);
|
||||
nlu.setExamples(questionLibrary.getQuestion());
|
||||
nluList.add(nlu);
|
||||
// 添加到map中,key为意图编码,value为意图ID
|
||||
intentCodeAndIdMap.put(intentCode, new QuestionAnswerDTO(questionLibrary.getQuestion(), CollUtil.newArrayList( questionLibrary.getId()), questionLibrary.getDescription()));
|
||||
}
|
||||
|
||||
// 这里处理呼出的问题(code和问题不能为空)
|
||||
List<ConfigPhysicalTool> physicalToolList = configPhysicalToolService.lambdaQuery()
|
||||
.isNotNull(ConfigPhysicalTool::getCode)
|
||||
.isNotNull(ConfigPhysicalTool::getCallOutQuestion).list();
|
||||
|
||||
for (ConfigPhysicalTool tool : physicalToolList) {
|
||||
// 把呼出的问题全部加进去
|
||||
NluYmlTemplate.Nlu nlu = new NluYmlTemplate.Nlu();
|
||||
String toolIntent = "tool_" + tool.getCode();
|
||||
nlu.setIntent(toolIntent);
|
||||
nlu.setExamples(tool.getCallOutQuestion());
|
||||
nluList.add(nlu);
|
||||
// answer格式为:---tool---工具ID
|
||||
intentCodeAndIdMap.put(toolIntent,
|
||||
new QuestionAnswerDTO(tool.getCallOutQuestion(),
|
||||
CollUtil.newArrayList("tool_" + tool.getId()), "tool-" + tool.getToolName()));
|
||||
}
|
||||
|
||||
// 生成呼出的辅助检查
|
||||
List<ConfigAncillaryItem> ancillaryItemList = configAncillaryItemService.lambdaQuery()
|
||||
.isNotNull(ConfigAncillaryItem::getCode)
|
||||
.isNotNull(ConfigAncillaryItem::getCallOutQuestion).list();
|
||||
|
||||
for (ConfigAncillaryItem ancillary : ancillaryItemList) {
|
||||
// 把辅助问诊的问题全部加进去
|
||||
NluYmlTemplate.Nlu nlu = new NluYmlTemplate.Nlu();
|
||||
String itemIntent = "ancillary_" + ancillary.getCode();
|
||||
nlu.setIntent(itemIntent);
|
||||
nlu.setExamples(ancillary.getCallOutQuestion());
|
||||
nluList.add(nlu);
|
||||
// answer格式为:---ancillary---工具ID
|
||||
intentCodeAndIdMap.put(itemIntent,
|
||||
new QuestionAnswerDTO(ancillary.getCallOutQuestion(),
|
||||
CollUtil.newArrayList("ancillary_" + ancillary.getId()), "呼出-ancillary-" + ancillary.getItemName()));
|
||||
}
|
||||
NluYmlTemplate nluYmlTemplate = new NluYmlTemplate();
|
||||
nluYmlTemplate.setNlu(nluList);
|
||||
|
||||
// 生成后生成yml文件
|
||||
createYmlFile(NluYmlTemplate.class, "nlu.ftl", nluYmlTemplate, "nlu.yml", ymalFileMap);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void generateDomain(Map<String, QuestionAnswerDTO> questionCodeAndIdMap,
|
||||
List<RuleYmlTemplate.Rule> ruleList, Map<String, File> ymalFileMap) {
|
||||
LinkedHashMap<String, List<String>> responses = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, QuestionAnswerDTO> entry : questionCodeAndIdMap.entrySet()) {
|
||||
String intentCode = entry.getKey();
|
||||
QuestionAnswerDTO value = entry.getValue();
|
||||
String utter = "utter_" + intentCode;
|
||||
responses.put(utter, CollUtil.newArrayList(value.getAnswerList()));
|
||||
ruleList.add(new RuleYmlTemplate.Rule(value.getDesc(), intentCode, utter));
|
||||
}
|
||||
|
||||
|
||||
DomainYmlTemplate domainYmlTemplate = new DomainYmlTemplate();
|
||||
// 意图
|
||||
List<String> intentList = new ArrayList<>(questionCodeAndIdMap.keySet());
|
||||
domainYmlTemplate.setIntents(intentList);
|
||||
// 回复
|
||||
domainYmlTemplate.setResponses(responses);
|
||||
// action
|
||||
List<String> actionList = new ArrayList<>(responses.keySet());
|
||||
domainYmlTemplate.setActions(actionList);
|
||||
// 生成yml文件
|
||||
createYmlFile(DomainYmlTemplate.class, "domain.ftl", domainYmlTemplate, "domain.yml", ymalFileMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成rule
|
||||
*/
|
||||
public void generateRule(List<RuleYmlTemplate.Rule> ruleList, Map<String, File> ymalFileMap) {
|
||||
RuleYmlTemplate ruleYmlTemplate = new RuleYmlTemplate();
|
||||
ruleYmlTemplate.setRules(ruleList);
|
||||
// 生成yml文件
|
||||
createYmlFile(RuleYmlTemplate.class, "rules.ftl", ruleYmlTemplate, "rules.yml", ymalFileMap);
|
||||
}
|
||||
|
||||
private void createYmlFile(Class<?> clazz, String ftlName, Object data, String ymlName, Map<String, File> ymalFileMap) {
|
||||
try {
|
||||
// 这个版本和maven依赖的版本一致
|
||||
Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
|
||||
configuration.setClassForTemplateLoading(clazz, "/templates"); // 模板文件的所在目录
|
||||
// 获取模板
|
||||
Template template = configuration.getTemplate(ftlName);
|
||||
File tempFile = FileUtil.createTempFile(".yml", true);
|
||||
// 创建输出文件
|
||||
try (PrintWriter out = new PrintWriter(tempFile);) {
|
||||
// 填充并生成输出
|
||||
template.process(data, out);
|
||||
} catch (Exception e) {
|
||||
log.error("文件生成失败");
|
||||
}
|
||||
ymalFileMap.put(ymlName, tempFile);
|
||||
} catch (Exception e) {
|
||||
log.error("导出模板失败", e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public GlobalResult<String> trainRasa(String patientId) throws JsonProcessingException {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("modelId", patientId);
|
||||
String responseBody = HttpUtil.post(trainRasaUrl, JSONUtil.toJsonStr(param));
|
||||
return objectMapper.readValue(responseBody, new TypeReference<GlobalResult<String>>() {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public GlobalResult<String> runRasa(String patientId) throws JsonProcessingException {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("modelId", patientId);
|
||||
String responseBody = HttpUtil.post(runRasaUrl, JSONUtil.toJsonStr(param));
|
||||
return objectMapper.readValue(responseBody, new TypeReference<GlobalResult<String>>() {
|
||||
});
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
package com.supervision.util;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.supervision.pojo.paddlespeech.res.AsrResultDTO;
|
||||
import com.supervision.pojo.paddlespeech.res.PaddleSpeechResDTO;
|
||||
import com.supervision.pojo.rasa.train.dto.RasaReqDTO;
|
||||
import com.supervision.pojo.rasa.train.dto.RasaResDTO;
|
||||
import com.supervision.vo.rasa.RasaTalkVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public class RasaUtil {
|
||||
|
||||
private static final Environment environment = SpringBeanUtil.getBean(Environment.class);
|
||||
private static final String RASA_TALK_URL = environment.getProperty("rasa.base-url") + environment.getProperty("rasa.talk");
|
||||
|
||||
public static String talkRasa(String question, String sessionId) {
|
||||
RasaTalkVo rasaTalkVo = new RasaTalkVo();
|
||||
rasaTalkVo.setQuestion(question);
|
||||
rasaTalkVo.setSessionId(sessionId);
|
||||
// 默认为1
|
||||
rasaTalkVo.setModelId("1");
|
||||
String post = HttpUtil.post(RASA_TALK_URL, JSONUtil.toJsonStr(rasaTalkVo));
|
||||
log.info("调用rasa对话返回结果:{}", post);
|
||||
try {
|
||||
JSONObject entries = JSONUtil.parseObj(post);
|
||||
List<String> list = JSONUtil.toList(entries.getStr("data"), String.class);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return "对不起,我没有听懂您说的是什么意思";
|
||||
}
|
||||
return CollUtil.getFirst(list);
|
||||
} catch (Exception e) {
|
||||
log.error("talkRasa error ", e);
|
||||
}
|
||||
return "对不起,我没有听懂您说的是什么意思";
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue