diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs index beeaf629..e9b40722 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs @@ -53,12 +53,6 @@ public class RoleDialogModel : ITrackableMessage [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool StopCompletion { get; set; } - /// - /// Router routed to a wrong agent. - /// Set this flag as True will force router to re-route current request to a new agent. - /// - public bool UnmatchedAgent { get; set; } - public FunctionCallFromLlm Instruction { get; set; } private RoleDialogModel() diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Enums/RuleType.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Enums/RuleType.cs index 8b910f25..1d1913dd 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Enums/RuleType.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Enums/RuleType.cs @@ -11,4 +11,9 @@ public class RuleType /// Redirect to other agent if data validation failed /// public const string DataValidation = "data-validation"; + + /// + /// The planning approach name for next step + /// + public const string Planner = "planner"; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs index 8abcc9ca..a5369af9 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs @@ -27,7 +27,7 @@ public interface IRoutingService /// RoutingRule[] GetRulesByAgentId(string id); - List GetHandlers(); + List GetHandlers(Agent router); void ResetRecursiveCounter(); Task InvokeAgent(string agentId, List dialogs); Task InvokeFunction(string name, RoleDialogModel message); diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Settings/RoutingSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Settings/RoutingSettings.cs index 50cef510..6b7ef62c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Settings/RoutingSettings.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Settings/RoutingSettings.cs @@ -2,5 +2,4 @@ namespace BotSharp.Abstraction.Routing.Settings; public class RoutingSettings { - public string Planner { get; set; } = string.Empty; } diff --git a/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs b/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs index 4551ae82..8f4e0033 100644 --- a/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs @@ -4,7 +4,6 @@ using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Repositories; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Routing.Models; -using BotSharp.Abstraction.Routing.Settings; using BotSharp.Abstraction.Templating; namespace BotSharp.Core.Planning; diff --git a/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs b/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs index 561471e2..78112559 100644 --- a/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs @@ -3,7 +3,6 @@ using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Routing.Models; -using BotSharp.Abstraction.Routing.Settings; using BotSharp.Abstraction.Templating; namespace BotSharp.Core.Planning; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index 984df62c..0e1cce58 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -63,7 +63,6 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler var response = _dialogs.Last(); inst.Response = response.Content; - inst.UnmatchedAgent = response.UnmatchedAgent; return true; } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingAgentHook.cs b/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingAgentHook.cs index 314941c0..5b42f5d8 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingAgentHook.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingAgentHook.cs @@ -28,7 +28,7 @@ public class RoutingAgentHook : AgentHookBase var routing = _services.GetRequiredService(); var agents = routing.GetRoutableAgents(_agent.Profiles); dict["routing_agents"] = agents; - dict["routing_handlers"] = routing.GetHandlers(); + dict["routing_handlers"] = routing.GetHandlers(_agent); return base.OnInstructionLoaded(template, dict); } @@ -51,13 +51,18 @@ public class RoutingAgentHook : AgentHookBase user_goal_agent = new { type = "string", - description = $"the fixed value is: {_agent.Name}" + description = $"{_agent.Name}" }, next_action_agent = new { type = "string", - description = $"the fixed value is: {redirectAgent.Name}" - } + description = $"{redirectAgent.Name}" + }, + reason = new + { + type = "string", + description = $"the reason why you need to fallback to [{redirectAgent.Name}] from [{_agent.Name}]" + }, }); functions.Add(new FunctionDef { @@ -65,7 +70,13 @@ public class RoutingAgentHook : AgentHookBase Description = $"If the user's request is beyond your capabilities, you can call this function to handle by other agent ({redirectAgent.Name}).", Parameters = { - Properties = JsonSerializer.Deserialize(json) + Properties = JsonSerializer.Deserialize(json), + Required = new List + { + "user_goal_agent", + "next_action_agent", + "reason" + } } }); } diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs index c0881ed2..946e6057 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs @@ -38,17 +38,5 @@ public class RoutingPlugin : IBotSharpPlugin services.AddScoped(); services.AddScoped(); services.AddScoped(); - - services.AddScoped(provider => - { - var settingService = provider.GetRequiredService(); - var routingSettings = settingService.Bind("Router"); - if (routingSettings.Planner == nameof(HFPlanner)) - return provider.GetRequiredService(); - else if (routingSettings.Planner == nameof(SequentialPlanner)) - return provider.GetRequiredService(); - else - return provider.GetRequiredService(); - }); } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetPlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetPlanner.cs new file mode 100644 index 00000000..01de9a29 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetPlanner.cs @@ -0,0 +1,21 @@ +using BotSharp.Abstraction.Agents.Models; +using BotSharp.Abstraction.Planning; +using BotSharp.Abstraction.Routing.Enums; +using BotSharp.Core.Planning; + +namespace BotSharp.Core.Routing; + +public partial class RoutingService +{ + public IPlaner GetPlanner(Agent router) + { + var planner = router.RoutingRules.FirstOrDefault(x => x.Type == RuleType.Planner); + + if (planner?.Field == nameof(HFPlanner)) + return _services.GetRequiredService(); + else if (planner?.Field == nameof(SequentialPlanner)) + return _services.GetRequiredService(); + else + return _services.GetRequiredService(); + } +} diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs index 1c7789bd..e144a688 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs @@ -57,18 +57,8 @@ public partial class RoutingService // Call functions await conversationService.CallFunctions(message); - // Router selected the wrong agent, handle this excluding the agent - if (message.UnmatchedAgent) - { - // Save to memory dialogs - var msg = RoleDialogModel.From(message, - role: AgentRole.Function, - content: message.Content); - msg.UnmatchedAgent = true; - dialogs.Add(msg); - } // Pass execution result to LLM to get response - else if (!message.StopCompletion) + if (!message.StopCompletion) { var routing = _services.GetRequiredService(); diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs index a241fbe2..b94903af 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs @@ -73,9 +73,10 @@ public partial class RoutingService : IRoutingService var dialogs = conv.GetDialogHistory(); var context = _services.GetRequiredService(); - var planner = _services.GetRequiredService(); var executor = _services.GetRequiredService(); + var planner = GetPlanner(_router); + context.Push(_router.Id); int loopCount = 0; @@ -85,7 +86,6 @@ public partial class RoutingService : IRoutingService var conversation = await GetConversationContent(dialogs); _router.TemplateDict["conversation"] = conversation; - _router.TemplateDict["planner"] = _settings.Planner; // Get instruction from Planner var inst = await planner.GetNextInstruction(_router, message.MessageId); @@ -109,9 +109,9 @@ public partial class RoutingService : IRoutingService return response; } - public List GetHandlers() + public List GetHandlers(Agent router) { - var planer = _services.GetRequiredService(); + var planer = GetPlanner(router); return _services.GetServices() .Where(x => x.Planers == null || x.Planers.Contains(planer.GetType().Name)) diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json index c8e4f4bd..18e856b7 100644 --- a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json +++ b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json @@ -7,5 +7,12 @@ "updatedDateTime": "2023-08-18T14:39:32.2349686Z", "iconUrl": "https://cdn.iconscout.com/icon/premium/png-256-thumb/route-1613278-1368497.png", "disabled": false, - "isPublic": true + "isPublic": true, + "profiles": [ "default" ], + "routingRules": [ + { + "type": "planner", + "field": "HFPlanner" + } + ] } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs index dfc41e79..9183be01 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs @@ -33,9 +33,15 @@ public class AgentController : ControllerBase public async Task> GetAgents([FromQuery] AgentFilter filter) { var pagedAgents = await _agentService.GetAgents(filter); + var items = new List(); + foreach (var agent in pagedAgents.Items) + { + var renderedAgent = await _agentService.LoadAgent(agent.Id); + items.Add(renderedAgent); + } return new PagedItems { - Items = pagedAgents.Items.Select(x => AgentViewModel.FromAgent(x)).ToList(), + Items = items.Select(x => AgentViewModel.FromAgent(x)).ToList(), Count = pagedAgents.Count }; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs index e0d6c375..3c35b3af 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs @@ -17,18 +17,13 @@ public class AgentViewModel public List Functions { get; set; } public List Responses { get; set; } public List Samples { get; set; } + [JsonPropertyName("is_public")] public bool IsPublic { get; set; } - [JsonPropertyName("is_router")] - public bool IsRouter { get; set; } - [JsonPropertyName("is_host")] public bool IsHost { get; set; } - [JsonPropertyName("allow_routing")] - public bool AllowRouting { get; set; } - public bool Disabled { get; set; } [JsonPropertyName("icon_url")] diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/SearchKnowledgesFn.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/SearchKnowledgesFn.cs index f2bad9bf..68d5bd25 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/SearchKnowledgesFn.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/SearchKnowledgesFn.cs @@ -27,7 +27,6 @@ public class SearchKnowledgesFn : IFunctionCallback if (string.IsNullOrEmpty(knowledge)) { message.Content = "Can't find any relevant data in local knowledge base."; - message.UnmatchedAgent = true; } return true; diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index 61ff3a19..67952c9a 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -60,7 +60,6 @@ ], "Router": { - "Planner": "NaivePlanner" }, "Evaluator": {