|
@@ -117,7 +117,7 @@ public class RobotChat extends RobotBase {
|
|
|
// In the outbound call scenario, solve the problem that the first few words of the first sentence
|
|
// In the outbound call scenario, solve the problem that the first few words of the first sentence
|
|
|
// cannot be heard clearly, because it takes about 2 seconds for the customer to transfer from
|
|
// cannot be heard clearly, because it takes about 2 seconds for the customer to transfer from
|
|
|
// the receiver to the headphones after answering the call.
|
|
// the receiver to the headphones after answering the call.
|
|
|
- ThreadUtil.sleep(1500);
|
|
|
|
|
|
|
+ ThreadUtil.sleep(200);
|
|
|
if (isHangup) {
|
|
if (isHangup) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -135,7 +135,7 @@ public class RobotChat extends RobotBase {
|
|
|
HangupCause.TTS_ACCOUNT_INFO_INCORRECT,
|
|
HangupCause.TTS_ACCOUNT_INFO_INCORRECT,
|
|
|
"error msg:" + errMsg
|
|
"error msg:" + errMsg
|
|
|
);
|
|
);
|
|
|
- hangupAndCloseConn();
|
|
|
|
|
|
|
+ hangupAndCloseConn("AliyunTTSWebApi-getToken-error");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -224,7 +224,7 @@ public class RobotChat extends RobotBase {
|
|
|
if(recvHangupSignal){
|
|
if(recvHangupSignal){
|
|
|
logger.info("{} The hang signal was received in the previous interaction process, and the call is about to hang up.",
|
|
logger.info("{} The hang signal was received in the previous interaction process, and the call is about to hang up.",
|
|
|
getTraceId());
|
|
getTraceId());
|
|
|
- hangupAndCloseConn();
|
|
|
|
|
|
|
+ hangupAndCloseConn("recvHangupSignal");
|
|
|
}
|
|
}
|
|
|
}else if (EventNames.DTMF.equalsIgnoreCase(eventName)) {
|
|
}else if (EventNames.DTMF.equalsIgnoreCase(eventName)) {
|
|
|
// get the dtmf key to check if its value is the same as
|
|
// get the dtmf key to check if its value is the same as
|
|
@@ -234,8 +234,12 @@ public class RobotChat extends RobotBase {
|
|
|
String transferManualDigit = chatRobot.getAccount().transferManualDigit;
|
|
String transferManualDigit = chatRobot.getAccount().transferManualDigit;
|
|
|
if(transferManualDigit.equalsIgnoreCase(digit)){
|
|
if(transferManualDigit.equalsIgnoreCase(digit)){
|
|
|
logger.info("{} DTMF digit equals transferManualDigit.", getTraceId());
|
|
logger.info("{} DTMF digit equals transferManualDigit.", getTraceId());
|
|
|
- transferToAgent = true;
|
|
|
|
|
|
|
+
|
|
|
if (recvPlayBackEndEvent || getAllowInterrupt()) {
|
|
if (recvPlayBackEndEvent || getAllowInterrupt()) {
|
|
|
|
|
+
|
|
|
|
|
+ if(!setTransferState()){
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
logger.info("{} The digit-key during call have successfully activated the condition " +
|
|
logger.info("{} The digit-key during call have successfully activated the condition " +
|
|
|
"for transferring to a human operator. recvPlayBackEndEvent={}, getAllowInterrupt()={} ",
|
|
"for transferring to a human operator. recvPlayBackEndEvent={}, getAllowInterrupt()={} ",
|
|
|
getTraceId(), recvPlayBackEndEvent, getAllowInterrupt()
|
|
getTraceId(), recvPlayBackEndEvent, getAllowInterrupt()
|
|
@@ -244,6 +248,22 @@ public class RobotChat extends RobotBase {
|
|
|
interruptRobotSpeech();
|
|
interruptRobotSpeech();
|
|
|
releasePlayBackFinishedSignal();
|
|
releasePlayBackFinishedSignal();
|
|
|
ThreadUtil.sleep(100);
|
|
ThreadUtil.sleep(100);
|
|
|
|
|
+ // wait for tts closed
|
|
|
|
|
+ int step = 50;
|
|
|
|
|
+ int maxWaitMills = 2000;
|
|
|
|
|
+ int counter = 0;
|
|
|
|
|
+ logger.info("{} wait for tts channel closed.", getTraceId());
|
|
|
|
|
+ while (!ttsChannelClosed && !isHangup && counter <= maxWaitMills) {
|
|
|
|
|
+ ThreadUtil.sleep(step);
|
|
|
|
|
+ counter += step;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!ttsChannelClosed){
|
|
|
|
|
+ ttsChannelClosed = true;
|
|
|
|
|
+ chatRobot.setTtsChannelState(TtsChannelState.CLOSED);
|
|
|
|
|
+ logger.warn("{} We haven't received the event of the TTS channel being closed within two seconds, we consider it to have been closed. .", getTraceId());
|
|
|
|
|
+ }else{
|
|
|
|
|
+ logger.info("{} tts channel is closed.", getTraceId());
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
releaseSignal();
|
|
releaseSignal();
|
|
@@ -303,6 +323,12 @@ public class RobotChat extends RobotBase {
|
|
|
logger.info("{} TtsChannelClosed = true.", getTraceId());
|
|
logger.info("{} TtsChannelClosed = true.", getTraceId());
|
|
|
ttsChannelClosed = true;
|
|
ttsChannelClosed = true;
|
|
|
}
|
|
}
|
|
|
|
|
+ if("Speech-Open".equalsIgnoreCase(event)){
|
|
|
|
|
+ chatRobot.setTtsChannelState(TtsChannelState.OPENED);
|
|
|
|
|
+ chatRobot.flushTtsRequestQueue();
|
|
|
|
|
+ long timeSpent = System.currentTimeMillis() - playbackStartTime;
|
|
|
|
|
+ logger.info("{} Speech-Open event, time cost = {} ms. ", getTraceId(), timeSpent);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if ("NetworkError".equalsIgnoreCase(event)) {
|
|
if ("NetworkError".equalsIgnoreCase(event)) {
|
|
|
CommonUtils.setHangupCauseDetail(
|
|
CommonUtils.setHangupCauseDetail(
|
|
@@ -310,7 +336,8 @@ public class RobotChat extends RobotBase {
|
|
|
HangupCause.TTS_SERVER_CONNECTED_FAILED,
|
|
HangupCause.TTS_SERVER_CONNECTED_FAILED,
|
|
|
headers.get("Error-Details")
|
|
headers.get("Error-Details")
|
|
|
);
|
|
);
|
|
|
- hangupAndCloseConn();
|
|
|
|
|
|
|
+ logger.info("{} recv NetworkError event, hangup call session.", getTraceId());
|
|
|
|
|
+ hangupAndCloseConn("Asr-TTs-NetworkError");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
else if ("CUSTOM".equalsIgnoreCase(eventName) && (
|
|
else if ("CUSTOM".equalsIgnoreCase(eventName) && (
|
|
@@ -328,15 +355,15 @@ public class RobotChat extends RobotBase {
|
|
|
HangupCause.ASR_SERVER_CONNECTED_FAILED,
|
|
HangupCause.ASR_SERVER_CONNECTED_FAILED,
|
|
|
asrResponse
|
|
asrResponse
|
|
|
);
|
|
);
|
|
|
- hangupAndCloseConn();
|
|
|
|
|
|
|
+ hangupAndCloseConn("Asr-Tts-NetworkError");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
lastTalkTime = System.currentTimeMillis();
|
|
lastTalkTime = System.currentTimeMillis();
|
|
|
|
|
|
|
|
- if (isHangup || interactiveParam.checkInHangupState()) {
|
|
|
|
|
- logger.info("{} Session is going to be hangup, drop asr result: {}", getTraceId(), asrResponse);
|
|
|
|
|
|
|
+ if (isHangup || interactiveParam.checkInHangupState() || transferToAgent) {
|
|
|
|
|
+ logger.info("{} Session is going to be hangup or is already being transferred to human operator, drop asr result: {}", getTraceId(), asrResponse);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -407,6 +434,17 @@ public class RobotChat extends RobotBase {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private boolean setTransferState() {
|
|
|
|
|
+ synchronized (uuid.intern()) {
|
|
|
|
|
+ if (transferToAgent) {
|
|
|
|
|
+ logger.info("{} transferring to a human operator is already being handled. skip...", getTraceId());
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ transferToAgent = true;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
protected void interruptRobotSpeech(){
|
|
protected void interruptRobotSpeech(){
|
|
|
logger.info("{} send uuid_break command to FreeSWITCH.", uuid);
|
|
logger.info("{} send uuid_break command to FreeSWITCH.", uuid);
|
|
|
EslConnectionUtil.sendSyncApiCommand("uuid_break", uuid + " all");
|
|
EslConnectionUtil.sendSyncApiCommand("uuid_break", uuid + " all");
|
|
@@ -542,6 +580,9 @@ public class RobotChat extends RobotBase {
|
|
|
* interactWithRobot
|
|
* interactWithRobot
|
|
|
**/
|
|
**/
|
|
|
private void interactWithRobot() {
|
|
private void interactWithRobot() {
|
|
|
|
|
+ if (checkCallSession()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
interactiveParam.setAllowInterrupt(0);
|
|
interactiveParam.setAllowInterrupt(0);
|
|
|
recvPlayBackEndEvent = false;
|
|
recvPlayBackEndEvent = false;
|
|
|
firstSpeak = false;
|
|
firstSpeak = false;
|
|
@@ -590,6 +631,9 @@ public class RobotChat extends RobotBase {
|
|
|
logger.error("{} llm api error, retry to send question to chatRobot: {}", getTraceId(), question);
|
|
logger.error("{} llm api error, retry to send question to chatRobot: {}", getTraceId(), question);
|
|
|
aiphoneRes = chatRobot.talkWithAiAgent(question, kbQueryExecuted);
|
|
aiphoneRes = chatRobot.talkWithAiAgent(question, kbQueryExecuted);
|
|
|
Llm_max_try_counter.incrementAndGet();
|
|
Llm_max_try_counter.incrementAndGet();
|
|
|
|
|
+ if (checkCallSession()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
Llm_max_try_counter.set(0);
|
|
Llm_max_try_counter.set(0);
|
|
|
kbQueryExecuted = false;
|
|
kbQueryExecuted = false;
|
|
@@ -605,7 +649,7 @@ public class RobotChat extends RobotBase {
|
|
|
HangupCause.LLM_API_SERVER_ERROR,
|
|
HangupCause.LLM_API_SERVER_ERROR,
|
|
|
String.format("The large model failed to access successfully despite more than %d connection attempts.", LLM_MAX_TRY)
|
|
String.format("The large model failed to access successfully despite more than %d connection attempts.", LLM_MAX_TRY)
|
|
|
);
|
|
);
|
|
|
- hangupAndCloseConn();
|
|
|
|
|
|
|
+ hangupAndCloseConn("reach-llm-max-try-error");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -652,7 +696,14 @@ public class RobotChat extends RobotBase {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (checkCallSession()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (aiphoneRes.getTransferToAgent() == 1) {
|
|
if (aiphoneRes.getTransferToAgent() == 1) {
|
|
|
|
|
+ if(!setTransferState()){
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
doTransferToManualAgent(body);
|
|
doTransferToManualAgent(body);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -662,11 +713,15 @@ public class RobotChat extends RobotBase {
|
|
|
chatRobot.sendTtsRequest(chatRobot.getAccount().hangupTips);
|
|
chatRobot.sendTtsRequest(chatRobot.getAccount().hangupTips);
|
|
|
}
|
|
}
|
|
|
chatRobot.closeTts();
|
|
chatRobot.closeTts();
|
|
|
- acquire(9000);
|
|
|
|
|
|
|
+ waitForPlayBackFinished(11000);
|
|
|
|
|
+ long startTimeTick = System.currentTimeMillis();
|
|
|
while (!ttsChannelClosed && !isHangup) {
|
|
while (!ttsChannelClosed && !isHangup) {
|
|
|
ThreadUtil.sleep(1000);
|
|
ThreadUtil.sleep(1000);
|
|
|
|
|
+ if(System.currentTimeMillis() - startTimeTick > 11000){
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- hangupAndCloseConn();
|
|
|
|
|
|
|
+ hangupAndCloseConn("system-hangup");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -680,7 +735,7 @@ public class RobotChat extends RobotBase {
|
|
|
HangupCause.SYSTEM_INTERNAL_ERROR,
|
|
HangupCause.SYSTEM_INTERNAL_ERROR,
|
|
|
String.format("server error: %s", e.toString())
|
|
String.format("server error: %s", e.toString())
|
|
|
);
|
|
);
|
|
|
- hangupAndCloseConn();
|
|
|
|
|
|
|
+ hangupAndCloseConn(HangupCause.SYSTEM_INTERNAL_ERROR.getCode());
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -711,17 +766,20 @@ public class RobotChat extends RobotBase {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private void doTransferToManualAgent(String audioTipsText){
|
|
|
|
|
- transferToAgent = true;
|
|
|
|
|
|
|
+ private synchronized void doTransferToManualAgent(String audioTipsText){
|
|
|
|
|
+ if(transferToAgentExecuted){
|
|
|
|
|
+ logger.warn("{} The call transfer to a human agent has already been processed.", getTraceId());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ transferToAgentExecuted = true;
|
|
|
callDetail.setChatContent(chatRobot.getDialogues());
|
|
callDetail.setChatContent(chatRobot.getDialogues());
|
|
|
-
|
|
|
|
|
// Replace the prompt words for manual transfer in the text with blank spaces.
|
|
// Replace the prompt words for manual transfer in the text with blank spaces.
|
|
|
String transferToTel = "";
|
|
String transferToTel = "";
|
|
|
if(!StringUtils.isEmpty(audioTipsText) && audioTipsText.contains(LlmToolRequest.TRANSFER_TO_TEL)){
|
|
if(!StringUtils.isEmpty(audioTipsText) && audioTipsText.contains(LlmToolRequest.TRANSFER_TO_TEL)){
|
|
|
if(!TransferToAgent.TRANSFER_TO_GATEWAY.equalsIgnoreCase(chatRobot.getAccount().aiTransferType)){
|
|
if(!TransferToAgent.TRANSFER_TO_GATEWAY.equalsIgnoreCase(chatRobot.getAccount().aiTransferType)){
|
|
|
logger.error("{} instruction `{}` is only applicable when an external gateway is used to transfer to a manual agent.",
|
|
logger.error("{} instruction `{}` is only applicable when an external gateway is used to transfer to a manual agent.",
|
|
|
uuid, LlmToolRequest.TRANSFER_TO_TEL);
|
|
uuid, LlmToolRequest.TRANSFER_TO_TEL);
|
|
|
- hangupAndCloseConn();
|
|
|
|
|
|
|
+ hangupAndCloseConn("llm-instruction-error");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
List<String> matches = RegExp.GetMatchFromStringByRegExp(audioTipsText, LlmToolRequest.TRANSFER_TO_TEL_REGEXP);
|
|
List<String> matches = RegExp.GetMatchFromStringByRegExp(audioTipsText, LlmToolRequest.TRANSFER_TO_TEL_REGEXP);
|
|
@@ -744,7 +802,7 @@ public class RobotChat extends RobotBase {
|
|
|
logger.info("{} Try to play tts transferToAgentTips {}", getTraceId(), tips);
|
|
logger.info("{} Try to play tts transferToAgentTips {}", getTraceId(), tips);
|
|
|
chatRobot.sendTtsRequest(tips);
|
|
chatRobot.sendTtsRequest(tips);
|
|
|
chatRobot.closeTts();
|
|
chatRobot.closeTts();
|
|
|
- waitForPlayBackFinished();
|
|
|
|
|
|
|
+ waitForPlayBackFinished(6000);
|
|
|
// wait for tips playback finished
|
|
// wait for tips playback finished
|
|
|
}
|
|
}
|
|
|
|
|
|