diff --git a/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeModelSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeModelSettings.cs index 7ebe2c426..daf8714a8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeModelSettings.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeModelSettings.cs @@ -4,6 +4,7 @@ public class RealtimeModelSettings { public string Provider { get; set; } = "openai"; public string Model { get; set; } = "gpt-4o-mini-realtime-preview"; + public string[] Modalities { get; set; } = ["text", "audio"]; public bool InterruptResponse { get; set; } = true; public string InputAudioFormat { get; set; } = "g711_ulaw"; public string OutputAudioFormat { get; set; } = "g711_ulaw"; diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs index 4cac4c868..b07a64ffe 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs @@ -5,9 +5,7 @@ namespace BotSharp.Core.Agents.Services; public partial class AgentService { -#if !DEBUG [SharpCache(10)] -#endif public async Task> GetAgents(AgentFilter filter) { var agents = _db.GetAgents(filter); @@ -27,9 +25,7 @@ public async Task> GetAgents(AgentFilter filter) }; } -#if !DEBUG [SharpCache(10)] -#endif public async Task> GetAgentOptions(List? agentIds) { var agents = _db.GetAgents(new AgentFilter @@ -39,9 +35,7 @@ public async Task> GetAgentOptions(List? agentIds) return agents?.Select(x => new IdName(x.Id, x.Name))?.OrderBy(x => x.Name)?.ToList() ?? []; } -#if !DEBUG [SharpCache(10)] -#endif public async Task GetAgent(string id) { var profile = _db.GetAgent(id); diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs index 9e101b745..853b1561d 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs @@ -86,7 +86,7 @@ public IConversationStateService SetState(string name, T value, bool isNeedVe preValue = prevLeafNode?.Data ?? string.Empty; } - _logger.LogInformation($"[STATE] {name} = {value}"); + _logger.LogDebug($"[STATE] {name} = {value}"); var routingCtx = _services.GetRequiredService(); var isNoChange = ContainsState(name) @@ -221,7 +221,7 @@ public Dictionary Load(string conversationId, bool isReadOnly = var data = leafNode.Data ?? string.Empty; endNodes[state.Key] = data; - _logger.LogInformation($"[STATE] {key} : {data}"); + _logger.LogDebug($"[STATE] {key} : {data}"); } _logger.LogInformation($"Loaded conversation states: {conversationId}"); diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs index 47e476314..630497384 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs @@ -129,7 +129,7 @@ await hook.OnAgentDequeued(agentId, currentAgentId, reason: reason) // Run the routing rule var agency = _services.GetRequiredService(); - var agent = agency.LoadAgent(currentAgentId).Result; + var agent = agency.GetAgent(currentAgentId).Result; var message = new RoleDialogModel(AgentRole.User, $"Try to route to agent {agent.Name}") { diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs index 22ec7d4d1..069b6fc21 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs @@ -146,7 +146,7 @@ public override async Task OnFunctionExecuting(RoleDialogModel message) if (message.FunctionName == "route_to_agent") return; - var agent = await _agentService.LoadAgent(message.CurrentAgentId); + var agent = await _agentService.GetAgent(message.CurrentAgentId); message.FunctionArgs = message.FunctionArgs ?? "{}"; var args = message.FunctionArgs.FormatJson(); var log = $"*{message.Indication.Replace("\r", string.Empty).Replace("\n", string.Empty)}* \r\n\r\n **{message.FunctionName}**()"; @@ -169,7 +169,7 @@ public override async Task OnFunctionExecuted(RoleDialogModel message) if (message.FunctionName == "route_to_agent") return; - var agent = await _agentService.LoadAgent(message.CurrentAgentId); + var agent = await _agentService.GetAgent(message.CurrentAgentId); message.FunctionArgs = message.FunctionArgs ?? "{}"; var log = $"{message.FunctionName} =>\r\n*{message.Content?.Trim()}*"; @@ -196,7 +196,7 @@ public async Task AfterGenerated(RoleDialogModel message, TokenStatsModel tokenS var conversationId = _state.GetConversationId(); if (string.IsNullOrEmpty(conversationId)) return; - var agent = await _agentService.LoadAgent(message.CurrentAgentId); + var agent = await _agentService.GetAgent(message.CurrentAgentId); var log = tokenStats.Prompt; @@ -226,7 +226,7 @@ public override async Task OnResponseGenerated(RoleDialogModel message) if (message.Role == AgentRole.Assistant) { - var agent = await _agentService.LoadAgent(message.CurrentAgentId); + var agent = await _agentService.GetAgent(message.CurrentAgentId); var log = $"{GetMessageContent(message)}"; if (message.RichContent != null || message.SecondaryRichContent != null) { @@ -251,7 +251,7 @@ public override async Task OnTaskCompleted(RoleDialogModel message) if (string.IsNullOrEmpty(conversationId)) return; var log = $"{GetMessageContent(message)}"; - var agent = await _agentService.LoadAgent(message.CurrentAgentId); + var agent = await _agentService.GetAgent(message.CurrentAgentId); var input = new ContentLogInputModel(conversationId, message) { @@ -268,7 +268,7 @@ public override async Task OnConversationEnding(RoleDialogModel message) if (string.IsNullOrEmpty(conversationId)) return; var log = $"Conversation ended"; - var agent = await _agentService.LoadAgent(message.CurrentAgentId); + var agent = await _agentService.GetAgent(message.CurrentAgentId); var input = new ContentLogInputModel(conversationId, message) { @@ -290,7 +290,7 @@ public override async Task OnBreakpointUpdated(string conversationId, bool reset } var routing = _services.GetRequiredService(); var agentId = routing.Context.GetCurrentAgentId(); - var agent = await _agentService.LoadAgent(agentId); + var agent = await _agentService.GetAgent(agentId); var input = new ContentLogInputModel() { @@ -324,7 +324,7 @@ public async Task OnAgentEnqueued(string agentId, string preAgentId, string? rea var conversationId = _state.GetConversationId(); if (string.IsNullOrEmpty(conversationId)) return; - var agent = await _agentService.LoadAgent(agentId); + var agent = await _agentService.GetAgent(agentId); // Agent queue log var log = $"{agent.Name} is enqueued"; @@ -351,8 +351,8 @@ public async Task OnAgentDequeued(string agentId, string currentAgentId, string? var conversationId = _state.GetConversationId(); if (string.IsNullOrEmpty(conversationId)) return; - var agent = await _agentService.LoadAgent(agentId); - var currentAgent = await _agentService.LoadAgent(currentAgentId); + var agent = await _agentService.GetAgent(agentId); + var currentAgent = await _agentService.GetAgent(currentAgentId); // Agent queue log var log = $"{agent.Name} is dequeued"; @@ -379,8 +379,8 @@ public async Task OnAgentReplaced(string fromAgentId, string toAgentId, string? var conversationId = _state.GetConversationId(); if (string.IsNullOrEmpty(conversationId)) return; - var fromAgent = await _agentService.LoadAgent(fromAgentId); - var toAgent = await _agentService.LoadAgent(toAgentId); + var fromAgent = await _agentService.GetAgent(fromAgentId); + var toAgent = await _agentService.GetAgent(toAgentId); // Agent queue log var log = $"Agent queue is replaced from {fromAgent.Name} to {toAgent.Name}"; @@ -432,7 +432,7 @@ public async Task OnRoutingInstructionReceived(FunctionCallFromLlm instruct, Rol var conversationId = _state.GetConversationId(); if (string.IsNullOrEmpty(conversationId)) return; - var agent = await _agentService.LoadAgent(message.CurrentAgentId); + var agent = await _agentService.GetAgent(message.CurrentAgentId); var log = JsonSerializer.Serialize(instruct, _options.JsonSerializerOptions); log = $"```json\r\n{log}\r\n```"; @@ -451,7 +451,7 @@ public async Task OnRoutingInstructionRevised(FunctionCallFromLlm instruct, Role var conversationId = _state.GetConversationId(); if (string.IsNullOrEmpty(conversationId)) return; - var agent = await _agentService.LoadAgent(message.CurrentAgentId); + var agent = await _agentService.GetAgent(message.CurrentAgentId); var log = $"Revised user goal agent to {instruct.OriginalAgent}"; var input = new ContentLogInputModel(conversationId, message) diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs index b0b655ceb..e87f2226b 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs @@ -258,7 +258,7 @@ public async Task UpdateSession(RealtimeHubConnection conn) Instructions = instruction, ToolChoice = "auto", Tools = functions, - Modalities = [ "text", "audio" ], + Modalities = realtimeModelSettings.Modalities, Temperature = Math.Max(options.Temperature ?? realtimeModelSettings.Temperature, 0.6f), MaxResponseOutputTokens = realtimeModelSettings.MaxResponseOutputTokens, TurnDetection = new RealtimeSessionTurnDetection diff --git a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/HangupPhoneCallFn.cs b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/HangupPhoneCallFn.cs index 89d770ac8..3bba99e4b 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/HangupPhoneCallFn.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/HangupPhoneCallFn.cs @@ -44,7 +44,7 @@ public async Task Execute(RoleDialogModel message) var processUrl = $"{_twilioSetting.CallbackHost}/twilio/voice/hang-up?agent-id={message.CurrentAgentId}&conversation-id={conversationId}"; // Generate initial assistant audio - string initAudioFile = null; + /*string initAudioFile = null; if (!string.IsNullOrEmpty(args.ResponseContent)) { var completion = CompletionProvider.GetAudioSynthesizer(_services); @@ -53,7 +53,7 @@ public async Task Execute(RoleDialogModel message) fileStorage.SaveSpeechFile(conversationId, initAudioFile, data); processUrl += $"&init-audio-file={initAudioFile}"; - } + }*/ var call = CallResource.Update( url: new Uri(processUrl), diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs b/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs index 4b074a432..d93f39fbc 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs @@ -139,6 +139,12 @@ public VoiceResponse HangUp(ConversationalVoiceResponse voiceResponse) response.Play(new Uri(uri)); } } + else + { + response.Pause(5); + response.Say("Goodbye."); + } + response.Hangup(); return response; }