添加代码 问答功能代码

main
xueqingkun 11 months ago
parent 17fa2255cb
commit c137fbcad4

@ -1,6 +1,6 @@
package com.supervision.controller;
import com.supervision.dto.MatchQuestionAnswerDTO;
import com.supervision.dto.matchTool.MatchQuestionAnswerDTO;
import com.supervision.service.MatchToolService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@ -1,17 +1,21 @@
package com.supervision.controller;
import com.supervision.dto.RobotTalkDTO;
import com.supervision.dto.robot.RobotTalkDTO;
import com.supervision.service.RobotTalkService;
import com.supervision.vo.robot.ArchivesReqVo;
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;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@Slf4j
@Api(tags = "机器人对话服务")
@RestController
@ -23,15 +27,47 @@ public class RobotTalkController {
@ApiOperation("机器人对话服务(文字)")
@GetMapping("/textTalk2Robot")
public RobotTalkDTO textTalk2Robot(RobotTalkReq robotTalkReq) {
return robotTalkService.textTalk2Robot(robotTalkReq.getSessionId(), robotTalkReq.getMessage());
@PostMapping("/textTalkRobot")
public RobotTalkDTO textTalk2Robot(@RequestBody RobotTalkReq robotTalkReq) {
robotTalkReq.populateSuspectInfo();
return robotTalkService.textTalk2Robot(robotTalkReq);
}
@ApiOperation("机器人对话服务(语音)")
@GetMapping("/videoTalk2Robot")
@PostMapping("/videoTalkRobot")
public RobotTalkDTO videoTalk2Robot(@RequestParam("file") MultipartFile multipartFile,
@ApiParam("对话id") @RequestParam(value = "sessionId",required = false) String sessionId) {
return robotTalkService.videoTalk2Robot(sessionId, multipartFile);
@ModelAttribute RobotTalkReq robotTalkReq) {
robotTalkReq.populateSuspectInfo();
return robotTalkService.videoTalk2Robot(multipartFile, robotTalkReq);
}
@ApiOperation("获取对话内容列表")
@GetMapping("/talkList")
public List<RobotTalkDTO> talkList(String sessionId) {
return robotTalkService.talkList(sessionId);
}
@ApiOperation("获取音频")
@GetMapping("/getAudio")
public void getAudio(HttpServletResponse response,
@RequestParam("audioId")String audioId) throws IOException {
robotTalkService.getAudio(response,audioId);
}
@ApiOperation("下载嫌疑人归档数据")
@GetMapping("/downLoadArchives")
public void downLoadArchives(HttpServletResponse response,
ArchivesReqVo archivesReq) throws IOException {
robotTalkService.downLoadArchives(response,archivesReq);
}
@ApiOperation("下载对话过程中的文件")
@GetMapping("/downLoadFile")
public void downLoadFile(HttpServletResponse response,
String fileType,
String imageId) throws IOException {
robotTalkService.downLoadFile(response,fileType,imageId);
}
}

@ -32,7 +32,7 @@ public class TestController {
@GetMapping("process")
public String process(String templateId,String sessionId) {
QueryProcessDTO process = queryTemplateProcessor.process(templateId, sessionId);
QueryProcessDTO process = queryTemplateProcessor.process(templateId, sessionId,null);
return process.getStringContent();
}

@ -1,5 +1,6 @@
package com.supervision.controller;
import com.supervision.dto.paddlespeech.res.TtsResultDTO;
import com.supervision.service.VoiceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -10,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Objects;
@Slf4j
@Api(tags = "音频处理")
@ -28,6 +30,10 @@ public class VoiceController {
@ApiOperation("文字转语音")
@PostMapping("textToVoice")
public String textToVoice(String text){
return voiceService.textToVoice(text);
TtsResultDTO ttsResultDTO = voiceService.textToVoice(text);
if (Objects.isNull(ttsResultDTO)){
return null;
}
return ttsResultDTO.getAudio();
}
}

@ -1,6 +1,5 @@
package com.supervision.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@ -35,13 +34,18 @@ public class IrSessionHistory implements Serializable {
/**
* ID(ID)
*/
private String userQuestionVideoId;
private String userQuestionVoiceId;
/**
*
*/
private String answer;
/**
* 1: 2 3
*/
private Integer answerType;
/**
* ID
*/

@ -62,4 +62,13 @@ public class IrSessionParam implements Serializable {
@TableField(exist = false)
private static final long serialVersionUID = 1L;
public IrSessionParam() {
}
public IrSessionParam( String sessionId, String paramName, String paramValue) {
this.sessionId = sessionId;
this.paramName = paramName;
this.paramValue = paramValue;
}
}

@ -32,6 +32,11 @@ public class QueryProcessDTO {
*/
private byte[] byteContent;
/**
* id
*/
private String byteContentId;
/**
*
*/

@ -1,51 +0,0 @@
package com.supervision.dto;
import lombok.Data;
/**
* DTO
*/
@Data
public class RobotTalkDTO {
/**
* id
*/
private String sessionId;
/**
* id
*/
private String askId;
/**
* 1-2-3-4-5-
*/
private Integer askContentType;
/**
*
*/
private String askMessage;
/**
* 1-2-3-4-5-
*/
private Integer answerContentType;
/**
*
*/
private String answerMessage;
/**
* id
*/
private String answerVoiceBaseId;
/**
* id
*/
private String answerByteId;
}

@ -0,0 +1,31 @@
package com.supervision.dto.matchTool;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
@Data
public class ExtractInformationDTO {
/**
*
*/
private String name;
/**
*
*/
private String cardNumber;
/**
*
*/
private String idNumber;
/**
*
* @return
*/
public boolean allEmpty() {
return StrUtil.isAllEmpty(name, cardNumber, idNumber);
}
}

@ -1,4 +1,4 @@
package com.supervision.dto;
package com.supervision.dto.matchTool;
import lombok.Data;

@ -1,4 +1,4 @@
package com.supervision.dto;
package com.supervision.dto.matchTool;
import lombok.Data;

@ -19,5 +19,8 @@ public class TtsResultDTO {
private String save_path;
/**
* base64
*/
private String audio;
}

@ -0,0 +1,54 @@
package com.supervision.dto.robot;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class AnswerInfo {
/**
* 1-2-3-4-5-
*/
private Integer contentType;
/**
*
*/
private String message;
/**
*
*/
private Integer audioLength;
/**
* id
*/
private String voiceBaseId;
/**
* base64
*/
private String voiceBase64;
/**
* id
*/
private String answerByteId;
/**
*
*/
private transient byte[] answerByte;
/**
*
*/
private SuspectInfo suspectInfo;
}

@ -0,0 +1,34 @@
package com.supervision.dto.robot;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class AskInfo {
private String askId;
/**
* 1-2-3-4-5-
*/
private Integer contentType;
/**
*
*/
private String message;
/**
* 1-2-3-4-5- 6-
*/
/*private Integer answerContentType;*/
/**
*
*/
private Long audioLength;
}

@ -0,0 +1,9 @@
package com.supervision.dto.robot;
import lombok.Data;
@Data
public class ByteWrapper {
private byte[] result;
}

@ -0,0 +1,29 @@
package com.supervision.dto.robot;
import lombok.Builder;
import lombok.Data;
/**
* DTO
*/
@Data
@Builder
public class RobotTalkDTO {
/**
* id
*/
private String sessionId;
private AskInfo askInfo;
private AnswerInfo answerInfo;
/**
* true-false-
*/
private transient boolean doNext = true;
}

@ -0,0 +1,24 @@
package com.supervision.dto.robot;
import lombok.Data;
import java.util.List;
@Data
public class SuspectInfo {
/**
*
*/
private String name;
/**
*
*/
private List<String> cardNumber;
/**
*
*/
private String idNumber;
}

@ -0,0 +1,46 @@
package com.supervision.handler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
public class StringSplitHandler implements TypeHandler<Object> {
@Override
public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
// 不能作为参数进行查询
}
@Override
public Object getResult(ResultSet rs, String columnName) throws SQLException {
String string = rs.getString(columnName);
if(string==null){
return Collections.emptyList();
}
return Arrays.asList(string.split(","));
}
@Override
public Object getResult(ResultSet rs, int columnIndex) throws SQLException {
String string = rs.getString(columnIndex);
if(string==null){
return Collections.emptyList();
}
return Arrays.asList(string.split(","));
}
@Override
public Object getResult(CallableStatement cs, int columnIndex) throws SQLException {
String string = cs.getString(columnIndex);
if(string==null){
return Collections.emptyList();
}
return Arrays.asList(string.split(","));
}
}

@ -1,5 +1,7 @@
package com.supervision.mapper;
import com.supervision.dto.robot.ByteWrapper;
import com.supervision.dto.robot.SuspectInfo;
import com.supervision.vo.session.CreateAjResVO;
import org.apache.ibatis.annotations.Param;
@ -10,4 +12,16 @@ public interface RobotDataMapper {
List<CreateAjResVO> queryAjByAjidOrAjmc(@Param("ajid") Integer ajid, @Param("ajmc") String ajmc);
List<SuspectInfo> querySuspect(@Param("ajid") Integer ajid, @Param("idNumber") String idNumber,
@Param("name") String name,@Param("cardNumber") String cardNumber);
/**
*
* @return
*/
ByteWrapper capitalFlowImage(String guid);
}

@ -1,6 +1,7 @@
package com.supervision.service;
import com.supervision.dto.MatchQuestionAnswerDTO;
import com.supervision.dto.matchTool.ExtractInformationDTO;
import com.supervision.dto.matchTool.MatchQuestionAnswerDTO;
import java.util.List;
@ -9,4 +10,7 @@ public interface MatchToolService {
void refreshMatchToolLibrary();
List<MatchQuestionAnswerDTO> execMatch(String question);
ExtractInformationDTO extractInformation(String message);
}

@ -1,7 +1,11 @@
package com.supervision.service;
import com.supervision.domain.IrSessionParam;
import com.supervision.dto.QueryProcessDTO;
import java.util.List;
import java.util.function.Supplier;
/**
*
@ -9,12 +13,14 @@ import com.supervision.dto.QueryProcessDTO;
public interface QueryTemplateProcessor {
/**
* idid
* @param templateId id
* @param sessionId id
* @param sessionParamSupplier
* @return
*/
QueryProcessDTO process(String templateId, String sessionId);
QueryProcessDTO process(String templateId, String sessionId, Supplier<List<IrSessionParam>> sessionParamSupplier);
}

@ -1,12 +1,40 @@
package com.supervision.service;
import com.supervision.dto.RobotTalkDTO;
import com.supervision.dto.robot.RobotTalkDTO;
import com.supervision.vo.robot.ArchivesReqVo;
import com.supervision.vo.talk.RobotTalkReq;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
public interface RobotTalkService {
RobotTalkDTO textTalk2Robot(String sessionId, String message);
RobotTalkDTO textTalk2Robot(RobotTalkReq robotTalkReq);
RobotTalkDTO videoTalk2Robot(MultipartFile multipartFile, RobotTalkReq robotTalkReq);
/**
*
* @param sessionId
* @return
*/
List<RobotTalkDTO> talkList(String sessionId);
void getAudio(HttpServletResponse response, String audioId) throws IOException;
/**
*
* @param archivesReq
*/
void downLoadArchives(HttpServletResponse response,ArchivesReqVo archivesReq) throws IOException;
RobotTalkDTO videoTalk2Robot(String sessionId, MultipartFile multipartFile);
void downLoadFile(HttpServletResponse response, String fileType, String imageId) throws IOException;
}

@ -1,5 +1,6 @@
package com.supervision.service;
import com.supervision.dto.paddlespeech.res.TtsResultDTO;
import com.supervision.vo.voice.VoiceReqVO;
import org.springframework.web.multipart.MultipartFile;
@ -9,5 +10,5 @@ public interface VoiceService {
String voiceToText(MultipartFile file, String sessionId) throws IOException;
String textToVoice(String text);
TtsResultDTO textToVoice(String text);
}

@ -3,19 +3,22 @@ package com.supervision.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.supervision.config.domain.GlobalResult;
import com.supervision.domain.IrKnowledge;
import com.supervision.domain.IrKnowledgeSimilar;
import com.supervision.dto.MatchQuestionAnswerDTO;
import com.supervision.dto.MatchToolQuestionDTO;
import com.supervision.dto.matchTool.ExtractInformationDTO;
import com.supervision.dto.matchTool.MatchQuestionAnswerDTO;
import com.supervision.dto.matchTool.MatchToolQuestionDTO;
import com.supervision.dto.QuestionReqDTO;
import com.supervision.exception.BusinessException;
import com.supervision.service.IrKnowledgeService;
import com.supervision.service.IrKnowledgeSimilarService;
import com.supervision.service.MatchToolService;
import com.supervision.vo.matchTool.ExtractInformationReqVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@ -98,6 +101,25 @@ public class MatchToolServiceImpl implements MatchToolService {
}
}
@Override
public ExtractInformationDTO extractInformation(String message) {
log.info("开始调用extractInformation,message:{}", message);
if (StrUtil.isEmpty(message)) {
return null;
}
try {
TimeInterval timer = DateUtil.timer();
String result = HttpUtil.post(matchToolUrl + "/extractInformation", JSONUtil.toJsonStr(new ExtractInformationReqVo(message)));
log.info("抽取信息message:{}抽取结果:{},耗时:{} 毫秒", message, result, timer.intervalMs());
TypeReference<ExtractInformationDTO> globalResultTypeReference = new TypeReference<ExtractInformationDTO>() {
};
return JSONUtil.toBean(result, globalResultTypeReference.getType(), true);
} catch (Exception e) {
log.error("调用extractInformation error ", e);
return null;
}
}
private void submitRefresh(List<MatchToolQuestionDTO> matchToolQuestionDTOList) {
log.info("开始调用matchTool服务进行更新操作");
try {

@ -23,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@Slf4j
@ -40,7 +41,7 @@ public class QueryTemplateProcessorImpl implements QueryTemplateProcessor {
@Override
//note:重新构建一个事务,与调用方事务隔离
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public QueryProcessDTO process(String templateId, String sessionId) {
public QueryProcessDTO process(String templateId, String sessionId, Supplier<List<IrSessionParam>> sessionParamSupplier) {
Assert.notEmpty(templateId, "模板ID不能为空");
@ -61,7 +62,8 @@ public class QueryTemplateProcessorImpl implements QueryTemplateProcessor {
// 查询知识查询sql需要的参数
List<IrSqlParam> paramsList = sqlParamService.lambdaQuery().eq(IrSqlParam::getKnowledgeId, templateId).list();
// 校验知识查询sql必填参数
List<IrSessionParam> sessionParams = sessionParamService.lambdaQuery().eq(IrSessionParam::getSessionId, sessionId).list();
List<IrSessionParam> sessionParams = null == sessionParamSupplier ?
sessionParamService.lambdaQuery().eq(IrSessionParam::getSessionId, sessionId).list() : sessionParamSupplier.get();
Set<String> sessionParamsNames = sessionParams.stream().map(IrSessionParam::getParamName).collect(Collectors.toSet());
paramsList.stream().filter(param -> Integer.valueOf(1).equals(param.getParamRequire())).forEach(param -> {
queryProcessDTO.notNullParam(param.getParamName(),
@ -115,6 +117,7 @@ public class QueryTemplateProcessorImpl implements QueryTemplateProcessor {
// 如果存在byte类型的数据数据key统一命名为 byteContent
queryProcessDTO.setByteContent((byte[]) CollUtil.getFirst(maps).get("byteContent"));
queryProcessDTO.setContentType(3);
queryProcessDTO.setByteContentId(CollUtil.getFirst(maps).get("byteContentId").toString());
}
// 去除回响应字符串中的特殊字符
if (StrUtil.isNotEmpty(queryProcessDTO.getStringContent())){

@ -1,29 +1,42 @@
package com.supervision.service.impl;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
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.domain.*;
import com.supervision.dto.paddlespeech.res.TtsResultDTO;
import com.supervision.dto.robot.*;
import com.supervision.dto.matchTool.ExtractInformationDTO;
import com.supervision.dto.matchTool.MatchQuestionAnswerDTO;
import com.supervision.dto.QueryProcessDTO;
import com.supervision.dto.RobotTalkDTO;
import com.supervision.mapper.RobotDataMapper;
import com.supervision.service.*;
import com.supervision.util.UserUtil;
import com.supervision.vo.robot.ArchivesReqVo;
import com.supervision.vo.talk.RobotTalkReq;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
@Service
@ -40,83 +53,176 @@ public class RobotTalkServiceImpl implements RobotTalkService {
private final IrSessionHistoryService sessionService;
private final IrSessionParamService irSessionParamService;
private final IrVoiceService irVoiceService;
private final IrFileService irFileService;
@Resource
private final RobotDataMapper robotDataMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public RobotTalkDTO textTalk2Robot(String sessionId, String message) {
public RobotTalkDTO textTalk2Robot(RobotTalkReq robotTalkReq) {
String sessionId = robotTalkReq.getSessionId();
String message = robotTalkReq.getMessage();
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);
RobotTalkDTO robotTalkDTO = RobotTalkDTO.builder()
.sessionId(sessionId).doNext(true)
.askInfo(AskInfo.builder().contentType(1).message(robotTalkReq.getMessage()).build())
.answerInfo(AnswerInfo.builder().contentType(robotTalkReq.getAnswerType()).build())
.build();
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);
}
}
// todo识别下载文件的语义
// 提取信息中的关键信息
if (Boolean.FALSE.equals(robotTalkReq.isConfirmFlag())){
extractInformation(sessionId, message, robotTalkDTO);
}
// 匹配问题意图
MatchQuestionAnswerDTO matchQuestionAnswerDTO = matchQuestionAnswer(message);
// 获取机器人配置
IrRobotConfig config = irRobotConfigService.lambdaQuery().one();
String answerText = null;
if (CollUtil.isEmpty(matchQuestionAnswerDTOS)){
if (Objects.isNull(matchQuestionAnswerDTO) && robotTalkDTO.isDoNext()){
// 未匹配到查询意图,设置默认错误语
log.info("问题:{}未匹配到意图",message);
answerText = config.getErrorLanguage();
robotTalkDTO.setAnswerMessage(config.getErrorLanguage());
robotTalkDTO.getAnswerInfo().setMessage(config.getErrorLanguage());
robotTalkDTO.setDoNext(false);
}
// 匹配到查询意图,用第一个意图
QueryProcessDTO process = QueryProcessDTO.builder().state(2).build();
MatchQuestionAnswerDTO matchQuestionAnswerDTO = CollUtil.getFirst(matchQuestionAnswerDTOS);
if (Objects.nonNull(matchQuestionAnswerDTO)){
process = queryTemplateProcessor.process(matchQuestionAnswerDTO.getMatchQuestionCode(), sessionId);
if (robotTalkDTO.isDoNext()){
QueryProcessDTO matchAnswer = queryMatchAnswer(sessionId, matchQuestionAnswerDTO, robotTalkDTO, robotTalkReq.getTitleContent());
if (Integer.valueOf(0).equals(matchAnswer.getState()) &&
Integer.valueOf(3).equals(matchAnswer.getContentType())){
// 查询结果类型为字节数组
robotTalkDTO.getAnswerInfo().setContentType(3);
robotTalkDTO.getAnswerInfo().setAnswerByteId(matchAnswer.getByteContentId());
robotTalkDTO.getAnswerInfo().setAnswerByte(matchAnswer.getByteContent());
}else {
robotTalkDTO.getAnswerInfo().setMessage(decideAnswer(matchAnswer, config));
}
}
// 查询结果类型为字节数组
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);
}
logSessionInfo(robotTalkDTO, matchQuestionAnswerDTO);
log.info("textTalk2Robot:结束问答,耗时:{}ms",timeInterval.interval("all"));
return robotTalkDTO;
}
private void logSessionInfo(RobotTalkDTO robotTalkDTO, MatchQuestionAnswerDTO matchQuestionAnswerDTO) {
// 组装日志信息
IrSessionHistory irSessionHistory = talk2SessionHistory(sessionId, message,
CollUtil.getFirst(matchQuestionAnswerDTOS));
// todo:语音倍速设置
IrSessionHistory irSessionHistory = talk2SessionHistory(robotTalkDTO.getSessionId(),
robotTalkDTO.getAnswerInfo().getMessage(), matchQuestionAnswerDTO);
irSessionHistory.setAnswerType(robotTalkDTO.getAnswerInfo().getContentType());
// 保存回答音频文件
if (StrUtil.isNotEmpty(answerText)){
String audioBase = voiceService.textToVoice(answerText);
IrVoice irVoice = new IrVoice();
irVoice.setVoiceBase64(audioBase);
irVoiceService.save(irVoice);
robotTalkDTO.setAnswerVoiceBaseId(irVoice.getId());
IrVoice irVoice = saveAudioIfNoAbsent(robotTalkDTO.getAnswerInfo().getMessage());
if (Objects.nonNull(irVoice)) {
robotTalkDTO.getAnswerInfo().setVoiceBaseId(irVoice.getId());
robotTalkDTO.getAnswerInfo().setVoiceBase64(irVoice.getVoiceBase64());
robotTalkDTO.getAnswerInfo().setAudioLength(irVoice.getLength());
irSessionHistory.setAnswerVoiceId(irVoice.getId());
}
if (Objects.nonNull(robotTalkDTO.getAnswerInfo().getAnswerByte())) {
// 如果返回的结果是字节,保存到文件表
IrFile irFile = saveFileIfNoAbsent(robotTalkDTO.getAnswerInfo().getAnswerByte());
if (Objects.nonNull(irFile)) {
robotTalkDTO.getAnswerInfo().setContentType(3);
robotTalkDTO.getAnswerInfo().setAnswerByteId(irFile.getId());
}
}
// 写入对话日志
sessionService.save(irSessionHistory);
robotTalkDTO.setAnswerMessage(answerText);
robotTalkDTO.setAskId(irSessionHistory.getId());
log.info("textTalk2Robot:结束问答,耗时:{}ms",timeInterval.interval("all"));
return robotTalkDTO;
robotTalkDTO.getAskInfo().setAskId(irSessionHistory.getId());
}
private IrVoice saveAudioIfNoAbsent(String message) {
if (StrUtil.isEmpty(message)) {
return null;
}
TtsResultDTO resultDTO = voiceService.textToVoice(message);
IrVoice irVoice = new IrVoice();
irVoice.setVoiceBase64(resultDTO.getAudio());
if (NumberUtil.isNumber(resultDTO.getDuration())){
irVoice.setLength(NumberUtil.parseInt(resultDTO.getDuration()));
}
irVoiceService.save(irVoice);
return irVoice;
}
private QueryProcessDTO queryMatchAnswer(String sessionId, MatchQuestionAnswerDTO matchQuestionAnswerDTO,
RobotTalkDTO robotTalkDTO,SuspectInfo suspectInfo) {
QueryProcessDTO process = QueryProcessDTO.builder().state(2).build();
if (Objects.nonNull(matchQuestionAnswerDTO) && robotTalkDTO.isDoNext()) {
process = queryTemplateProcessor.process(matchQuestionAnswerDTO.getMatchQuestionCode(), sessionId,
()->this.suspectInfo2IrSessionParam(sessionId,suspectInfo));
}
return process;
}
private List<IrSessionParam> suspectInfo2IrSessionParam(String sessionId,SuspectInfo suspectInfo) {
List<IrSessionParam> sessionParams = new ArrayList<>();
if (Objects.nonNull(suspectInfo)){
sessionParams.add(new IrSessionParam(sessionId,"jykh",StrUtil.join(",",suspectInfo.getCardNumber())));
sessionParams.add(new IrSessionParam(sessionId,"khrzjhm",suspectInfo.getIdNumber()));
}
IrSessionParam sessionParam = irSessionParamService.lambdaQuery().eq(IrSessionParam::getSessionId, sessionId)
.eq(IrSessionParam::getParamName, "ajid").one();
if (Objects.nonNull(sessionParam)) {
sessionParams.add(sessionParam);
}
return sessionParams;
}
private MatchQuestionAnswerDTO matchQuestionAnswer(String message) {
if (StrUtil.isNotEmpty(message)){
// 如果消息为空,则没必要进行意图匹配
try {
List<MatchQuestionAnswerDTO> matchQuestionAnswerDTOS = matchToolService.execMatch(message);
log.info("问题:{} 匹配到的意图:{}", message, JSONUtil.toJsonStr(matchQuestionAnswerDTOS));
return CollUtil.getFirst(matchQuestionAnswerDTOS);
} catch (Exception e) {
log.error("textTalk2Robot:内容:{} 相似度匹配失败", message,e);
return null;
}
}
return null;
}
private void extractInformation(String sessionId, String message, RobotTalkDTO robotTalkDTO) {
ExtractInformationDTO extractInformationDTO = matchToolService.extractInformation(message);
if (Objects.isNull(extractInformationDTO) || extractInformationDTO.allEmpty()) {
return;
}
// 识别到重要信息
IrSessionParam sessionParam = irSessionParamService.lambdaQuery().eq(IrSessionParam::getSessionId, sessionId).eq(IrSessionParam::getParamName, "ajid").one();
AnswerInfo answerInfo = robotTalkDTO.getAnswerInfo();
if (Objects.isNull(sessionParam) || StrUtil.isEmpty(sessionParam.getParamValue())) {
// 案件id为空需要设置案件id
answerInfo.setContentType(2);
answerInfo.setMessage("请先设置案件id");
robotTalkDTO.setDoNext(false);
} else {
Integer caseNo = StrUtil.isEmpty(sessionParam.getParamValue()) ? null : Integer.valueOf(sessionParam.getParamValue());
List<SuspectInfo> suspectInfos = robotDataMapper.querySuspect(caseNo,
extractInformationDTO.getIdNumber(),
extractInformationDTO.getName(),
extractInformationDTO.getCardNumber());
answerInfo.setContentType(6);
answerInfo.setSuspectInfo(CollUtil.getFirst(suspectInfos));
robotTalkDTO.setDoNext(false);
}
}
private static String decideAnswer(QueryProcessDTO process, IrRobotConfig config) {
@ -134,13 +240,16 @@ public class RobotTalkServiceImpl implements RobotTalkService {
return null;
}
private static IrFile process2File(QueryProcessDTO process) {
byte[] byteContent = process.getByteContent();
private IrFile saveFileIfNoAbsent(byte[] byteContent) {
if (Objects.isNull(byteContent)){
return null;
}
IrFile irFile = new IrFile();
irFile.setFileByte(byteContent);
irFile.setFileSize(byteContent.length);
irFile.setFileName("answer");
irFile.setFileType("F");
irFileService.save(irFile);
return irFile;
}
@ -160,20 +269,89 @@ public class RobotTalkServiceImpl implements RobotTalkService {
@Override
@Transactional(rollbackFor = Exception.class)
public RobotTalkDTO videoTalk2Robot(String sessionId, MultipartFile multipartFile) {
public RobotTalkDTO videoTalk2Robot(MultipartFile multipartFile,RobotTalkReq robotTalkReq) {
String sessionId = robotTalkReq.getSessionId();
Assert.notEmpty(sessionId, "sessionId不能为空");
Assert.notNull(multipartFile, "multipartFile不能为空");
String message = null;
try {
message = voiceService.voiceToText(multipartFile, sessionId);
String message = voiceService.voiceToText(multipartFile, sessionId);
robotTalkReq.setMessage(message);
} catch (IOException e) {
log.error("语音转文字失败", e);
}
RobotTalkDTO robotTalkDTO = this.textTalk2Robot(sessionId, message);
robotTalkDTO.setAskContentType(2);
RobotTalkDTO robotTalkDTO = this.textTalk2Robot(robotTalkReq);
robotTalkDTO.getAskInfo().setContentType(2);
return robotTalkDTO;
}
@Override
public List<RobotTalkDTO> talkList(String sessionId) {
Assert.notEmpty(sessionId, "sessionId不能为空");
List<IrSessionHistory> sessionHistoryList = sessionService.lambdaQuery().eq(IrSessionHistory::getSessionId, sessionId).list();
return sessionHistoryList.stream().map(this::sessionHistory2RobotTalkDTO).collect(Collectors.toList());
}
private RobotTalkDTO sessionHistory2RobotTalkDTO(IrSessionHistory sessionHistory) {
if (Objects.isNull(sessionHistory)){
return null;
}
AskInfo askInfo = AskInfo.builder()
.askId(sessionHistory.getId())
.message(sessionHistory.getUserQuestion())
.contentType(sessionHistory.getAnswerType())
//.audioLength(sessionHistory)
.build();
AnswerInfo answerInfo = AnswerInfo.builder()
.contentType(sessionHistory.getAnswerType())
.answerByteId(sessionHistory.getAnswerVoiceId())
.message(sessionHistory.getAnswer())
.build();
return RobotTalkDTO.builder().sessionId(sessionHistory.getSessionId())
.askInfo(askInfo).answerInfo(answerInfo).build();
}
@Override
public void getAudio(HttpServletResponse response, String audioId) throws IOException {
Assert.notEmpty(audioId, "audioId不能为空");
IrVoice voice = irVoiceService.getById(audioId);
if (Objects.isNull(voice) || StrUtil.isEmpty(voice.getVoiceBase64())){
return;
}
Base64.decodeToStream(voice.getVoiceBase64(), response.getOutputStream(),false);
}
@Override
public void downLoadArchives(HttpServletResponse response,ArchivesReqVo archivesReq) throws IOException {
String path = localArchivesFilePath(archivesReq);
if (StrUtil.isEmpty(path)){
return;
}
IoUtil.copy(Files.newInputStream(Paths.get(path)),response.getOutputStream());
}
@Override
public void downLoadFile(HttpServletResponse response, String fileType, String imageId) throws IOException {
IrFile file = irFileService.getById(imageId);
if (Objects.isNull(file) || Objects.isNull(file.getFileByte())){
return;
}
IoUtil.write(response.getOutputStream(), true, Base64.decode(file.getFileByte()));
}
private String localArchivesFilePath(ArchivesReqVo archivesReq) {
String path = StrUtil.join(File.separator,archivesReq.getCaseId(),
StrUtil.join("-",archivesReq.getName(),archivesReq.getIdNumber()));
// 判断文件是否存在
if (FileUtil.exist(path)){
return path;
}
return null;
}
}

@ -2,6 +2,7 @@ package com.supervision.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import com.supervision.dto.paddlespeech.res.TtsResultDTO;
import com.supervision.service.VoiceService;
import com.supervision.util.AsrUtil;
import com.supervision.util.TtsUtil;
@ -28,10 +29,10 @@ public class VoiceServiceImpl implements VoiceService {
@Override
public String textToVoice(String text) {
log.info("文字转语音开始");
public TtsResultDTO textToVoice(String text) {
log.info("文字转语音开始text:{}",text);
TimeInterval timeInterval = DateUtil.timer();
String transform = TtsUtil.ttsTransform(text);
TtsResultDTO transform = TtsUtil.ttsTransform(text);
log.info("文字转语音结束,耗时:{}", timeInterval.interval());
return transform;
}

@ -17,7 +17,7 @@ public class TtsUtil {
private static final ObjectMapper objectMapper = new ObjectMapper();
public static String ttsTransform(String str) {
public static TtsResultDTO ttsTransform(String str) {
// 构建
String post = HttpUtil.post(TTS_URL, JSONUtil.toJsonStr(new TtsReqDTO(str)));
try {
@ -26,7 +26,7 @@ public class TtsUtil {
if (!response.getSuccess() || ObjectUtil.isEmpty(response.getResult())) {
throw new BusinessException("文字转换语音失败");
}
return response.getResult().getAudio();
return response.getResult();
} catch (Exception e) {
throw new BusinessException("语音转换文字失败", e);
}

@ -0,0 +1,11 @@
package com.supervision.vo.matchTool;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class ExtractInformationReqVo {
private String inputText;
}

@ -0,0 +1,13 @@
package com.supervision.vo.robot;
import lombok.Data;
@Data
public class ArchivesReqVo {
private String caseId;
private String idNumber;
private String name;
}

@ -1,11 +1,53 @@
package com.supervision.vo.talk;
import cn.hutool.core.util.StrUtil;
import com.supervision.dto.robot.SuspectInfo;
import lombok.Data;
@Data
public class RobotTalkReq {
private String sessionId;
private String message;
/**
* 1-2-3-4-5-
*/
private Integer answerType;
private boolean confirmFlag;
// ========方便前端好传参=======>>>>>>
/**
*
*/
private String name;
/**
*
*/
private String cardNumber;
/**
*
*/
private String idNumber;
// <<<<<========方便前端好传参=======
private SuspectInfo titleContent;
public void populateSuspectInfo() {
titleContent = new SuspectInfo();
if (StrUtil.isNotEmpty(name)){
titleContent.setName(name);
}
if (StrUtil.isNotEmpty(cardNumber)){
titleContent.setCardNumber(StrUtil.split(cardNumber,','));
}
if (StrUtil.isNotEmpty(idNumber)){
titleContent.setIdNumber(idNumber);
}
}
}

@ -8,12 +8,12 @@
<id property="id" column="id" jdbcType="VARCHAR"/>
<result property="sessionId" column="session_id" jdbcType="VARCHAR"/>
<result property="userQuestion" column="user_question" jdbcType="VARCHAR"/>
<result property="userQuestionVideoId" column="user_question_video_id" jdbcType="VARCHAR"/>
<result property="userQuestionVoiceId" column="user_question_voice_id" jdbcType="VARCHAR"/>
<result property="matchKnowledgeId" column="match_knowledge_id" jdbcType="VARCHAR"/>
<result property="userId" column="user_id" jdbcType="VARCHAR"/>
<result property="threshold" column="threshold" jdbcType="NUMERIC"/>
<result property="score" column="score" jdbcType="INTEGER"/>
<result property="scoreCause" column="score_cause" jdbcType="INTEGER"/>
<result property="answerType" column="answer_type" jdbcType="INTEGER"/>
<result property="answerTime" column="answer_time" jdbcType="TIMESTAMP"/>
<result property="dealState" column="deal_state" jdbcType="INTEGER"/>
<result property="createUserId" column="create_user_id" jdbcType="VARCHAR"/>
@ -24,8 +24,8 @@
<sql id="Base_Column_List">
id,session_id,user_question,
user_question_video_id,match_knowledge_id,user_id,
threshold,score,score_cause,
user_question_voice_id,match_knowledge_id,user_id,
threshold,score_cause,answer_type,
answer_time,deal_state,create_user_id,
create_time,update_user_id,update_time
</sql>

@ -19,4 +19,48 @@
</select>
<resultMap id="querySuspectMap" type="com.supervision.dto.robot.SuspectInfo" >
<id column="idNumber" property="idNumber"/>
<id column="name" property="name"/>
<result column="cardNumber" property="cardNumber" typeHandler="com.supervision.handler.StringSplitHandler"/>
</resultMap>
<select id="querySuspect" resultMap="querySuspectMap">
select khrzjhm as idNumber,
zhkhmc as name,
string_agg(distinct jykh, ',') as cardNumber
from yxyc_robot_data.yxyc_cj_zj_khxx
where 1=1
<if test="ajid != null">
and ajid = #{ajid}
</if>
<if test="name != null and name != ''">
and zhkhmc like concat('%', #{name}, '%')
</if>
<if test="idNumber != null and idNumber != '' ">
and khrzjhm = #{idNumber}
</if>
<if test="cardNumber != null and cardNumber != '' ">
and jykh = #{cardNumber}
</if>
group by khrzjhm, zhkhmc;
</select>
<select id="capitalFlowImage" resultType="com.supervision.dto.robot.ByteWrapper">
select xyzjlxt result
from yxyc_robot_data.yxyc_xyzjyjt
where guid = #{guid}
</select>
<!--<select id="selectTest" resultType="com.supervision.dto.robot.ByteWrapper">
select xyzjlxt result
from yxyc_robot_data.yxyc_xyzjyjt
where ajid =2 limit 1 offset 10
</select>-->
</mapper>

@ -1,7 +1,11 @@
package com.supervision;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.IoUtil;
import com.supervision.domain.IrFile;
import com.supervision.dto.QueryProcessDTO;
import com.supervision.dto.robot.ByteWrapper;
import com.supervision.mapper.RobotDataMapper;
import com.supervision.service.IrFileService;
import com.supervision.service.IrKnowledgeService;
import com.supervision.service.QueryTemplateProcessor;
@ -18,6 +22,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
@ -101,7 +108,7 @@ class AskApplicationTests {
@Test
void QueryTemplateProcessorProcessTest() {
QueryProcessDTO process = queryTemplateProcessor.process("1770984442920292354", "123");
QueryProcessDTO process = queryTemplateProcessor.process("1770984442920292354", "123",null);
System.out.println(process);
}
@ -124,4 +131,22 @@ class AskApplicationTests {
System.out.println(byId.getFileName());
}
@Resource
private RobotDataMapper robotDataMapper;
@Test
void aaaTest() throws FileNotFoundException {
/*AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(null)*/
ByteWrapper byteWrapper = robotDataMapper.capitalFlowImage("12");
FileOutputStream fos = new FileOutputStream("F:\\tmp\\1\\image11.png");
IoUtil.write(fos, true, Base64.decode(byteWrapper.getResult()));
}
}

Loading…
Cancel
Save