添加代码 问答功能代码
parent
e0845801a2
commit
17fa2255cb
@ -0,0 +1,37 @@
|
||||
package com.supervision.controller;
|
||||
|
||||
|
||||
import com.supervision.dto.RobotTalkDTO;
|
||||
import com.supervision.service.RobotTalkService;
|
||||
import com.supervision.vo.talk.RobotTalkReq;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "机器人对话服务")
|
||||
@RestController
|
||||
@RequestMapping("/robot")
|
||||
@RequiredArgsConstructor
|
||||
public class RobotTalkController {
|
||||
|
||||
private final RobotTalkService robotTalkService;
|
||||
|
||||
|
||||
@ApiOperation("机器人对话服务(文字)")
|
||||
@GetMapping("/textTalk2Robot")
|
||||
public RobotTalkDTO textTalk2Robot(RobotTalkReq robotTalkReq) {
|
||||
return robotTalkService.textTalk2Robot(robotTalkReq.getSessionId(), robotTalkReq.getMessage());
|
||||
}
|
||||
|
||||
@ApiOperation("机器人对话服务(语音)")
|
||||
@GetMapping("/videoTalk2Robot")
|
||||
public RobotTalkDTO videoTalk2Robot(@RequestParam("file") MultipartFile multipartFile,
|
||||
@ApiParam("对话id") @RequestParam(value = "sessionId",required = false) String sessionId) {
|
||||
return robotTalkService.videoTalk2Robot(sessionId, multipartFile);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.supervision.service;
|
||||
|
||||
import com.supervision.dto.RobotTalkDTO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
public interface RobotTalkService {
|
||||
|
||||
RobotTalkDTO textTalk2Robot(String sessionId, String message);
|
||||
|
||||
|
||||
RobotTalkDTO videoTalk2Robot(String sessionId, MultipartFile multipartFile);
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
package com.supervision.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.TimeInterval;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.supervision.domain.IrFile;
|
||||
import com.supervision.domain.IrRobotConfig;
|
||||
import com.supervision.domain.IrSessionHistory;
|
||||
import com.supervision.domain.IrVoice;
|
||||
import com.supervision.dto.MatchQuestionAnswerDTO;
|
||||
import com.supervision.dto.QueryProcessDTO;
|
||||
import com.supervision.dto.RobotTalkDTO;
|
||||
import com.supervision.service.*;
|
||||
import com.supervision.util.UserUtil;
|
||||
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.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RobotTalkServiceImpl implements RobotTalkService {
|
||||
|
||||
private final QueryTemplateProcessor queryTemplateProcessor;
|
||||
|
||||
private final MatchToolService matchToolService;
|
||||
|
||||
private final VoiceService voiceService;
|
||||
|
||||
private final IrRobotConfigService irRobotConfigService;
|
||||
|
||||
private final IrSessionHistoryService sessionService;
|
||||
|
||||
private final IrVoiceService irVoiceService;
|
||||
|
||||
private final IrFileService irFileService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public RobotTalkDTO textTalk2Robot(String sessionId, String message) {
|
||||
Assert.notEmpty(sessionId, "sessionId不能为空");
|
||||
TimeInterval timeInterval = new TimeInterval();
|
||||
timeInterval.start("all");
|
||||
log.info("textTalk2Robot:开始问答,sessionId:{},message:{}",sessionId,message);
|
||||
|
||||
RobotTalkDTO robotTalkDTO = new RobotTalkDTO();
|
||||
robotTalkDTO.setSessionId(sessionId);
|
||||
robotTalkDTO.setAskMessage(message);
|
||||
// 设置问答类型为文本
|
||||
robotTalkDTO.setAskContentType(1);
|
||||
robotTalkDTO.setAnswerContentType(2);
|
||||
|
||||
List<MatchQuestionAnswerDTO> matchQuestionAnswerDTOS = null;
|
||||
if (StrUtil.isNotEmpty(message)){
|
||||
// 如果消息为空,则没必要进行意图匹配
|
||||
try {
|
||||
matchQuestionAnswerDTOS = matchToolService.execMatch(message);
|
||||
log.info("问题:{} 匹配到的意图:{}",message, JSONUtil.toJsonStr(matchQuestionAnswerDTOS));
|
||||
} catch (Exception e) {
|
||||
log.error("textTalk2Robot:内容:{} 相似度匹配失败",message,e);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取机器人配置
|
||||
IrRobotConfig config = irRobotConfigService.lambdaQuery().one();
|
||||
String answerText = null;
|
||||
if (CollUtil.isEmpty(matchQuestionAnswerDTOS)){
|
||||
// 未匹配到查询意图,设置默认错误语
|
||||
log.info("问题:{}未匹配到意图",message);
|
||||
answerText = config.getErrorLanguage();
|
||||
robotTalkDTO.setAnswerMessage(config.getErrorLanguage());
|
||||
}
|
||||
|
||||
// 匹配到查询意图,用第一个意图
|
||||
QueryProcessDTO process = QueryProcessDTO.builder().state(2).build();
|
||||
MatchQuestionAnswerDTO matchQuestionAnswerDTO = CollUtil.getFirst(matchQuestionAnswerDTOS);
|
||||
if (Objects.nonNull(matchQuestionAnswerDTO)){
|
||||
process = queryTemplateProcessor.process(matchQuestionAnswerDTO.getMatchQuestionCode(), sessionId);
|
||||
}
|
||||
|
||||
// 查询结果类型为字节数组
|
||||
if (Integer.valueOf(0).equals(process.getState()) &&
|
||||
Integer.valueOf(3).equals(process.getContentType())){
|
||||
// 返回的结果是字节,保存到文件表
|
||||
IrFile irFile = process2File(process);
|
||||
irFileService.save(irFile);
|
||||
robotTalkDTO.setAnswerContentType(3);
|
||||
robotTalkDTO.setAnswerByteId(irFile.getId());
|
||||
}else {
|
||||
answerText = decideAnswer(process, config);
|
||||
}
|
||||
// 组装日志信息
|
||||
IrSessionHistory irSessionHistory = talk2SessionHistory(sessionId, message,
|
||||
CollUtil.getFirst(matchQuestionAnswerDTOS));
|
||||
// todo:语音倍速设置
|
||||
// 保存回答音频文件
|
||||
if (StrUtil.isNotEmpty(answerText)){
|
||||
String audioBase = voiceService.textToVoice(answerText);
|
||||
IrVoice irVoice = new IrVoice();
|
||||
irVoice.setVoiceBase64(audioBase);
|
||||
irVoiceService.save(irVoice);
|
||||
robotTalkDTO.setAnswerVoiceBaseId(irVoice.getId());
|
||||
irSessionHistory.setAnswerVoiceId(irVoice.getId());
|
||||
}
|
||||
// 写入对话日志
|
||||
sessionService.save(irSessionHistory);
|
||||
robotTalkDTO.setAnswerMessage(answerText);
|
||||
robotTalkDTO.setAskId(irSessionHistory.getId());
|
||||
log.info("textTalk2Robot:结束问答,耗时:{}ms",timeInterval.interval("all"));
|
||||
return robotTalkDTO;
|
||||
}
|
||||
|
||||
private static String decideAnswer(QueryProcessDTO process, IrRobotConfig config) {
|
||||
// 正确查询出结果
|
||||
if (Integer.valueOf(0).equals(process.getState())
|
||||
&& Integer.valueOf(1).equals(process.getContentType())){
|
||||
// 查询结果类型为字符串
|
||||
return process.getStringContent();
|
||||
}
|
||||
// 参数异常或查询结果异常
|
||||
if (Integer.valueOf(1).equals(process.getState())
|
||||
|| Integer.valueOf(2).equals(process.getState())){
|
||||
return config.getUnrecognizedOne();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IrFile process2File(QueryProcessDTO process) {
|
||||
byte[] byteContent = process.getByteContent();
|
||||
IrFile irFile = new IrFile();
|
||||
irFile.setFileByte(byteContent);
|
||||
irFile.setFileSize(byteContent.length);
|
||||
irFile.setFileName("answer");
|
||||
irFile.setFileType("F");
|
||||
return irFile;
|
||||
}
|
||||
|
||||
|
||||
private IrSessionHistory talk2SessionHistory(String sessionId, String message,
|
||||
MatchQuestionAnswerDTO matchQuestionAnswerDTO) {
|
||||
IrSessionHistory sessionHistory = new IrSessionHistory();
|
||||
sessionHistory.setSessionId(sessionId);
|
||||
sessionHistory.setUserQuestion(message);
|
||||
sessionHistory.setCreateUserId(UserUtil.getUser().getId());
|
||||
if (Objects.nonNull(matchQuestionAnswerDTO)){
|
||||
sessionHistory.setMatchKnowledgeId(matchQuestionAnswerDTO.getMatchQuestionCode());
|
||||
sessionHistory.setThreshold(BigDecimal.valueOf(matchQuestionAnswerDTO.getMatchScore()));
|
||||
}
|
||||
return sessionHistory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public RobotTalkDTO videoTalk2Robot(String sessionId, MultipartFile multipartFile) {
|
||||
|
||||
Assert.notEmpty(sessionId, "sessionId不能为空");
|
||||
Assert.notNull(multipartFile, "multipartFile不能为空");
|
||||
|
||||
String message = null;
|
||||
try {
|
||||
message = voiceService.voiceToText(multipartFile, sessionId);
|
||||
} catch (IOException e) {
|
||||
log.error("语音转文字失败", e);
|
||||
}
|
||||
RobotTalkDTO robotTalkDTO = this.textTalk2Robot(sessionId, message);
|
||||
robotTalkDTO.setAskContentType(2);
|
||||
return robotTalkDTO;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.supervision.vo.talk;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RobotTalkReq {
|
||||
|
||||
private String sessionId;
|
||||
private String message;
|
||||
|
||||
}
|
Loading…
Reference in New Issue