From cdae1235da5c526cc381453f31b84564a555cd7d Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sat, 6 Jan 2024 16:24:22 -0600 Subject: [PATCH] UnmatchedAgent --- BotSharp.sln | 11 ++++++ .../Conversations/Models/RoleDialogModel.cs | 6 +++ .../Functions/Models/FunctionCallFromLlm.cs | 7 ++++ .../BotSharp.Abstraction/Planning/IPlaner.cs | 4 +- .../Plugins/IBotSharpPlugin.cs | 6 +++ .../Plugins/Models/PluginDef.cs | 3 ++ .../Routing/Models/RoutingItem.cs | 5 +++ .../BotSharp.Core/Planning/HFPlanner.cs | 4 +- .../BotSharp.Core/Planning/NaivePlanner.cs | 20 ++++++++-- .../BotSharp.Core/Plugins/PluginLoader.cs | 3 +- .../Handlers/RouteToAgentRoutingHandler.cs | 1 + .../Routing/RoutingService.InvokeAgent.cs | 12 +++++- .../BotSharp.Core/Routing/RoutingService.cs | 4 +- .../BotSharpOpenApiExtensions.cs | 2 - .../BotSharp.Plugin.ChatHub/ChatHubPlugin.cs | 2 + .../BotSharp.Plugin.HttpHandler.csproj | 16 ++++++++ .../HttpHandlerPlugin.cs | 16 ++++++++ .../BotSharp.Plugin.HttpHandler/Using.cs | 14 +++++++ .../agent.json | 9 +++++ .../functions.json | 3 ++ .../instruction.liquid | 1 + .../Functions/SearchKnowledgesFn.cs | 3 +- .../KnowledgeBasePlugin.cs | 3 ++ .../agent.json | 9 +++++ .../functions.json | 16 ++++++++ .../instruction.liquid | 1 + .../BotSharp.Plugin.LLamaSharp.csproj | 2 +- .../Providers/TextEmbeddingProvider.cs | 4 +- .../BotSharp.Plugin.WebDriver.csproj | 8 +--- .../PlaywrightDriver/PlaywrightInstance.cs | 4 ++ .../PlaywrightWebDriver.LaunchBrowser.cs | 5 ++- .../WebDriverPlugin.cs | 4 +- .../agent.json | 2 +- .../functions.json | 38 ++++++++++++++++--- .../instruction.liquid | 8 +++- .../templates/extract_data.liquid | 4 ++ .../templates/html_parser.liquid | 1 - src/WebStarter/WebStarter.csproj | 4 +- src/WebStarter/appsettings.json | 1 + .../BotSharp.Plugin.PizzaBot.csproj | 3 -- .../PizzaBotPlugin.cs | 2 + 41 files changed, 233 insertions(+), 38 deletions(-) create mode 100644 src/Plugins/BotSharp.Plugin.HttpHandler/BotSharp.Plugin.HttpHandler.csproj create mode 100644 src/Plugins/BotSharp.Plugin.HttpHandler/HttpHandlerPlugin.cs create mode 100644 src/Plugins/BotSharp.Plugin.HttpHandler/Using.cs create mode 100644 src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/agent.json create mode 100644 src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/functions.json create mode 100644 src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/instruction.liquid create mode 100644 src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/agent.json create mode 100644 src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/functions.json create mode 100644 src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/instruction.liquid create mode 100644 src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/extract_data.liquid diff --git a/BotSharp.sln b/BotSharp.sln index c6d0684b..6806adf1 100644 --- a/BotSharp.sln +++ b/BotSharp.sln @@ -77,6 +77,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.TelegramBot EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Logger", "src\Infrastructure\BotSharp.Logger\BotSharp.Logger.csproj", "{5CA3335E-E6AD-46FD-B277-29BBC3A16500}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.HttpHandler", "src\Plugins\BotSharp.Plugin.HttpHandler\BotSharp.Plugin.HttpHandler.csproj", "{32D9E720-6FE6-4F29-94B1-B10B05BFAD75}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -293,6 +295,14 @@ Global {5CA3335E-E6AD-46FD-B277-29BBC3A16500}.Release|Any CPU.Build.0 = Release|Any CPU {5CA3335E-E6AD-46FD-B277-29BBC3A16500}.Release|x64.ActiveCfg = Release|Any CPU {5CA3335E-E6AD-46FD-B277-29BBC3A16500}.Release|x64.Build.0 = Release|Any CPU + {32D9E720-6FE6-4F29-94B1-B10B05BFAD75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32D9E720-6FE6-4F29-94B1-B10B05BFAD75}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32D9E720-6FE6-4F29-94B1-B10B05BFAD75}.Debug|x64.ActiveCfg = Debug|Any CPU + {32D9E720-6FE6-4F29-94B1-B10B05BFAD75}.Debug|x64.Build.0 = Debug|Any CPU + {32D9E720-6FE6-4F29-94B1-B10B05BFAD75}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32D9E720-6FE6-4F29-94B1-B10B05BFAD75}.Release|Any CPU.Build.0 = Release|Any CPU + {32D9E720-6FE6-4F29-94B1-B10B05BFAD75}.Release|x64.ActiveCfg = Release|Any CPU + {32D9E720-6FE6-4F29-94B1-B10B05BFAD75}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -331,6 +341,7 @@ Global {EDCD9C20-2D9D-4098-A16E-03F97B306CB8} = {64264688-0F5C-4AB0-8F2B-B59B717CCE00} {DCA18996-4D3A-4E98-BCD0-1FB77C59253E} = {64264688-0F5C-4AB0-8F2B-B59B717CCE00} {5CA3335E-E6AD-46FD-B277-29BBC3A16500} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749} + {32D9E720-6FE6-4F29-94B1-B10B05BFAD75} = {51AFE054-AE99-497D-A593-69BAEFB5106F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19} diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs index e9b40722..beeaf629 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs @@ -53,6 +53,12 @@ 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/Functions/Models/FunctionCallFromLlm.cs b/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs index 4f8435b4..dd9e2f1a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs @@ -15,6 +15,13 @@ public class FunctionCallFromLlm : RoutingArgs [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool ExecutingDirectly { 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. + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] + public bool UnmatchedAgent { get; set; } + public override string ToString() { var route = string.IsNullOrEmpty(AgentName) ? "" : $""; diff --git a/src/Infrastructure/BotSharp.Abstraction/Planning/IPlaner.cs b/src/Infrastructure/BotSharp.Abstraction/Planning/IPlaner.cs index 3d7996a1..a6136ea8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Planning/IPlaner.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Planning/IPlaner.cs @@ -9,6 +9,6 @@ namespace BotSharp.Abstraction.Planning; public interface IPlaner { Task GetNextInstruction(Agent router, string messageId); - Task AgentExecuting(FunctionCallFromLlm inst, RoleDialogModel message); - Task AgentExecuted(FunctionCallFromLlm inst, RoleDialogModel message); + Task AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message); + Task AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Plugins/IBotSharpPlugin.cs b/src/Infrastructure/BotSharp.Abstraction/Plugins/IBotSharpPlugin.cs index a5bcfd1e..ca4f6f1e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Plugins/IBotSharpPlugin.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Plugins/IBotSharpPlugin.cs @@ -8,5 +8,11 @@ public interface IBotSharpPlugin string Name => ""; string Description => ""; string IconUrl => "https://avatars.githubusercontent.com/u/44989469?s=200&v=4"; + + /// + /// Has build-in agent profile with this plugin + /// + bool WithAgent => false; + void RegisterDI(IServiceCollection services, IConfiguration config); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Plugins/Models/PluginDef.cs b/src/Infrastructure/BotSharp.Abstraction/Plugins/Models/PluginDef.cs index e0040d46..a18486d6 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Plugins/Models/PluginDef.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Plugins/Models/PluginDef.cs @@ -8,4 +8,7 @@ public class PluginDef public string Assembly { get; set; } [JsonPropertyName("icon_url")] public string IconUrl { get; set; } + + [JsonPropertyName("with_agent")] + public bool WithAgent { get; set; } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingItem.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingItem.cs index 97b5f1fb..b08edfed 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingItem.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingItem.cs @@ -18,4 +18,9 @@ public class RoutingItem [JsonPropertyName("optional_fields")] public List OptionalFields { get; set; } = new List(); + + public override string ToString() + { + return Name; + } } diff --git a/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs b/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs index 5a109452..a6c91e76 100644 --- a/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs @@ -67,7 +67,7 @@ public class HFPlanner : IPlaner return inst; } - public async Task AgentExecuting(FunctionCallFromLlm inst, RoleDialogModel message) + public async Task AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message) { if (!string.IsNullOrEmpty(inst.AgentName)) { @@ -82,7 +82,7 @@ public class HFPlanner : IPlaner return true; } - public async Task AgentExecuted(FunctionCallFromLlm inst, RoleDialogModel message) + public async Task AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message) { var context = _services.GetRequiredService(); context.Empty(); diff --git a/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs b/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs index d15f2f23..81738225 100644 --- a/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs @@ -76,7 +76,7 @@ public class NaivePlanner : IPlaner return inst; } - public async Task AgentExecuting(FunctionCallFromLlm inst, RoleDialogModel message) + public async Task AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message) { // Set user content as Planner's question message.FunctionName = inst.Function; @@ -85,10 +85,24 @@ public class NaivePlanner : IPlaner return true; } - public async Task AgentExecuted(FunctionCallFromLlm inst, RoleDialogModel message) + public async Task AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message) { var context = _services.GetRequiredService(); - context.Empty(); + if (inst.UnmatchedAgent) + { + var unmatchedAgentId = context.GetCurrentAgentId(); + + // Exclude the wrong routed agent + var agents = router.TemplateDict["routing_agents"] as RoutingItem[]; + router.TemplateDict["routing_agents"] = agents.Where(x => x.AgentId != unmatchedAgentId).ToArray(); + + // Handover to Router; + context.Pop(); + } + else + { + context.Empty(); + } return true; } diff --git a/src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs b/src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs index 38cd2899..9667ae90 100644 --- a/src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs +++ b/src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs @@ -54,7 +54,8 @@ public class PluginLoader Name = name, Description = module.Description, Assembly = assemblyName, - IconUrl = module.IconUrl + IconUrl = module.IconUrl, + WithAgent = module.WithAgent, }); Console.Write($"Loaded plugin "); Console.Write(name, Color.Green); diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index b9acfad4..d42d1349 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -50,6 +50,7 @@ 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/RoutingService.InvokeAgent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs index 51d0a22f..b5140e20 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs @@ -59,8 +59,18 @@ 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 - if (!message.StopCompletion) + else 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 8304b46e..ee8c50f1 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs @@ -98,12 +98,12 @@ public partial class RoutingService : IRoutingService #else _logger.LogInformation($"*** Next Instruction *** {inst}"); #endif - await planner.AgentExecuting(inst, message); + await planner.AgentExecuting(_router, inst, message); // Handle instruction by Executor response = await executor.Execute(this, inst, message, dialogs); - await planner.AgentExecuted(inst, response); + await planner.AgentExecuted(_router, inst, response); } return response; diff --git a/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs b/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs index cc27091c..89b9555f 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs @@ -1,7 +1,5 @@ using BotSharp.Abstraction.Messaging.JsonConverters; -using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Configuration; -using Microsoft.IdentityModel.Tokens; namespace BotSharp.OpenAPI; diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs b/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs index dcba858b..b085bef7 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs @@ -10,6 +10,8 @@ public class ChatHubPlugin : IBotSharpPlugin { public string Name => "Chat Hub"; public string Description => "A communication channel connects agents and users in real-time."; + public string IconUrl => "https://media.zeemly.com/media/product/chatrandom.png"; + public void RegisterDI(IServiceCollection services, IConfiguration config) { // Register hooks diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/BotSharp.Plugin.HttpHandler.csproj b/src/Plugins/BotSharp.Plugin.HttpHandler/BotSharp.Plugin.HttpHandler.csproj new file mode 100644 index 00000000..ef4d32e4 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/BotSharp.Plugin.HttpHandler.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.1 + enable + $(LangVersion) + $(BotSharpVersion) + $(GeneratePackageOnBuild) + $(GenerateDocumentationFile) + + + + + + + diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/HttpHandlerPlugin.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/HttpHandlerPlugin.cs new file mode 100644 index 00000000..3482d041 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/HttpHandlerPlugin.cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.Configuration; + +namespace BotSharp.Plugin.HttpHandler; + +public class HttpHandlerPlugin : IBotSharpPlugin +{ + public string Name => "HTTP Handler"; + public string Description => "Empower agent to handle HTTP request in RESTful API or GraphQL"; + public string IconUrl => "https://lirp.cdn-website.com/6f8d6d8a/dms3rep/multi/opt/API_Icon-640w.png"; + public bool WithAgent => true; + + public void RegisterDI(IServiceCollection services, IConfiguration config) + { + + } +} diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Using.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Using.cs new file mode 100644 index 00000000..f813420b --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Using.cs @@ -0,0 +1,14 @@ +global using System; +global using System.Collections.Generic; +global using System.Text; +global using BotSharp.Abstraction.Conversations; +global using BotSharp.Abstraction.Plugins; +global using System.Text.Json; +global using BotSharp.Abstraction.Conversations.Models; +global using System.Threading.Tasks; +global using BotSharp.Abstraction.Functions; +global using BotSharp.Abstraction.Agents.Models; +global using BotSharp.Abstraction.Templating; +global using Microsoft.Extensions.DependencyInjection; +global using System.Linq; +global using BotSharp.Abstraction.Utilities; \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/agent.json b/src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/agent.json new file mode 100644 index 00000000..fc879e14 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/agent.json @@ -0,0 +1,9 @@ +{ + "name": "HTTP Handler", + "description": "Use Web API to interact with other systems to obtain or update data.", + "createdDateTime": "2024-01-06T00:00:00Z", + "updatedDateTime": "2024-01-06T00:00:00Z", + "id": "87c458fc-ec5f-40ae-8ed6-05dda8a07523", + "allowRouting": true, + "isPublic": true +} \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/functions.json b/src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/functions.json new file mode 100644 index 00000000..b5a2cf7b --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/functions.json @@ -0,0 +1,3 @@ +[ + +] diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/instruction.liquid b/src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/instruction.liquid new file mode 100644 index 00000000..0f98d3da --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/agents/87c458fc-ec5f-40ae-8ed6-05dda8a07523/instruction.liquid @@ -0,0 +1 @@ +You are an HTTP handler and know how to use Open API to interact with other systems. \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/SearchKnowledgesFn.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/SearchKnowledgesFn.cs index f4d883ea..5d94f9cb 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/SearchKnowledgesFn.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/SearchKnowledgesFn.cs @@ -28,8 +28,7 @@ public class SearchKnowledgesFn : IFunctionCallback if (string.IsNullOrEmpty(knowledge)) { message.Content = "Can't find any relevant data in local knowledge base."; - var routingCtx = _services.GetRequiredService(); - routingCtx.Pop(); + message.UnmatchedAgent = true; } return true; diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/KnowledgeBasePlugin.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/KnowledgeBasePlugin.cs index 2eb6250a..e4685843 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/KnowledgeBasePlugin.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/KnowledgeBasePlugin.cs @@ -6,6 +6,9 @@ public class KnowledgeBasePlugin : IBotSharpPlugin { public string Name => "Knowledge Base"; public string Description => "Embedding private data and feed them into LLM in the conversation."; + public string IconUrl => "https://cdn-icons-png.flaticon.com/512/9592/9592995.png"; + public bool WithAgent => true; + public void RegisterDI(IServiceCollection services, IConfiguration config) { var settings = new KnowledgeBaseSettings(); diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/agent.json b/src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/agent.json new file mode 100644 index 00000000..9eb33118 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/agent.json @@ -0,0 +1,9 @@ +{ + "name": "Knowledge Base", + "description": "Local knowledge base, providing relevant answers or background knowledge to help handle user questions.", + "createdDateTime": "2024-01-02T00:00:00Z", + "updatedDateTime": "2024-01-02T00:00:00Z", + "id": "f5679799-ba89-4fef-936a-bcc311e5f14d", + "allowRouting": true, + "isPublic": true + } \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/functions.json b/src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/functions.json new file mode 100644 index 00000000..5adc8d82 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/functions.json @@ -0,0 +1,16 @@ +[ + { + "name": "search_knowledges", + "description": "Retrieve relevant knowledges", + "parameters": { + "type": "object", + "properties": { + "question": { + "type": "string", + "description": "User question" + } + }, + "required": ["question"] + } + } +] \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/instruction.liquid b/src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/instruction.liquid new file mode 100644 index 00000000..2bdfa8be --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/agents/f5679799-ba89-4fef-936a-bcc311e5f14d/instruction.liquid @@ -0,0 +1 @@ +You are a local knowledge base that retrieves the most relevant answers to certain questions. \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.LLamaSharp/BotSharp.Plugin.LLamaSharp.csproj b/src/Plugins/BotSharp.Plugin.LLamaSharp/BotSharp.Plugin.LLamaSharp.csproj index 8dcb7b38..76010525 100644 --- a/src/Plugins/BotSharp.Plugin.LLamaSharp/BotSharp.Plugin.LLamaSharp.csproj +++ b/src/Plugins/BotSharp.Plugin.LLamaSharp/BotSharp.Plugin.LLamaSharp.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Plugins/BotSharp.Plugin.LLamaSharp/Providers/TextEmbeddingProvider.cs b/src/Plugins/BotSharp.Plugin.LLamaSharp/Providers/TextEmbeddingProvider.cs index 4a433e7e..25710428 100644 --- a/src/Plugins/BotSharp.Plugin.LLamaSharp/Providers/TextEmbeddingProvider.cs +++ b/src/Plugins/BotSharp.Plugin.LLamaSharp/Providers/TextEmbeddingProvider.cs @@ -20,7 +20,9 @@ public class TextEmbeddingProvider : ITextEmbedding if (_embedder == null) { var path = Path.Combine(_settings.ModelDir, _settings.DefaultModel); - _embedder = new LLamaEmbedder(new ModelParams(path)); + var @params = new ModelParams(path); + using var weights = LLamaWeights.LoadFromFile(@params); + _embedder = new LLamaEmbedder(weights, @params); } return Task.FromResult(_embedder.GetEmbeddings(text)); diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj index b5c7afe8..aee2baa4 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj +++ b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -12,12 +12,6 @@ - - - - - - diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs index 5f62b647..0df3c6ee 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs @@ -20,6 +20,10 @@ public class PlaywrightInstance : IDisposable { Headless = false, Channel = "chrome", + Args = new[] + { + "--start-maximized" + } }); } } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LaunchBrowser.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LaunchBrowser.cs index c02b3ff1..d095d776 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LaunchBrowser.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.LaunchBrowser.cs @@ -8,7 +8,10 @@ public partial class PlaywrightWebDriver if (!string.IsNullOrEmpty(url)) { - var page = await _instance.Browser.NewPageAsync(); + var page = await _instance.Browser.NewPageAsync(new BrowserNewPageOptions + { + ViewportSize = ViewportSize.NoViewport + }); _instance.SetPage(page); var response = await page.GotoAsync(url); } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/WebDriverPlugin.cs b/src/Plugins/BotSharp.Plugin.WebDriver/WebDriverPlugin.cs index 3e4bea2b..26af3ae7 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/WebDriverPlugin.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/WebDriverPlugin.cs @@ -7,7 +7,9 @@ namespace BotSharp.Plugin.Playwrights; public class WebDriverPlugin : IBotSharpPlugin { public string Name => "Web Driver"; - public string Description => "Manipulate web browser in automation tools."; + public string Description => "Empower agent to manipulate web browser in automation tools."; + public string IconUrl => "https://cdn-icons-png.flaticon.com/512/8576/8576378.png"; + public bool WithAgent => true; public void RegisterDI(IServiceCollection services, IConfiguration config) { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json index d733511b..d2250da1 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json +++ b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json @@ -1,5 +1,5 @@ { - "name": "Web Browser", + "name": "Web Driver", "description": "Perform a specific action on a web browser", "createdDateTime": "2024-01-02T00:00:00Z", "updatedDateTime": "2024-01-02T00:00:00Z", diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json index 1f6aceac..cbc554e1 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json +++ b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json @@ -14,8 +14,8 @@ } }, { - "name": "click_html_element", - "description": "Click the html element in a web page.", + "name": "click_button", + "description": "Click a button in a web page.", "parameters": { "type": "object", "properties": { @@ -27,22 +27,50 @@ "required": ["element_name"] } }, + { + "name": "extract_data_from_page", + "description": "Extract data from current web page.", + "parameters": { + "type": "object", + "properties": { + "question": { + "type": "string", + "description": "the information user wants to know" + } + }, + "required": ["question"] + } + }, { "name": "input_user_text", - "description": "Input text in input box of web page when user requests.", + "description": "Input non-sensitive text in current web page.", "parameters": { "type": "object", "properties": { "element_name": { "type": "string", - "description": "the html element name." + "description": "the html input box element name." }, "input_text": { "type": "string", - "description": "user input." + "description": "non-sensitive text user provided." } }, "required": ["element_name", "input_text"] } + }, + { + "name": "input_user_password", + "description": "Input password in current web page", + "parameters": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "user password" + } + }, + "required": ["password"] + } } ] diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/instruction.liquid b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/instruction.liquid index 1f9f0377..4f6d65dd 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/instruction.liquid +++ b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/instruction.liquid @@ -1,2 +1,8 @@ -You are a web browser that can manipulate web elements through automated tools like Playwright and Selenium. +You are a Web Driver that can manipulate web elements through automation tools. +Follow below steps to response: +1. Analyze user's latest request in the conversation. +2. Call appropriate function to execute the instruction. + +Additional response requirements: +* Call function input_user_password if user wants to input password. \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/extract_data.liquid b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/extract_data.liquid new file mode 100644 index 00000000..12e8773b --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/extract_data.liquid @@ -0,0 +1,4 @@ +{{ content }} + +=== According to above text === +Find the answer of "{{ question }}" \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/html_parser.liquid b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/html_parser.liquid index 067ee875..2e9c8bf5 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/html_parser.liquid +++ b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/html_parser.liquid @@ -1,6 +1,5 @@ {{ html_content }} === According to above HTML === -You're using Playwright selector syntax. Find the html element tag name of "{{ element_name }}". Output in JSON format {"tag_name": "", "index": -1} with appropriate values, the "index" starts with 0. \ No newline at end of file diff --git a/src/WebStarter/WebStarter.csproj b/src/WebStarter/WebStarter.csproj index d7e6168f..4cd0482e 100644 --- a/src/WebStarter/WebStarter.csproj +++ b/src/WebStarter/WebStarter.csproj @@ -35,10 +35,11 @@ + - + @@ -64,6 +65,7 @@ + diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index ba36ef8b..915017a5 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -168,6 +168,7 @@ // "BotSharp.Plugin.TelegramBots", // "BotSharp.Plugin.RoutingSpeeder", "BotSharp.Plugin.WebDriver", + "BotSharp.Plugin.HttpHandler", "BotSharp.Plugin.PizzaBot" ] } diff --git a/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj b/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj index 4e5a8883..b4c62dd8 100644 --- a/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj +++ b/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj @@ -14,11 +14,8 @@ - - - diff --git a/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs b/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs index e1a1d61a..6946bf83 100644 --- a/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs +++ b/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs @@ -7,6 +7,8 @@ public class PizzaBotPlugin : IBotSharpPlugin { public string Name => "Pizza AI Assistant"; public string Description => "An example of an enterprise-grade AI Chatbot."; + public string IconUrl => "https://cdn-icons-png.flaticon.com/512/6978/6978255.png"; + public bool WithAgent => true; public void RegisterDI(IServiceCollection services, IConfiguration config) {