BotSharp/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioMessageQueueService.cs

135 lines
5.2 KiB
C#
Raw Normal View History

2024-08-23 20:16:55 +00:00
using BotSharp.Abstraction.Files;
2024-08-08 19:54:32 +00:00
using BotSharp.Abstraction.Routing;
2024-08-23 20:16:55 +00:00
using BotSharp.Core.Infrastructures;
2024-08-08 19:54:32 +00:00
using BotSharp.Plugin.Twilio.Models;
using Microsoft.Extensions.Hosting;
using System.Threading;
using Task = System.Threading.Tasks.Task;
namespace BotSharp.Plugin.Twilio.Services
{
public class TwilioMessageQueueService : BackgroundService
{
private readonly TwilioMessageQueue _queue;
private readonly IServiceProvider _serviceProvider;
private readonly SemaphoreSlim _throttler;
public TwilioMessageQueueService(
TwilioMessageQueue queue,
IServiceProvider serviceProvider)
{
_queue = queue;
_serviceProvider = serviceProvider;
_throttler = new SemaphoreSlim(4, 4);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await foreach (var message in _queue.Reader.ReadAllAsync(stoppingToken))
{
await _throttler.WaitAsync(stoppingToken);
_ = Task.Run(async () =>
{
try
{
2024-08-09 03:28:39 +00:00
Console.WriteLine($"Start processing {message}.");
2024-08-08 19:54:32 +00:00
await ProcessUserMessageAsync(message);
}
catch (Exception ex)
{
2024-08-09 03:28:39 +00:00
Console.WriteLine($"Processing {message} failed due to {ex.Message}.");
2024-08-08 19:54:32 +00:00
}
finally
{
_throttler.Release();
}
});
}
}
public override async Task StopAsync(CancellationToken cancellationToken)
{
_queue.Stop();
await base.StopAsync(cancellationToken);
}
private async Task ProcessUserMessageAsync(CallerMessage message)
{
using var scope = _serviceProvider.CreateScope();
var sp = scope.ServiceProvider;
2024-08-28 20:34:41 +00:00
2024-08-14 21:44:47 +00:00
AssistantMessage reply = null;
2024-08-08 19:54:32 +00:00
var inputMsg = new RoleDialogModel(AgentRole.User, message.Content);
var conv = sp.GetRequiredService<IConversationService>();
var routing = sp.GetRequiredService<IRoutingService>();
2024-08-09 03:28:39 +00:00
var config = sp.GetRequiredService<TwilioSetting>();
2024-08-28 20:34:41 +00:00
2024-08-14 21:44:47 +00:00
routing.Context.SetMessageId(message.ConversationId, inputMsg.MessageId);
var states = new List<MessageState>
2024-08-08 19:54:32 +00:00
{
new MessageState("channel", ConversationChannel.Phone),
new MessageState("calling_phone", message.From)
2024-08-14 21:44:47 +00:00
};
2024-08-28 20:34:41 +00:00
2024-08-14 21:44:47 +00:00
foreach (var kvp in message.States)
{
states.Add(new MessageState(kvp.Key, kvp.Value));
}
conv.SetConversationId(message.ConversationId, states);
2024-08-28 20:34:41 +00:00
2024-08-14 21:44:47 +00:00
var sessionManager = sp.GetRequiredService<ITwilioSessionManager>();
2024-08-09 03:28:39 +00:00
var result = await conv.SendMessage(config.AgentId,
2024-08-08 19:54:32 +00:00
inputMsg,
replyMessage: null,
async msg =>
{
2024-08-14 21:44:47 +00:00
reply = new AssistantMessage()
{
2024-08-29 16:49:34 +00:00
ConversationEnd = msg.Instruction?.ConversationEnd ?? false,
2024-09-06 15:14:10 +00:00
HumanIntervationNeeded = string.Equals("human_intervention_needed", msg.FunctionName),
2024-08-22 15:56:10 +00:00
Content = msg.Content,
MessageId = msg.MessageId
2024-08-14 21:44:47 +00:00
};
},
async msg =>
{
if (!string.IsNullOrEmpty(msg.Indication))
{
await sessionManager.SetReplyIndicationAsync(message.ConversationId, message.SeqNumber, msg.Indication);
}
2024-08-08 19:54:32 +00:00
},
2024-08-28 20:34:41 +00:00
async functionExecuted => { }
2024-08-08 19:54:32 +00:00
);
2024-08-28 20:34:41 +00:00
2024-08-28 16:08:12 +00:00
var completion = CompletionProvider.GetAudioCompletion(sp, "openai", "tts-1");
var fileStorage = sp.GetRequiredService<IFileStorageService>();
2024-08-28 18:43:37 +00:00
var data = await completion.GenerateAudioFromTextAsync(reply.Content);
2024-08-23 20:16:55 +00:00
var fileName = $"reply_{reply.MessageId}.mp3";
2024-08-28 20:34:41 +00:00
fileStorage.SaveSpeechFile(message.ConversationId, fileName, data);
2024-08-23 20:16:55 +00:00
reply.SpeechFileName = fileName;
2024-09-09 20:27:09 +00:00
var phrases = reply.Content.Split(',', StringSplitOptions.RemoveEmptyEntries);
int capcity = 100;
var hints = new List<string>(capcity);
for (int i = phrases.Length - 1; i >= 0; i--)
{
var words = phrases[i].Split(' ', StringSplitOptions.RemoveEmptyEntries);
for (int j = words.Length - 1; j >= 0; j--)
{
hints.Add(words[j]);
if (hints.Count >= capcity)
{
break;
}
}
if (hints.Count >= capcity)
{
break;
}
}
2024-09-09 21:43:59 +00:00
reply.Hints = string.Join(", ", hints.Select(x => x.ToLower()).Distinct().Reverse());
2024-08-23 20:16:55 +00:00
reply.Content = null;
2024-08-14 21:44:47 +00:00
await sessionManager.SetAssistantReplyAsync(message.ConversationId, message.SeqNumber, reply);
2024-08-08 19:54:32 +00:00
}
}
}