Merge pull request #611 from wcao-lessen/feature/twilio
improve the workflow
This commit is contained in:
commit
a37a80fee9
|
|
@ -36,13 +36,13 @@ public class TwilioVoiceController : TwilioController
|
|||
string conversationId = $"TwilioVoice_{request.CallSid}";
|
||||
var twilio = _services.GetRequiredService<TwilioService>();
|
||||
var url = $"twilio/voice/{conversationId}/receive/0?states={states}";
|
||||
var response = twilio.ReturnInstructions(new List<string> { "twilio/welcome.mp3" }, url, true);
|
||||
var response = twilio.ReturnNoninterruptedInstructions(new List<string> { "twilio/welcome.mp3" }, url, true);
|
||||
return TwiML(response);
|
||||
}
|
||||
|
||||
[ValidateRequest]
|
||||
[HttpPost("twilio/voice/{conversationId}/receive/{seqNum}")]
|
||||
public async Task<TwiMLResult> ReceiveCallerMessage([FromRoute] string conversationId, [FromRoute] int seqNum, [FromQuery] string states, VoiceRequest request)
|
||||
public async Task<TwiMLResult> ReceiveCallerMessage([FromRoute] string conversationId, [FromRoute] int seqNum, [FromQuery] string states, [FromQuery] int attempts, VoiceRequest request)
|
||||
{
|
||||
var twilio = _services.GetRequiredService<TwilioService>();
|
||||
var messageQueue = _services.GetRequiredService<TwilioMessageQueue>();
|
||||
|
|
@ -81,7 +81,21 @@ public class TwilioVoiceController : TwilioController
|
|||
}
|
||||
else
|
||||
{
|
||||
response = twilio.ReturnInstructions(null, $"twilio/voice/{conversationId}/receive/{seqNum}?states={states}", true);
|
||||
if (attempts >= 3)
|
||||
{
|
||||
var speechPaths = new List<string>();
|
||||
if (seqNum == 0)
|
||||
{
|
||||
speechPaths.Add("twilio/welcome.mp3");
|
||||
}
|
||||
else
|
||||
{
|
||||
var lastRepy = await sessionManager.GetAssistantReplyAsync(conversationId, seqNum - 1);
|
||||
speechPaths.Add($"twilio/voice/speeches/{conversationId}/{lastRepy.SpeechFileName}");
|
||||
}
|
||||
response = twilio.ReturnInstructions(speechPaths, $"twilio/voice/{conversationId}/receive/{seqNum}?states={states}", true);
|
||||
}
|
||||
response = twilio.ReturnInstructions(null, $"twilio/voice/{conversationId}/receive/{seqNum}?states={states}&attempts={++attempts}", true);
|
||||
}
|
||||
|
||||
return TwiML(response);
|
||||
|
|
@ -90,7 +104,7 @@ public class TwilioVoiceController : TwilioController
|
|||
[ValidateRequest]
|
||||
[HttpPost("twilio/voice/{conversationId}/reply/{seqNum}")]
|
||||
public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversationId, [FromRoute] int seqNum,
|
||||
[FromQuery] string states, [FromQuery] string play, VoiceRequest request)
|
||||
[FromQuery] string states, VoiceRequest request)
|
||||
{
|
||||
var nextSeqNum = seqNum + 1;
|
||||
var sessionManager = _services.GetRequiredService<ITwilioSessionManager>();
|
||||
|
|
@ -107,6 +121,7 @@ public class TwilioVoiceController : TwilioController
|
|||
if (indication != null)
|
||||
{
|
||||
var speechPaths = new List<string>();
|
||||
int segIndex = 0;
|
||||
foreach (var text in indication.Split('|'))
|
||||
{
|
||||
var seg = text.Trim();
|
||||
|
|
@ -119,12 +134,14 @@ public class TwilioVoiceController : TwilioController
|
|||
var textToSpeechService = CompletionProvider.GetTextToSpeech(_services, "openai", "tts-1");
|
||||
var fileService = _services.GetRequiredService<IFileStorageService>();
|
||||
var data = await textToSpeechService.GenerateSpeechFromTextAsync(seg);
|
||||
var fileName = $"indication_{seqNum}.mp3";
|
||||
var fileName = $"indication_{seqNum}_{segIndex}.mp3";
|
||||
await fileService.SaveSpeechFileAsync(conversationId, fileName, data);
|
||||
speechPaths.Add($"twilio/voice/speeches/{conversationId}/{fileName}");
|
||||
segIndex++;
|
||||
}
|
||||
}
|
||||
response = twilio.ReturnInstructions(speechPaths, $"twilio/voice/{conversationId}/reply/{seqNum}?states={states}", true);
|
||||
await sessionManager.RemoveReplyIndicationAsync(conversationId, seqNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,5 +11,6 @@ namespace BotSharp.Plugin.Twilio.Services
|
|||
Task<List<string>> RetrieveStagedCallerMessagesAsync(string conversationId, int seqNum);
|
||||
Task SetReplyIndicationAsync(string conversationId, int seqNum, string indication);
|
||||
Task<string> GetReplyIndicationAsync(string conversationId, int seqNum);
|
||||
Task RemoveReplyIndicationAsync(string conversationId, int seqNum);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ public class TwilioService
|
|||
},
|
||||
Action = new Uri($"{_settings.CallbackHost}/{callbackPath}"),
|
||||
SpeechModel = Gather.SpeechModelEnum.PhoneCall,
|
||||
SpeechTimeout = timeout > 0 ? timeout.ToString() : "3",
|
||||
Timeout = timeout > 0 ? timeout : 3,
|
||||
SpeechTimeout = timeout > 0 ? timeout.ToString() : "2",
|
||||
Timeout = timeout > 0 ? timeout : 2,
|
||||
ActionOnEmptyResult = actionOnEmptyResult
|
||||
};
|
||||
if (speechPaths != null && speechPaths.Any())
|
||||
|
|
@ -91,6 +91,33 @@ public class TwilioService
|
|||
return response;
|
||||
}
|
||||
|
||||
public VoiceResponse ReturnNoninterruptedInstructions(List<string> speechPaths, string callbackPath, bool actionOnEmptyResult, int timeout = 2)
|
||||
{
|
||||
var response = new VoiceResponse();
|
||||
if (speechPaths != null && speechPaths.Any())
|
||||
{
|
||||
foreach (var speechPath in speechPaths)
|
||||
{
|
||||
response.Play(new Uri($"{_settings.CallbackHost}/{speechPath}"));
|
||||
}
|
||||
}
|
||||
var gather = new Gather()
|
||||
{
|
||||
Input = new List<Gather.InputEnum>()
|
||||
{
|
||||
Gather.InputEnum.Speech,
|
||||
Gather.InputEnum.Dtmf
|
||||
},
|
||||
Action = new Uri($"{_settings.CallbackHost}/{callbackPath}"),
|
||||
SpeechModel = Gather.SpeechModelEnum.PhoneCall,
|
||||
SpeechTimeout = timeout > 0 ? timeout.ToString() : "2",
|
||||
Timeout = timeout > 0 ? timeout : 2,
|
||||
ActionOnEmptyResult = actionOnEmptyResult
|
||||
};
|
||||
response.Append(gather);
|
||||
return response;
|
||||
}
|
||||
|
||||
public VoiceResponse HangUp(string speechPath)
|
||||
{
|
||||
var response = new VoiceResponse();
|
||||
|
|
|
|||
|
|
@ -59,5 +59,12 @@ namespace BotSharp.Plugin.Twilio.Services
|
|||
var key = $"{conversationId}:Indication:{seqNum}";
|
||||
return await db.StringGetAsync(key);
|
||||
}
|
||||
|
||||
public async Task RemoveReplyIndicationAsync(string conversationId, int seqNum)
|
||||
{
|
||||
var db = _redis.GetDatabase();
|
||||
var key = $"{conversationId}:Indication:{seqNum}";
|
||||
await db.KeyDeleteAsync(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue