From 9d570311d10538b721cd7eb5b23636488a18b075 Mon Sep 17 00:00:00 2001 From: Haiping Chen <101423@smsassist.com> Date: Wed, 26 Feb 2025 22:40:50 -0600 Subject: [PATCH] realtime route to agent --- .../MLTasks/IRealTimeCompletion.cs | 2 +- .../BotSharp.Core/Realtime/RealtimeHub.cs | 23 ++++++++++++++----- .../Realtime/RealTimeCompletionProvider.cs | 4 ++-- .../Controllers/TwilioStreamController.cs | 18 +++++++-------- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/MLTasks/IRealTimeCompletion.cs b/src/Infrastructure/BotSharp.Abstraction/MLTasks/IRealTimeCompletion.cs index 8e1d11d5..bd958805 100644 --- a/src/Infrastructure/BotSharp.Abstraction/MLTasks/IRealTimeCompletion.cs +++ b/src/Infrastructure/BotSharp.Abstraction/MLTasks/IRealTimeCompletion.cs @@ -24,7 +24,7 @@ public interface IRealTimeCompletion Task Disconnect(); Task CreateSession(Agent agent, List conversations); - Task UpdateInitialSession(RealtimeHubConnection conn); + Task UpdateSession(RealtimeHubConnection conn); Task InsertConversationItem(RoleDialogModel message); Task TriggerModelInference(string? instructions = null); Task> OnResponsedDone(RealtimeHubConnection conn, string response); diff --git a/src/Infrastructure/BotSharp.Core/Realtime/RealtimeHub.cs b/src/Infrastructure/BotSharp.Core/Realtime/RealtimeHub.cs index 51c1bd33..c33f28a2 100644 --- a/src/Infrastructure/BotSharp.Core/Realtime/RealtimeHub.cs +++ b/src/Infrastructure/BotSharp.Core/Realtime/RealtimeHub.cs @@ -1,9 +1,7 @@ using BotSharp.Abstraction.Realtime; using System.Net.WebSockets; -using System; using BotSharp.Abstraction.Realtime.Models; using BotSharp.Abstraction.MLTasks; -using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Conversations.Enums; namespace BotSharp.Core.Realtime; @@ -12,6 +10,7 @@ public class RealtimeHub : IRealtimeHub { private readonly IServiceProvider _services; private readonly ILogger _logger; + public RealtimeHub(IServiceProvider services, ILogger logger) { _services = services; @@ -82,8 +81,7 @@ public class RealtimeHub : IRealtimeHub onModelReady: async () => { // Control initial session - await completer.UpdateInitialSession(conn); - + await completer.UpdateSession(conn); // Add dialog history foreach (var item in dialogs) @@ -123,8 +121,21 @@ public class RealtimeHub : IRealtimeHub { await routing.InvokeFunction(message.FunctionName, message); message.Role = AgentRole.Function; - await completer.InsertConversationItem(message); - await completer.TriggerModelInference("Reply based on the function's output."); + if (message.FunctionName == "route_to_agent") + { + var routedAgentId = routing.Context.GetCurrentAgentId(); + if (conn.EntryAgentId != routedAgentId) + { + conn.EntryAgentId = routedAgentId; + await completer.UpdateSession(conn); + await completer.TriggerModelInference("Reply based on the function's output."); + } + } + else + { + await completer.InsertConversationItem(message); + await completer.TriggerModelInference("Reply based on the function's output."); + } } else { diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs index efa96547..834cdd17 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs @@ -254,13 +254,13 @@ public class RealTimeCompletionProvider : IRealTimeCompletion return session; } - public async Task UpdateInitialSession(RealtimeHubConnection conn) + public async Task UpdateSession(RealtimeHubConnection conn) { var convService = _services.GetRequiredService(); var conv = await convService.GetConversation(conn.ConversationId); var agentService = _services.GetRequiredService(); - var agent = await agentService.LoadAgent(conv.AgentId); + var agent = await agentService.LoadAgent(conn.EntryAgentId); var client = ProviderHelper.GetClient(Provider, _model, _services); var chatClient = client.GetChatClient(_model); diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs index 774d014b..cd71ba01 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs @@ -1,13 +1,12 @@ using BotSharp.Abstraction.Infrastructures; +using BotSharp.Abstraction.Infrastructures.Enums; using BotSharp.Core.Infrastructures; using BotSharp.Plugin.Twilio.Interfaces; using BotSharp.Plugin.Twilio.Models; using BotSharp.Plugin.Twilio.Services; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Twilio.TwiML.Voice; using Conversation = BotSharp.Abstraction.Conversations.Models.Conversation; -using Task = System.Threading.Tasks.Task; namespace BotSharp.Plugin.Twilio.Controllers; @@ -52,10 +51,6 @@ public class TwilioStreamController : TwilioController { request.ConversationId = _context.HttpContext.Request.Query["conversation_id"]; } - else - { - request.ConversationId = request.CallSid; - } await HookEmitter.Emit(_services, async hook => { @@ -65,7 +60,7 @@ public class TwilioStreamController : TwilioController OnlyOnce = true }); - await InitConversation(request); + request.ConversationId = await InitConversation(request); var twilio = _services.GetRequiredService(); @@ -82,7 +77,7 @@ public class TwilioStreamController : TwilioController return TwiML(response); } - private async Task InitConversation(ConversationalVoiceRequest request) + private async Task InitConversation(ConversationalVoiceRequest request) { var convService = _services.GetRequiredService(); var conversation = await convService.GetConversation(request.ConversationId); @@ -90,11 +85,10 @@ public class TwilioStreamController : TwilioController { var conv = new Conversation { - Id = request.CallSid, AgentId = _settings.AgentId, Channel = ConversationChannel.Phone, ChannelId = request.CallSid, - Title = $"Phone call from {request.From}", + Title = $"Incoming phone call from {request.From}", Tags = [], }; @@ -106,9 +100,13 @@ public class TwilioStreamController : TwilioController new("channel", ConversationChannel.Phone), new("calling_phone", request.From), new("twilio_call_sid", request.CallSid), + // Enable lazy routing mode to optimize realtime experience + new(StateConst.ROUTING_MODE, "lazy"), }; convService.SetConversationId(conversation.Id, states); convService.SaveStates(); + + return conversation.Id; } }