@ -19,6 +19,7 @@ import com.supervision.mapper.RobotDataMapper;
import com.supervision.service.* ;
import com.supervision.util.UserUtil ;
import com.supervision.vo.robot.ArchivesReqVo ;
import com.supervision.vo.robot.CommonDialogVo ;
import com.supervision.vo.talk.RobotTalkReq ;
import lombok.RequiredArgsConstructor ;
import lombok.extern.slf4j.Slf4j ;
@ -33,9 +34,7 @@ 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.* ;
import java.util.stream.Collectors ;
@Slf4j
@ -66,11 +65,10 @@ public class RobotTalkServiceImpl implements RobotTalkService {
@Transactional ( rollbackFor = Exception . class )
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 ) ;
log . info ( "textTalk2Robot:开始问答, 参数:{}", JSONUtil . toJsonStr ( robotTalkReq ) ) ;
RobotTalkDTO robotTalkDTO = RobotTalkDTO . builder ( )
. sessionId ( sessionId ) . doNext ( true )
@ -78,19 +76,28 @@ public class RobotTalkServiceImpl implements RobotTalkService {
. answerInfo ( AnswerInfo . builder ( ) . contentType ( robotTalkReq . getAnswerType ( ) ) . build ( ) )
. build ( ) ;
// todo: 识别下载文件的语义
// 确认弹框信息
if ( StrUtil . isNotEmpty ( robotTalkReq . getAskId ( ) ) ) {
IrSessionHistory sessionHistory = sessionService . lambdaQuery ( ) . eq ( IrSessionHistory : : getId , robotTalkReq . getAskId ( ) ) . one ( ) ;
if ( Objects . nonNull ( sessionHistory ) ) {
robotTalkReq . setMessage ( sessionHistory . getUserQuestion ( ) ) ;
robotTalkReq . setConfirmFlag ( true ) ;
robotTalkDTO . getAskInfo ( ) . setAskId ( robotTalkReq . getAskId ( ) ) ;
}
}
// 提取信息中的关键信息
if ( Boolean . FALSE . equals ( robotTalkReq . isConfirmFlag ( ) ) ) {
extractInformation ( sessionId , message , robotTalkDTO ) ;
extractInformation ( sessionId , robotTalkReq. getMessage ( ) , robotTalkDTO ) ;
}
// 匹配问题意图
MatchQuestionAnswerDTO matchQuestionAnswerDTO = matchQuestionAnswer ( message ) ;
MatchQuestionAnswerDTO matchQuestionAnswerDTO = robotTalkDTO . isDoNext ( ) ? matchQuestionAnswer ( robotTalkReq . getMessage ( ) ) : null ;
// 获取机器人配置
IrRobotConfig config = irRobotConfigService . lambdaQuery ( ) . one ( ) ;
if ( Objects . isNull ( matchQuestionAnswerDTO ) & & robotTalkDTO . isDoNext ( ) ) {
// 未匹配到查询意图,设置默认错误语
log . info ( "问题:{}未匹配到意图" , message ) ;
log . info ( "问题:{}未匹配到意图" , robotTalkReq. getMessage ( ) ) ;
robotTalkDTO . getAnswerInfo ( ) . setMessage ( config . getErrorLanguage ( ) ) ;
robotTalkDTO . setDoNext ( false ) ;
}
@ -101,14 +108,16 @@ public class RobotTalkServiceImpl implements RobotTalkService {
Integer . valueOf ( 3 ) . equals ( matchAnswer . getContentType ( ) ) ) {
// 查询结果类型为字节数组
robotTalkDTO . getAnswerInfo ( ) . setContentType ( 3 ) ;
robotTalkDTO . getAnswerInfo ( ) . set Answer ByteId( matchAnswer . getByteContentId ( ) ) ;
robotTalkDTO . getAnswerInfo ( ) . set ByteId( matchAnswer . getByteContentId ( ) ) ;
robotTalkDTO . getAnswerInfo ( ) . setAnswerByte ( matchAnswer . getByteContent ( ) ) ;
} else {
} else {
robotTalkDTO . getAnswerInfo ( ) . setAnswerFile ( matchAnswer . getFileContent ( ) ) ;
robotTalkDTO . getAnswerInfo ( ) . setMessage ( decideAnswer ( matchAnswer , config ) ) ;
}
}
logSessionInfo ( robotTalkDTO , matchQuestionAnswerDTO ) ;
robotTalkDTO . getAnswerInfo ( ) . setVoiceBase64 ( null ) ;
log . info ( "textTalk2Robot:结束问答,耗时:{}ms" , timeInterval . interval ( "all" ) ) ;
return robotTalkDTO ;
@ -117,8 +126,7 @@ public class RobotTalkServiceImpl implements RobotTalkService {
private void logSessionInfo ( RobotTalkDTO robotTalkDTO , MatchQuestionAnswerDTO matchQuestionAnswerDTO ) {
// 组装日志信息
IrSessionHistory irSessionHistory = talk2SessionHistory ( robotTalkDTO . getSessionId ( ) ,
robotTalkDTO . getAnswerInfo ( ) . getMessage ( ) , matchQuestionAnswerDTO ) ;
irSessionHistory . setAnswerType ( robotTalkDTO . getAnswerInfo ( ) . getContentType ( ) ) ;
robotTalkDTO , matchQuestionAnswerDTO ) ;
// 保存回答音频文件
IrVoice irVoice = saveAudioIfNoAbsent ( robotTalkDTO . getAnswerInfo ( ) . getMessage ( ) ) ;
@ -129,16 +137,17 @@ public class RobotTalkServiceImpl implements RobotTalkService {
irSessionHistory . setAnswerVoiceId ( irVoice . getId ( ) ) ;
}
if ( Objects . nonNull ( robotTalkDTO . getAnswerInfo ( ) . getAnswerByte ( ) ) ) {
if ( Objects . nonNull ( robotTalkDTO . getAnswerInfo ( ) . getAnswerByte ( ) )
| | Objects . nonNull ( robotTalkDTO . getAnswerInfo ( ) . getAnswerFile ( ) ) ) {
// 如果返回的结果是字节,保存到文件表
IrFile irFile = saveFileIfNoAbsent ( robotTalkDTO . getAnswerInfo ( ) .getAnswerByte ( ) );
IrFile irFile = saveFileIfNoAbsent ( robotTalkDTO . getAnswerInfo ( ) );
if ( Objects . nonNull ( irFile ) ) {
robotTalkDTO . getAnswerInfo ( ) . setContentType ( 3 ) ;
robotTalkDTO . getAnswerInfo ( ) . set Answer ByteId( irFile . getId ( ) ) ;
robotTalkDTO . getAnswerInfo ( ) . set ByteId( irFile . getId ( ) ) ;
}
}
// 写入对话日志
sessionService . save ( irSessionHistory ) ;
sessionService . save OrUpdate ( irSessionHistory ) ;
robotTalkDTO . getAskInfo ( ) . setAskId ( irSessionHistory . getId ( ) ) ;
}
@ -173,6 +182,7 @@ public class RobotTalkServiceImpl implements RobotTalkService {
if ( Objects . nonNull ( suspectInfo ) ) {
sessionParams . add ( new IrSessionParam ( sessionId , "jykh" , StrUtil . join ( "," , suspectInfo . getCardNumber ( ) ) ) ) ;
sessionParams . add ( new IrSessionParam ( sessionId , "khrzjhm" , suspectInfo . getIdNumber ( ) ) ) ;
sessionParams . add ( new IrSessionParam ( sessionId , "khrmc" , suspectInfo . getName ( ) ) ) ;
}
IrSessionParam sessionParam = irSessionParamService . lambdaQuery ( ) . eq ( IrSessionParam : : getSessionId , sessionId )
@ -220,17 +230,32 @@ public class RobotTalkServiceImpl implements RobotTalkService {
extractInformationDTO . getCardNumber ( ) ) ;
answerInfo . setContentType ( 6 ) ;
answerInfo . setSuspectInfo ( CollUtil . getFirst ( suspectInfos ) ) ;
SuspectInfo suspectInfo = Objects . isNull ( CollUtil . getFirst ( suspectInfos ) ) ?
extractInformation2Suspect ( extractInformationDTO ) : CollUtil . getFirst ( suspectInfos ) ;
answerInfo . setSuspectInfo ( suspectInfo ) ;
robotTalkDTO . setDoNext ( false ) ;
}
}
private SuspectInfo extractInformation2Suspect ( ExtractInformationDTO informationDTO ) {
SuspectInfo suspectInfo = new SuspectInfo ( ) ;
suspectInfo . setName ( informationDTO . getName ( ) ) ;
suspectInfo . setIdNumber ( informationDTO . getIdNumber ( ) ) ;
if ( StrUtil . isNotEmpty ( informationDTO . getCardNumber ( ) ) ) {
suspectInfo . setCardNumber ( CollUtil . newArrayList ( informationDTO . getCardNumber ( ) ) ) ;
}
return suspectInfo ;
}
private static String decideAnswer ( QueryProcessDTO process , IrRobotConfig config ) {
// 正确查询出结果
if ( Integer . valueOf ( 0 ) . equals ( process . getState ( ) )
& & Integer . valueOf ( 1 ) . equals ( process . getContentType ( ) ) ) {
// 查询结果类型为字符串
if ( Integer . valueOf ( 0 ) . equals ( process . getState ( ) ) ) {
if ( Integer . valueOf ( 1 ) . equals ( process . getContentType ( ) ) | |
Integer . valueOf ( 6 ) . equals ( process . getContentType ( ) ) ) {
// 查询结果类型为字符串
return process . getStringContent ( ) ;
}
}
// 参数异常或查询结果异常
if ( Integer . valueOf ( 1 ) . equals ( process . getState ( ) )
@ -240,25 +265,36 @@ public class RobotTalkServiceImpl implements RobotTalkService {
return null ;
}
private IrFile saveFileIfNoAbsent ( byte [ ] byteContent ) {
if ( Objects . isNull ( byteContent ) ) {
private IrFile saveFileIfNoAbsent ( AnswerInfo answerInfo ) {
if ( Objects . isNull ( answerInfo. getAnswerByte ( ) ) & & Objects . isNull ( answerInfo . getAnswerFile ( ) ) ) {
return null ;
}
String fileType = Integer . valueOf ( 3 ) . equals ( answerInfo . getContentType ( ) ) ? "1" : "2" ;
IrFile irFile = new IrFile ( ) ;
irFile . setFileByte ( byteContent ) ;
irFile . setFileSize ( byteContent . length ) ;
irFile . setFileType ( fileType ) ;
irFile . setFileName ( "answer" ) ;
irFile . setFileType ( "F" ) ;
if ( "1" . equals ( irFile . getFileType ( ) ) ) {
irFile . setFileByte ( answerInfo . getAnswerByte ( ) ) ;
} else {
irFile . setFileByte ( IoUtil . readBytes ( FileUtil . getInputStream ( answerInfo . getAnswerFile ( ) ) ) ) ;
FileUtil . del ( answerInfo . getAnswerFile ( ) ) ;
}
irFile . setFileSize ( irFile . getFileByte ( ) . length ) ;
irFile . setFileType ( fileType ) ;
irFileService . save ( irFile ) ;
return irFile ;
}
private IrSessionHistory talk2SessionHistory ( String sessionId , String message ,
private IrSessionHistory talk2SessionHistory ( String sessionId , RobotTalkDTO robotTalkDTO ,
MatchQuestionAnswerDTO matchQuestionAnswerDTO ) {
IrSessionHistory sessionHistory = new IrSessionHistory ( ) ;
sessionHistory . setId ( robotTalkDTO . getAskInfo ( ) . getAskId ( ) ) ;
sessionHistory . setSessionId ( sessionId ) ;
sessionHistory . setUserQuestion ( message ) ;
AnswerInfo answerInfo = robotTalkDTO . getAnswerInfo ( ) ;
sessionHistory . setAnswer ( answerInfo . getMessage ( ) ) ;
sessionHistory . setAnswerType ( answerInfo . getContentType ( ) ) ;
sessionHistory . setUserQuestion ( answerInfo . getMessage ( ) ) ;
sessionHistory . setCreateUserId ( UserUtil . getUser ( ) . getId ( ) ) ;
if ( Objects . nonNull ( matchQuestionAnswerDTO ) ) {
sessionHistory . setMatchKnowledgeId ( matchQuestionAnswerDTO . getMatchQuestionCode ( ) ) ;
@ -282,36 +318,53 @@ public class RobotTalkServiceImpl implements RobotTalkService {
} catch ( IOException e ) {
log . error ( "语音转文字失败" , e ) ;
}
// todo: 设置问题语音长度和 历史记录中的语音id
RobotTalkDTO robotTalkDTO = this . textTalk2Robot ( robotTalkReq ) ;
robotTalkDTO . getAskInfo ( ) . setContentType ( 2 ) ;
return robotTalkDTO ;
}
@Override
public List < RobotTalkDTO > talkList ( String sessionId ) {
public List < CommonDialogVo > 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 ( ) ) ;
List < IrSessionHistory > sessionHistoryList = sessionService . lambdaQuery ( ) . eq ( IrSessionHistory : : getSessionId , sessionId ) . orderBy ( true , false , IrSessionHistory : : getCreateTime ) . list ( ) ;
// 获取音频的长度
List < String > voiceIds = sessionHistoryList . stream ( )
. map ( session - > CollUtil . toList ( session . getAnswerVoiceId ( ) , session . getUserQuestionVoiceId ( ) ) )
. flatMap ( Collection : : stream ) . filter ( StrUtil : : isNotEmpty ) . collect ( Collectors . toList ( ) ) ;
Map < String , Integer > voiceLengthMap = CollUtil . isEmpty ( voiceIds ) ? new HashMap < > ( ) :
irVoiceService . listByIds ( voiceIds ) . stream ( ) . collect ( Collectors . toMap ( IrVoice : : getId , IrVoice : : getLength ) ) ;
return sessionHistoryList . stream ( ) . map ( session - > this . sessionHistory2RobotTalkDTO ( session , voiceLengthMap ) )
. filter ( Objects : : nonNull ) . flatMap ( Collection : : stream ) . collect ( Collectors . toList ( ) ) ;
}
private RobotTalkDTO sessionHistory2RobotTalkDTO ( IrSessionHistory sessionHistory ) {
private List< CommonDialogVo > sessionHistory2RobotTalkDTO ( IrSessionHistory sessionHistory , Map < String , Integer > voiceLengthMap ) {
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 ( ) )
CommonDialogVo askDiaLog = CommonDialogVo . builder ( ) . dialogType ( 1 )
. dialogId ( sessionHistory . getId ( ) ) . sessionId ( sessionHistory . getSessionId ( ) )
. contentType ( StrUtil . isEmpty ( sessionHistory . getUserQuestionVoiceId ( ) ) ? 1 : 2 ) //userQuestionVoiceId 为空, 则为1 否则为2
. message ( sessionHistory . getUserQuestion ( ) ) . voiceBaseId ( sessionHistory . getUserQuestionVoiceId ( ) )
. audioLength ( voiceLengthMap . get ( sessionHistory . getUserQuestionVoiceId ( ) ) ) . build ( ) ;
if ( Integer . valueOf ( 6 ) . equals ( sessionHistory . getAnswerType ( ) ) ) {
return CollUtil . newArrayList ( askDiaLog ) ;
}
CommonDialogVo answerDiaLog = CommonDialogVo . builder ( ) . dialogType ( 2 )
. dialogId ( sessionHistory . getId ( ) ) . sessionId ( sessionHistory . getSessionId ( ) )
. contentType ( sessionHistory . getAnswerType ( ) ) . message ( sessionHistory . getAnswer ( ) )
. byteId ( sessionHistory . getAnswerFileId ( ) ) . voiceBaseId ( sessionHistory . getAnswerVoiceId ( ) )
. audioLength ( voiceLengthMap . get ( sessionHistory . getAnswerVoiceId ( ) ) )
. build ( ) ;
return RobotTalkDTO . builder ( ) . sessionId ( sessionHistory . getSessionId ( ) )
. askInfo ( askInfo ) . answerInfo ( answerInfo ) . build ( ) ;
return CollUtil . toList ( askDiaLog , answerDiaLog ) ;
}
@Override
@ -340,12 +393,33 @@ public class RobotTalkServiceImpl implements RobotTalkService {
if ( Objects . isNull ( file ) | | Objects . isNull ( file . getFileByte ( ) ) ) {
return ;
}
IoUtil . write ( response . getOutputStream ( ) , true , Base64 . decode ( file . getFileByte ( ) ) ) ;
if ( "1" . equals ( file . getFileType ( ) ) ) {
IoUtil . write ( response . getOutputStream ( ) , true , Base64 . decode ( file . getFileByte ( ) ) ) ;
}
if ( "2" . equals ( file . getFileType ( ) ) ) {
IoUtil . write ( response . getOutputStream ( ) , true , file . getFileByte ( ) ) ;
}
}
@Override
public List < SuspectInfo > querySuspectInfo ( String sessionId , String name ) {
Assert . notEmpty ( sessionId , "sessionId不能为空" ) ;
//Assert.notEmpty(name, "name不能为空");
IrSessionParam sessionParam = irSessionParamService . lambdaQuery ( ) . eq ( IrSessionParam : : getSessionId , sessionId ) . eq ( IrSessionParam : : getParamName , "ajid" ) . one ( ) ;
Assert . notNull ( sessionParam , "未查询到案件" ) ;
Assert . notEmpty ( sessionParam . getParamValue ( ) , "ajid不能为空" ) ;
return robotDataMapper . querySuspect ( NumberUtil . parseInt ( sessionParam . getParamValue ( ) ) , null , name , null ) ;
}
private String localArchivesFilePath ( ArchivesReqVo archivesReq ) {
String path = StrUtil . join ( File . separator , archivesReq . getCaseId ( ) ,
StrUtil . join ( "-" , archivesReq . getName ( ) , archivesReq . getIdNumber ( ) ) ) ;
StrUtil . join ( "-" , archivesReq . getName ( ) , archivesReq . getIdNumber ( ) ) ,
archivesReq . getDocumentId ( ) ) ;
// 判断文件是否存在
if ( FileUtil . exist ( path ) ) {