draft
This commit is contained in:
parent
23f547ab85
commit
de44da5425
|
|
@ -2,7 +2,7 @@ using System.IO;
|
|||
|
||||
namespace BotSharp.Core.Files.Services
|
||||
{
|
||||
public partial class BotSharpFileService
|
||||
public partial class LocalFileStorageService
|
||||
{
|
||||
public async Task SaveSpeechFileAsync(string conversationId, string fileName, BinaryData data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -86,24 +86,24 @@ public class TwilioVoiceController : TwilioController
|
|||
}
|
||||
|
||||
|
||||
[HttpPost("anonymous/start")]
|
||||
[HttpPost("start")]
|
||||
public TwiMLResult InitiateConversation(VoiceRequest request)
|
||||
{
|
||||
if (request?.CallSid == null) throw new ArgumentNullException(nameof(VoiceRequest.CallSid));
|
||||
string sessionId = $"TwilioVoice_{request.CallSid}";
|
||||
var twilio = _services.GetRequiredService<TwilioService>();
|
||||
var url = $"twiliovoice/anonymous/{sessionId}/send/0";
|
||||
var response = twilio.DummyInstructions("Hello, how may I help you?", url, false);
|
||||
var url = $"twiliovoice/{sessionId}/send/0";
|
||||
var response = twilio.ReturnInstructions("twilio/welcome.mp3", url, false);
|
||||
return TwiML(response);
|
||||
}
|
||||
|
||||
[HttpPost("anonymous/{sessionId}/send/{seqNum}")]
|
||||
[HttpPost("{sessionId}/send/{seqNum}")]
|
||||
public async Task<TwiMLResult> SendCallerMessage([FromRoute] string sessionId, [FromRoute] int seqNum, VoiceRequest request)
|
||||
{
|
||||
var twilio = _services.GetRequiredService<TwilioService>();
|
||||
var messageQueue = _services.GetRequiredService<TwilioMessageQueue>();
|
||||
var sessionManager = _services.GetRequiredService<ITwilioSessionManager>();
|
||||
var url = $"twiliovoice/anonymous/{sessionId}/reply/{seqNum}";
|
||||
var url = $"twiliovoice/{sessionId}/reply/{seqNum}";
|
||||
var messages = await sessionManager.RetrieveStagedCallerMessagesAsync(sessionId, seqNum);
|
||||
if (!string.IsNullOrWhiteSpace(request.SpeechResult))
|
||||
{
|
||||
|
|
@ -121,16 +121,16 @@ public class TwilioVoiceController : TwilioController
|
|||
From = request.From
|
||||
};
|
||||
await messageQueue.EnqueueAsync(callerMessage);
|
||||
response = twilio.DummyInstructions("Please hold on and wait a moment.", url, true);
|
||||
response = twilio.ReturnInstructions("twilio/holdon.mp3", url, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = twilio.HangUp("Thanks for calling. Good bye.");
|
||||
response = twilio.HangUp("twilio/holdon.mp3");
|
||||
}
|
||||
return TwiML(response);
|
||||
}
|
||||
|
||||
[HttpPost("anonymous/{sessionId}/reply/{seqNum}")]
|
||||
[HttpPost("{sessionId}/reply/{seqNum}")]
|
||||
public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string sessionId, [FromRoute] int seqNum, VoiceRequest request)
|
||||
{
|
||||
var nextSeqNum = seqNum + 1;
|
||||
|
|
@ -144,38 +144,28 @@ public class TwilioVoiceController : TwilioController
|
|||
VoiceResponse response;
|
||||
if (string.IsNullOrEmpty(reply))
|
||||
{
|
||||
response = twilio.ReturnInstructions(null, $"twiliovoice/anonymous/{sessionId}/reply/{seqNum}", true);
|
||||
response = twilio.ReturnInstructions(null, $"twiliovoice/{sessionId}/reply/{seqNum}", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var textToSpeechService = CompletionProvider.GetTextToSpeech(_services, "openai", "tts-1");
|
||||
var fileService = _services.GetRequiredService<IBotSharpFileService>();
|
||||
var fileService = _services.GetRequiredService<IFileStorageService>();
|
||||
var data = await textToSpeechService.GenerateSpeechFromTextAsync(reply);
|
||||
var fileName = $"{seqNum}.mp3";
|
||||
await fileService.SaveSpeechFileAsync(sessionId, fileName, data);
|
||||
response = twilio.ReturnInstructions($"twiliovoice/anonymous/speeches/{sessionId}/{fileName}", $"twiliovoice/anonymous/{sessionId}/send/{nextSeqNum}", true);
|
||||
response = twilio.ReturnInstructions($"twiliovoice/speeches/{sessionId}/{fileName}", $"twiliovoice/{sessionId}/send/{nextSeqNum}", true);
|
||||
}
|
||||
return TwiML(response);
|
||||
}
|
||||
|
||||
[HttpGet("anonymous/speeches/{conversationId}/{fileName}")]
|
||||
[HttpGet("speeches/{conversationId}/{fileName}")]
|
||||
public async Task<FileContentResult> RetrieveSpeechFile([FromRoute] string conversationId, [FromRoute] string fileName)
|
||||
{
|
||||
var fileService = _services.GetRequiredService<IBotSharpFileService>();
|
||||
var fileService = _services.GetRequiredService<IFileStorageService>();
|
||||
var data = await fileService.RetrieveSpeechFileAsync(conversationId, fileName);
|
||||
var result = new FileContentResult(data.ToArray(), "application/octet-stream");
|
||||
var result = new FileContentResult(data.ToArray(), "audio/mpeg");
|
||||
result.FileDownloadName = fileName;
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpGet("anonymous/text-to-speech")]
|
||||
public async Task<IActionResult> TextToSpeech([FromQuery] string text)
|
||||
{
|
||||
var textToSpeechService = CompletionProvider.GetTextToSpeech(_services, "openai", "tts-1");
|
||||
var data = await textToSpeechService.GenerateSpeechFromTextAsync(text);
|
||||
var fileService = _services.GetRequiredService<IBotSharpFileService>();
|
||||
await fileService.SaveSpeechFileAsync("123", "sample.mp3", data);
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace BotSharp.Plugin.Twilio.Models
|
|||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"({SessionId}-{SeqNumber}) {Content}";
|
||||
return $"{SessionId}-{SeqNumber}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ namespace BotSharp.Plugin.Twilio.Services
|
|||
|
||||
internal void Stop()
|
||||
{
|
||||
Console.WriteLine($"[{DateTime.UtcNow}] Complete queue");
|
||||
_queue.Writer.TryComplete();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using BotSharp.Abstraction.Routing;
|
||||
using BotSharp.Plugin.Twilio.Models;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
|
||||
|
|
@ -31,12 +30,12 @@ namespace BotSharp.Plugin.Twilio.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Processing {message}.", message);
|
||||
Console.WriteLine($"Start processing {message}.");
|
||||
await ProcessUserMessageAsync(message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Processing {message} failed due to {ex}.", message, ex.Message);
|
||||
Console.WriteLine($"Processing {message} failed due to {ex.Message}.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -57,18 +56,17 @@ namespace BotSharp.Plugin.Twilio.Services
|
|||
using var scope = _serviceProvider.CreateScope();
|
||||
var sp = scope.ServiceProvider;
|
||||
string reply = null;
|
||||
//await Task.Delay(2000);
|
||||
//reply = $"response for sequence number {message.SeqNumber}";
|
||||
var inputMsg = new RoleDialogModel(AgentRole.User, message.Content);
|
||||
var conv = sp.GetRequiredService<IConversationService>();
|
||||
var routing = sp.GetRequiredService<IRoutingService>();
|
||||
var config = sp.GetRequiredService<TwilioSetting>();
|
||||
routing.Context.SetMessageId(message.SessionId, inputMsg.MessageId);
|
||||
conv.SetConversationId(message.SessionId, new List<MessageState>
|
||||
{
|
||||
new MessageState("channel", ConversationChannel.Phone),
|
||||
new MessageState("calling_phone", message.From)
|
||||
});
|
||||
var result = await conv.SendMessage("2cd4b805-7078-4405-87e9-2ec9aadf8a11",
|
||||
var result = await conv.SendMessage(config.AgentId,
|
||||
inputMsg,
|
||||
replyMessage: null,
|
||||
async msg =>
|
||||
|
|
@ -82,7 +80,7 @@ namespace BotSharp.Plugin.Twilio.Services
|
|||
);
|
||||
if (string.IsNullOrWhiteSpace(reply))
|
||||
{
|
||||
reply = "Bye.";
|
||||
reply = "Sorry, something was wrong.";
|
||||
}
|
||||
var sessionManager = sp.GetRequiredService<ITwilioSessionManager>();
|
||||
await sessionManager.SetAssistantReplyAsync(message.SessionId, message.SeqNumber, reply);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using BotSharp.Plugin.Twilio.Settings;
|
||||
using Twilio.Jwt.AccessToken;
|
||||
using Token = Twilio.Jwt.AccessToken.Token;
|
||||
|
||||
|
|
@ -74,6 +73,7 @@ public class TwilioService
|
|||
Gather.InputEnum.Speech
|
||||
},
|
||||
Action = new Uri($"{_settings.CallbackHost}/{callbackPath}"),
|
||||
SpeechTimeout = "3",
|
||||
ActionOnEmptyResult = actionOnEmptyResult
|
||||
};
|
||||
if (!string.IsNullOrEmpty(speechPath))
|
||||
|
|
@ -84,32 +84,12 @@ public class TwilioService
|
|||
return response;
|
||||
}
|
||||
|
||||
public VoiceResponse DummyInstructions(string message, string callbackPath, bool actionOnEmptyResult)
|
||||
public VoiceResponse HangUp(string speechPath)
|
||||
{
|
||||
var response = new VoiceResponse();
|
||||
var gather = new Gather()
|
||||
if (!string.IsNullOrEmpty(speechPath))
|
||||
{
|
||||
Input = new List<Gather.InputEnum>()
|
||||
{
|
||||
Gather.InputEnum.Speech
|
||||
},
|
||||
Action = new Uri($"{_settings.CallbackHost}/{callbackPath}"),
|
||||
ActionOnEmptyResult = actionOnEmptyResult
|
||||
};
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
gather.Say(message);
|
||||
}
|
||||
response.Append(gather);
|
||||
return response;
|
||||
}
|
||||
|
||||
public VoiceResponse HangUp(string message)
|
||||
{
|
||||
var response = new VoiceResponse();
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
response.Say(message);
|
||||
response.Play(new Uri($"{_settings.CallbackHost}/{speechPath}"));
|
||||
}
|
||||
response.Hangup();
|
||||
return response;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public class TwilioPlugin : IBotSharpPlugin
|
|||
});
|
||||
|
||||
services.AddScoped<TwilioService>();
|
||||
var conn = ConnectionMultiplexer.Connect("10.2.3.227");
|
||||
var conn = ConnectionMultiplexer.Connect(config["Twilio:RedisConnectionString"]);
|
||||
var sessionManager = new TwilioSessionManager(conn);
|
||||
services.AddSingleton<ITwilioSessionManager>(sessionManager);
|
||||
services.AddSingleton<TwilioMessageQueue>();
|
||||
|
|
|
|||
Loading…
Reference in a new issue