package com.supervision.service.impl; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.supervision.exception.BusinessException; import com.supervision.util.AsrUtil; import com.supervision.util.TtsUtil; import com.supervision.util.RasaUtil; import com.supervision.service.AskService; import com.supervision.util.UserUtil; import com.supervision.websocket.cache.WebSocketUserCache; import com.supervision.websocket.dto.ActionDTO; import com.supervision.websocket.dto.SocketMessageDTO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import java.io.IOException; import java.util.List; @Slf4j @Service @RequiredArgsConstructor public class AskServiceImpl implements AskService { @Override public void handlerMessageBySocket(SocketMessageDTO socketMessageDTO) throws IOException { // 首先获取消息的类型 String text; if (0 == socketMessageDTO.getMessageType()) { // 如果是语音消息 // 调用百度接口,语音转文字 text = AsrUtil.asrTransformByBytes(socketMessageDTO.getVoiceMessage()); } else { text = socketMessageDTO.getTextMessage(); } if (StrUtil.isBlank(text)) { throw new BusinessException("语音消息不能为空"); } // 进行rasa对话 List rasaResultList = RasaUtil.talkRasa(text, socketMessageDTO.getSocketId()); log.info("问题:{},rasa回复:{}", text, JSONUtil.toJsonStr(rasaResultList)); WebSocketSession session = WebSocketUserCache.getSession(socketMessageDTO.getSocketId()); for (String rasaResult : rasaResultList) { if (StrUtil.isNotBlank(rasaResult)) { // 这里校验,rasa回复的结果是不是action // 这里设置的模板,对于action的动作全部是用---进行标记,详情看生成rasa的yml的代码:RasaServiceImpl.generateDomain // ---ancillary---xxx // ---tool---xxx if (rasaResult.startsWith("---")) { // ["","ancillary","xxx"] List actionList = StrUtil.split(rasaResult, "---"); if (actionList.size() > 2) { ActionDTO actionDTO = new ActionDTO(); actionDTO.setActionType(actionList.get(1)); actionDTO.setActionId(actionList.get(2)); // 在这里给socket回复,设置为动作 SocketMessageDTO res = new SocketMessageDTO(); res.setSocketId(socketMessageDTO.getSocketId()); res.setUserId(UserUtil.getUser().getId()); res.setAction(actionDTO); res.setType(2); session.sendMessage(new TextMessage(JSONUtil.toJsonStr(res))); return; } } else { // 走到这里,说明是文字,这个时候文字转语音 String replyVoiceResVO = TtsUtil.ttsTransform(rasaResult); // 在这里给socket回复 SocketMessageDTO res = new SocketMessageDTO(); res.setSocketId(socketMessageDTO.getSocketId()); res.setUserId(UserUtil.getUser().getId()); res.setTextMessage(rasaResult); res.setVoiceMessage(replyVoiceResVO); res.setType(1); session.sendMessage(new TextMessage(JSONUtil.toJsonStr(res))); return; } } } // 兜底,如果走到了这里,就直接返回未识别 SocketMessageDTO res = new SocketMessageDTO(); res.setSocketId(socketMessageDTO.getSocketId()); res.setUserId(UserUtil.getUser().getId()); res.setTextMessage("医生,我没有听懂您说的什么意思"); res.setType(1); session.sendMessage(new TextMessage(JSONUtil.toJsonStr(res))); log.info("兜底话术,需要检查上面是不是出什么问题了"); } @Override public String receiveVoiceFile(MultipartFile file) throws IOException { // 获取音频对应的文字 String askQuestion = AsrUtil.asrTransformByBytes(file.getBytes()); // 调用rasa获取文字内容 throw new BusinessException("暂未实现"); } @Override public String replyVoice() { String text = "测试:这是文字转语音的测试,测试是否OK"; return TtsUtil.ttsTransform(text); } @Override public List conversation(String question, String sessionId) { return RasaUtil.talkRasa(question, sessionId); } }