realtime route to agent

This commit is contained in:
Haiping Chen 2025-02-26 22:40:50 -06:00
parent 1468c01f46
commit 9d570311d1
4 changed files with 28 additions and 19 deletions

View file

@ -24,7 +24,7 @@ public interface IRealTimeCompletion
Task Disconnect();
Task<RealtimeSession> CreateSession(Agent agent, List<RoleDialogModel> conversations);
Task UpdateInitialSession(RealtimeHubConnection conn);
Task UpdateSession(RealtimeHubConnection conn);
Task InsertConversationItem(RoleDialogModel message);
Task TriggerModelInference(string? instructions = null);
Task<List<RoleDialogModel>> OnResponsedDone(RealtimeHubConnection conn, string response);

View file

@ -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<RealtimeHub> 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
{

View file

@ -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<IConversationService>();
var conv = await convService.GetConversation(conn.ConversationId);
var agentService = _services.GetRequiredService<IAgentService>();
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);

View file

@ -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<ITwilioSessionHook>(_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<TwilioService>();
@ -82,7 +77,7 @@ public class TwilioStreamController : TwilioController
return TwiML(response);
}
private async Task InitConversation(ConversationalVoiceRequest request)
private async Task<string> InitConversation(ConversationalVoiceRequest request)
{
var convService = _services.GetRequiredService<IConversationService>();
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;
}
}