diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs index 8a922b80..925d44cf 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs @@ -1,3 +1,5 @@ +using BotSharp.Abstraction.Routing.Models; + namespace BotSharp.Abstraction.Conversations.Models; public class RoleDialogModel @@ -28,11 +30,6 @@ public class RoleDialogModel /// public object ExecutionData { get; set; } - /// - /// Intent name - /// - public string IntentName { get; set; } - /// /// Stop conversation completion /// diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingContext.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingContext.cs new file mode 100644 index 00000000..cd18008a --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingContext.cs @@ -0,0 +1,40 @@ +namespace BotSharp.Abstraction.Routing.Models; + +public class RoutingContext +{ + private Stack _stack { get; set; } + = new Stack(); + + /// + /// Intent name + /// + public string IntentName { get; set; } + + public string OriginAgentId + => _stack.Last(); + + public string CurrentAgentId + => _stack.Peek(); + + public void Push(string agentId) + { + if (_stack.Count == 0 || _stack.Peek() != agentId) + { + _stack.Push(agentId); + } + } + + /// + /// Pop current agent + /// + /// Return next agent + public string Pop() + { + if (_stack.Count > 1) + { + _stack.Pop(); + } + + return _stack.Peek(); + } +} diff --git a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs index 2d8852ed..02a5f050 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs +++ b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs @@ -10,6 +10,7 @@ using BotSharp.Core.Instructs; using BotSharp.Abstraction.Instructs; using BotSharp.Abstraction.Routing; using BotSharp.Core.Routing.Hooks; +using BotSharp.Abstraction.Routing.Models; namespace BotSharp.Core; @@ -32,6 +33,7 @@ public static class BotSharpServiceCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); var databaseSettings = new DatabaseBasicSettings(); config.Bind("Database", databaseSettings); diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index 3baad287..b1e279a2 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -37,11 +37,13 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler { AgentName = inst.AgentName }), + CurrentAgentId = routing.Dialogs.Last().CurrentAgentId }; var ret = await function.Execute(message); - var result = await routing.InvokeAgent(message.CurrentAgentId); + var context = _services.GetRequiredService(); + var result = await routing.InvokeAgent(context.CurrentAgentId); return result; } diff --git a/src/Infrastructure/BotSharp.Core/Routing/RouteToAgentFn.cs b/src/Infrastructure/BotSharp.Core/Routing/RouteToAgentFn.cs index 12e30261..df8209e5 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RouteToAgentFn.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RouteToAgentFn.cs @@ -13,16 +13,21 @@ public class RouteToAgentFn : IFunctionCallback { public string Name => "route_to_agent"; private readonly IServiceProvider _services; + private readonly RoutingContext _context; - public RouteToAgentFn(IServiceProvider services) + public RouteToAgentFn(IServiceProvider services, RoutingContext context) { _services = services; + _context = context; } public async Task Execute(RoleDialogModel message) { var args = JsonSerializer.Deserialize(message.FunctionArgs); + // Push to routing stack + _context.Push(message.CurrentAgentId); + if (string.IsNullOrEmpty(args.AgentName)) { message.ExecutionResult = $"missing agent name"; @@ -46,6 +51,8 @@ public class RouteToAgentFn : IFunctionCallback } } + _context.Push(message.CurrentAgentId); + // Set default execution data message.ExecutionData = JsonSerializer.Deserialize(message.FunctionArgs); return true; diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs index 628d9ef7..87ef9645 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs @@ -5,7 +5,7 @@ namespace BotSharp.Core.Routing; public partial class RoutingService { - const int MAXIMUM_RECURSION_DEPTH = 2; + const int MAXIMUM_RECURSION_DEPTH = 3; int CurrentRecursionDepth = 0; public async Task InvokeAgent(string agentId) { diff --git a/src/Infrastructure/BotSharp.Core/Templating/ResponseTemplateService.cs b/src/Infrastructure/BotSharp.Core/Templating/ResponseTemplateService.cs index 8fa6101d..9adce256 100644 --- a/src/Infrastructure/BotSharp.Core/Templating/ResponseTemplateService.cs +++ b/src/Infrastructure/BotSharp.Core/Templating/ResponseTemplateService.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Repositories; +using BotSharp.Abstraction.Routing.Models; using BotSharp.Abstraction.Templating; using System.IO; using System.Reflection; @@ -64,7 +65,8 @@ public class ResponseTemplateService : IResponseTemplateService // .ToList(); var db = _services.GetRequiredService(); - var responses = db.GetAgentResponses(agentId, "intent", message.IntentName); + var context = _services.GetRequiredService(); + var responses = db.GetAgentResponses(agentId, "intent", context.IntentName); if (responses.Count == 0) { diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs index 5edebf56..75aa07f1 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs @@ -11,6 +11,7 @@ using BotSharp.Plugin.RoutingSpeeder.Providers; using BotSharp.Abstraction.Agents; using System.IO; using BotSharp.Abstraction.Routing.Settings; +using BotSharp.Abstraction.Routing.Models; namespace BotSharp.Plugin.RoutingSpeeder; @@ -30,15 +31,14 @@ public class RoutingConversationHook: ConversationHookBase // intentClassifier.Train(); // Utilize local discriminative model to predict intent - var predText = intentClassifier.Predict(vector); + var context = _services.GetRequiredService(); + context.IntentName = intentClassifier.Predict(vector); - if (string.IsNullOrEmpty(predText)) + if (string.IsNullOrEmpty(context.IntentName)) { return; } - message.IntentName = predText; - // Render by template var templateService = _services.GetRequiredService(); var response = await templateService.RenderIntentResponse(_agent.Id, message);