From 6308bdea5fa712f12f56e09d0d51343a25835d8a Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Mon, 4 Aug 2025 14:21:11 -0500 Subject: [PATCH] change to options --- .../Conversations/ConversationHookBase.cs | 4 +-- .../Conversations/IConversationHook.cs | 4 +-- .../Routing/IRoutingService.cs | 4 +-- .../Routing/Models/InvokeOptions.cs | 31 +++++++++++++++++++ .../Hooks/RealtimeConversationHook.cs | 6 ++-- .../Services/RealtimeHub.cs | 2 +- .../Evaluations/EvaluationConversationHook.cs | 5 +-- .../Routing/Reasoning/InstructExecutor.cs | 14 +++++---- .../Routing/RoutingService.InvokeAgent.cs | 17 +++++----- .../Routing/RoutingService.InvokeFunction.cs | 8 +++-- .../BotSharp.Core/Routing/RoutingService.cs | 11 ++++--- .../Controllers/RealtimeController.cs | 2 +- .../Hooks/ChatHubConversationHook.cs | 5 +-- .../Hooks/StreamingLogHook.cs | 5 +-- .../Hooks/TwilioConversationHook.cs | 3 +- 15 files changed, 81 insertions(+), 40 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Routing/Models/InvokeOptions.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs index 0a5244f8..855bd79e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs @@ -49,10 +49,10 @@ public abstract class ConversationHookBase : IConversationHook public virtual Task OnHumanInterventionNeeded(RoleDialogModel message) => Task.CompletedTask; - public virtual Task OnFunctionExecuting(RoleDialogModel message, string from = InvokeSource.Manual) + public virtual Task OnFunctionExecuting(RoleDialogModel message, InvokeFunctionOptions? options = null) => Task.CompletedTask; - public virtual Task OnFunctionExecuted(RoleDialogModel message, string from = InvokeSource.Manual) + public virtual Task OnFunctionExecuted(RoleDialogModel message, InvokeFunctionOptions? options = null) => Task.CompletedTask; public virtual Task OnMessageReceived(RoleDialogModel message) diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs index d1b6f83c..5a1d8aa2 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs @@ -61,7 +61,7 @@ public interface IConversationHook : IHookBase /// /// /// - Task OnFunctionExecuting(RoleDialogModel message, string from = InvokeSource.Manual); + Task OnFunctionExecuting(RoleDialogModel message, InvokeFunctionOptions? options = null); /// /// Triggered when the function calling completed. @@ -69,7 +69,7 @@ public interface IConversationHook : IHookBase /// /// /// - Task OnFunctionExecuted(RoleDialogModel message, string from = InvokeSource.Manual); + Task OnFunctionExecuted(RoleDialogModel message, InvokeFunctionOptions? options = null); Task OnResponseGenerated(RoleDialogModel message); diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs index 56c98a82..d387fab1 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs @@ -26,8 +26,8 @@ public interface IRoutingService /// RoutingRule[] GetRulesByAgentId(string id); - Task InvokeAgent(string agentId, List dialogs, string from = InvokeSource.Manual, bool useStream = false); - Task InvokeFunction(string name, RoleDialogModel messages, string from = InvokeSource.Manual); + Task InvokeAgent(string agentId, List dialogs, InvokeAgentOptions? options = null); + Task InvokeFunction(string name, RoleDialogModel messages, InvokeFunctionOptions? options = null); Task InstructLoop(Agent agent, RoleDialogModel message, List dialogs); /// diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/InvokeOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/InvokeOptions.cs new file mode 100644 index 00000000..5e031787 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/InvokeOptions.cs @@ -0,0 +1,31 @@ +namespace BotSharp.Abstraction.Routing.Models; + +public abstract class InvokeOptions +{ + public string From { get; set; } +} + +public class InvokeAgentOptions : InvokeOptions +{ + public bool UseStream { get; set; } + + public static InvokeAgentOptions Default() + { + return new() + { + From = InvokeSource.Manual, + UseStream = false + }; + } +} + +public class InvokeFunctionOptions : InvokeOptions +{ + public static InvokeFunctionOptions Default() + { + return new() + { + From = InvokeSource.Manual + }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs b/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs index 095ff2b8..07b8646c 100644 --- a/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs +++ b/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs @@ -11,7 +11,7 @@ public class RealtimeConversationHook : ConversationHookBase, IConversationHook _services = services; } - public async Task OnFunctionExecuting(RoleDialogModel message, string from = InvokeSource.Manual) + public async Task OnFunctionExecuting(RoleDialogModel message, InvokeFunctionOptions? options = null) { var hub = _services.GetRequiredService(); if (hub.HubConn == null) @@ -32,10 +32,10 @@ public class RealtimeConversationHook : ConversationHookBase, IConversationHook } } - public async Task OnFunctionExecuted(RoleDialogModel message, string from = InvokeSource.Manual) + public async Task OnFunctionExecuted(RoleDialogModel message, InvokeFunctionOptions? options = null) { var hub = _services.GetRequiredService(); - if (from != InvokeSource.Llm || hub.HubConn == null) + if (options?.From != InvokeSource.Llm || hub.HubConn == null) { return; } diff --git a/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs b/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs index fe544b4d..0ff601e1 100644 --- a/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs +++ b/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs @@ -99,7 +99,7 @@ public class RealtimeHub : IRealtimeHub agent.Id); } - await routing.InvokeFunction(message.FunctionName, message, from: InvokeSource.Llm); + await routing.InvokeFunction(message.FunctionName, message, options: new() { From = InvokeSource.Llm }); } else { diff --git a/src/Infrastructure/BotSharp.Core/Evaluations/EvaluationConversationHook.cs b/src/Infrastructure/BotSharp.Core/Evaluations/EvaluationConversationHook.cs index b1b4541e..80757219 100644 --- a/src/Infrastructure/BotSharp.Core/Evaluations/EvaluationConversationHook.cs +++ b/src/Infrastructure/BotSharp.Core/Evaluations/EvaluationConversationHook.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Evaluations; +using BotSharp.Abstraction.Routing.Models; namespace BotSharp.Core.Evaluations; @@ -22,13 +23,13 @@ public class EvaluationConversationHook : ConversationHookBase return base.OnMessageReceived(message); } - public override Task OnFunctionExecuted(RoleDialogModel message, string from = InvokeSource.Manual) + public override Task OnFunctionExecuted(RoleDialogModel message, InvokeFunctionOptions? options = null) { if (Conversation != null && _convSettings.EnableExecutionLog) { _logger.Append(Conversation.Id, $"[{DateTime.Now}] {message.Role}: {message.FunctionName}({message.FunctionArgs}) => {message.Content}"); } - return base.OnFunctionExecuted(message, from: from); + return base.OnFunctionExecuted(message, options); } public override Task OnResponseGenerated(RoleDialogModel message) diff --git a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs index e0ac69a2..9dd19c09 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Reasoning/InstructExecutor.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Infrastructures.Enums; using BotSharp.Abstraction.Planning; +using BotSharp.Abstraction.Routing.Models; namespace BotSharp.Core.Routing.Reasoning; @@ -33,7 +34,7 @@ public class InstructExecutor : IExecutor if (message.FunctionName != null) { var msg = RoleDialogModel.From(message, role: AgentRole.Function); - await routing.InvokeFunction(message.FunctionName, msg, from: InvokeSource.Llm); + await routing.InvokeFunction(message.FunctionName, msg, options: new() { From = InvokeSource.Routing }); } var agentId = routing.Context.GetCurrentAgentId(); @@ -59,11 +60,12 @@ public class InstructExecutor : IExecutor { var state = _services.GetRequiredService(); var useStreamMsg = state.GetState("use_stream_message"); - var ret = await routing.InvokeAgent( - agentId, - dialogs, - from: InvokeSource.Routing, - useStream: bool.TryParse(useStreamMsg, out var useStream) && useStream); + var options = new InvokeAgentOptions() + { + From = InvokeSource.Routing, + UseStream = bool.TryParse(useStreamMsg, out var useStream) && useStream + }; + var ret = await routing.InvokeAgent(agentId, dialogs, options); } var response = dialogs.Last(); diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs index 6d2813d9..6acb58b2 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Routing.Models; using BotSharp.Abstraction.Templating; namespace BotSharp.Core.Routing; @@ -7,9 +8,9 @@ public partial class RoutingService public async Task InvokeAgent( string agentId, List dialogs, - string from = InvokeSource.Manual, - bool useStream = false) + InvokeAgentOptions? options = null) { + options ??= InvokeAgentOptions.Default(); var agentService = _services.GetRequiredService(); var agent = await agentService.LoadAgent(agentId); @@ -36,7 +37,7 @@ public partial class RoutingService RoleDialogModel response; var message = dialogs.Last(); - if (useStream) + if (options?.UseStream == true) { response = await chatCompletion.GetChatCompletionsStreamingAsync(agent, dialogs); } @@ -59,7 +60,7 @@ public partial class RoutingService message.CurrentAgentId = agent.Id; message.IsStreaming = response.IsStreaming; - await InvokeFunction(message, dialogs, from: from, useStream: useStream); + await InvokeFunction(message, dialogs, options); } else { @@ -83,8 +84,7 @@ public partial class RoutingService private async Task InvokeFunction( RoleDialogModel message, List dialogs, - string from, - bool useStream) + InvokeAgentOptions? options = null) { // execute function // Save states @@ -93,7 +93,8 @@ public partial class RoutingService var routing = _services.GetRequiredService(); // Call functions - await routing.InvokeFunction(message.FunctionName, message, from: from); + var funcOptions = options != null ? new InvokeFunctionOptions() { From = options.From } : null; + await routing.InvokeFunction(message.FunctionName, message, options: funcOptions); // Pass execution result to LLM to get response if (!message.StopCompletion) @@ -120,7 +121,7 @@ public partial class RoutingService // Send to Next LLM var curAgentId = routing.Context.GetCurrentAgentId(); - await InvokeAgent(curAgentId, dialogs, from, useStream); + await InvokeAgent(curAgentId, dialogs, options); } } else diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs index 694ab2d3..dea0947d 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Routing.Models; using BotSharp.Core.MessageHub; using BotSharp.Core.Routing.Executor; @@ -5,8 +6,9 @@ namespace BotSharp.Core.Routing; public partial class RoutingService { - public async Task InvokeFunction(string name, RoleDialogModel message, string from = InvokeSource.Manual) + public async Task InvokeFunction(string name, RoleDialogModel message, InvokeFunctionOptions? options = null) { + options ??= InvokeFunctionOptions.Default(); var currentAgentId = message.CurrentAgentId; var agentService = _services.GetRequiredService(); var agent = await agentService.GetAgent(currentAgentId); @@ -38,7 +40,7 @@ public partial class RoutingService foreach (var hook in hooks) { hook.SetAgent(agent); - await hook.OnFunctionExecuting(clonedMessage, from: from); + await hook.OnFunctionExecuting(clonedMessage, options); } bool result = false; @@ -50,7 +52,7 @@ public partial class RoutingService // After functions have been executed foreach (var hook in hooks) { - await hook.OnFunctionExecuted(clonedMessage, from: from); + await hook.OnFunctionExecuted(clonedMessage, options); } // Set result to original message diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs index c66ef4b2..4e43cbd5 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs @@ -53,11 +53,12 @@ public partial class RoutingService : IRoutingService { var state = _services.GetRequiredService(); var useStreamMsg = state.GetState("use_stream_message"); - var ret = await routing.InvokeAgent( - agentId, - dialogs, - from: InvokeSource.Routing, - useStream: bool.TryParse(useStreamMsg, out var useStream) && useStream); + var options = new InvokeAgentOptions() + { + From = InvokeSource.Routing, + UseStream = bool.TryParse(useStreamMsg, out var useStream) && useStream + }; + var ret = await routing.InvokeAgent(agentId, dialogs, options); } var response = dialogs.Last(); diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/RealtimeController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/RealtimeController.cs index 61ae77a7..ff3aca46 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/RealtimeController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/RealtimeController.cs @@ -26,7 +26,7 @@ public class RealtimeController : ControllerBase FunctionName = functionName, FunctionArgs = JsonSerializer.Serialize(args) }; - await routing.InvokeFunction(functionName, message, from: InvokeSource.Llm); + await routing.InvokeFunction(functionName, message, options: new() { From = InvokeSource.Llm }); return message.Content; } } diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs index bd590276..e07f94d4 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs @@ -1,6 +1,7 @@ using BotSharp.Abstraction.Conversations.Dtos; using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.Routing.Enums; +using BotSharp.Abstraction.Routing.Models; using BotSharp.Abstraction.SideCar; using BotSharp.Abstraction.Users.Dtos; using Microsoft.AspNetCore.SignalR; @@ -78,9 +79,9 @@ public class ChatHubConversationHook : ConversationHookBase await base.OnMessageReceived(message); } - public override async Task OnFunctionExecuting(RoleDialogModel message, string from = InvokeSource.Manual) + public override async Task OnFunctionExecuting(RoleDialogModel message, InvokeFunctionOptions? options = null) { - await base.OnFunctionExecuting(message, from: from); + await base.OnFunctionExecuting(message, options); } public override async Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg) diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs index 73365115..86adaf2c 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.Routing.Enums; +using BotSharp.Abstraction.Routing.Models; using Microsoft.AspNetCore.SignalR; using System.Runtime.CompilerServices; using System.Text.Encodings.Web; @@ -141,7 +142,7 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IR if (!_convSettings.ShowVerboseLog) return; } - public override async Task OnFunctionExecuting(RoleDialogModel message, string from = InvokeSource.Manual) + public override async Task OnFunctionExecuting(RoleDialogModel message, InvokeFunctionOptions? options = null) { var conversationId = _state.GetConversationId(); if (string.IsNullOrEmpty(conversationId)) return; @@ -165,7 +166,7 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IR await SendEvent(ChatEvent.OnConversationContentLogGenerated, conversationId, BuildContentLog(input)); } - public override async Task OnFunctionExecuted(RoleDialogModel message, string from = InvokeSource.Manual) + public override async Task OnFunctionExecuted(RoleDialogModel message, InvokeFunctionOptions? options = null) { var conversationId = _state.GetConversationId(); if (string.IsNullOrEmpty(conversationId)) return; diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Hooks/TwilioConversationHook.cs b/src/Plugins/BotSharp.Plugin.Twilio/Hooks/TwilioConversationHook.cs index 11bd8d36..bf856ee4 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Hooks/TwilioConversationHook.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Hooks/TwilioConversationHook.cs @@ -1,6 +1,7 @@ using BotSharp.Abstraction.Hooks; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Enums; +using BotSharp.Abstraction.Routing.Models; using BotSharp.Plugin.Twilio.Interfaces; using BotSharp.Plugin.Twilio.Models; using Twilio.Rest.Api.V2010.Account; @@ -23,7 +24,7 @@ public class TwilioConversationHook : ConversationHookBase, IConversationHook _logger = logger; } - public override async Task OnFunctionExecuted(RoleDialogModel message, string from = InvokeSource.Manual) + public override async Task OnFunctionExecuted(RoleDialogModel message, InvokeFunctionOptions? options = null) { var hooks = _services.GetHooks(message.CurrentAgentId);