From c46fa843cda4e251e8cfd3040ecd40cc8e6337b0 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sun, 24 Sep 2023 11:20:02 -0500 Subject: [PATCH] Clean code. --- Directory.Build.props | 2 +- .../Routing/IRoutingHandler.cs | 3 +- .../Routing/Models/RoutingHandlerDef.cs | 4 +- .../Accounts/AccountController.cs | 87 ------------------- .../BotSharp.Core/Accounts/AccountCore.cs | 64 -------------- .../Accounts/AccountDbInitializer.cs | 40 --------- .../BotSharp.Core/Accounts/User.cs | 60 ------------- .../BotSharp.Core/Accounts/UserAuth.cs | 36 -------- .../BotSharp.Core/Accounts/VmUser.cs | 21 ----- .../BotSharp.Core/Accounts/VmUserLogin.cs | 13 --- .../BotSharp.Core/BotSharp.Core.csproj | 40 +-------- .../BotSharpServiceCollectionExtensions.cs | 40 +++++---- .../ConversationService.SendMessage.cs | 13 ++- .../BotSharp.Core/CoreController.cs | 43 --------- .../Infrastructures/PluginLoader.cs | 3 +- .../ContinueExecuteTaskRoutingHandler.cs | 9 +- .../Handlers/ConversationEndRoutingHandler.cs | 4 +- .../GetNextInstructionRoutingHandler.cs | 2 - .../InterruptTaskExecutionRoutingHandler.cs | 7 +- .../Handlers/ResponseToUserRoutingHandler.cs | 7 +- .../RetrieveDataFromAgentRoutingHandler.cs | 11 +-- .../Handlers/RouteToAgentRoutingHandler.cs | 9 +- .../Routing/Handlers/TaskEndRoutingHandler.cs | 5 +- .../BotSharp.Core/Routing/PromptConst.cs | 33 ------- .../BotSharp.Core/Routing/RoutingService.cs | 54 ++++++++++-- .../BotSharp.Plugin.AzureOpenAI.csproj | 2 +- .../Providers/ChatCompletionProvider.cs | 6 +- .../BotSharp.Plugin.KnowledgeBase.csproj | 2 +- .../BotSharp.Plugin.WeChat.csproj | 1 - .../BotSharp.Plugin.WeChat/WeChatPlugin.cs | 6 -- src/WebStarter/appsettings.json | 1 + 31 files changed, 130 insertions(+), 498 deletions(-) delete mode 100644 src/Infrastructure/BotSharp.Core/Accounts/AccountController.cs delete mode 100644 src/Infrastructure/BotSharp.Core/Accounts/AccountCore.cs delete mode 100644 src/Infrastructure/BotSharp.Core/Accounts/AccountDbInitializer.cs delete mode 100644 src/Infrastructure/BotSharp.Core/Accounts/User.cs delete mode 100644 src/Infrastructure/BotSharp.Core/Accounts/UserAuth.cs delete mode 100644 src/Infrastructure/BotSharp.Core/Accounts/VmUser.cs delete mode 100644 src/Infrastructure/BotSharp.Core/Accounts/VmUserLogin.cs delete mode 100644 src/Infrastructure/BotSharp.Core/CoreController.cs delete mode 100644 src/Infrastructure/BotSharp.Core/Routing/PromptConst.cs diff --git a/Directory.Build.props b/Directory.Build.props index fffd5b8b..95c90ef7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ 10.0 ..\..\..\packages - 0.14.7 + 0.14.8 true \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs index 944cd502..ddb83fec 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Models; namespace BotSharp.Abstraction.Routing; @@ -8,7 +9,7 @@ public interface IRoutingHandler string Description { get; } bool IsReasoning { get => false; } bool Enabled { get => true; } - List Parameters { get => new List(); } + List Parameters { get => new List(); } void SetRouter(Agent router) { } diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingHandlerDef.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingHandlerDef.cs index 8b792287..eb50835c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingHandlerDef.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingHandlerDef.cs @@ -1,8 +1,10 @@ +using BotSharp.Abstraction.Models; + namespace BotSharp.Abstraction.Routing.Models; public class RoutingHandlerDef { public string Name { get; set; } public string Description { get; set; } - public List Parameters { get; set; } + public List Parameters { get; set; } } diff --git a/src/Infrastructure/BotSharp.Core/Accounts/AccountController.cs b/src/Infrastructure/BotSharp.Core/Accounts/AccountController.cs deleted file mode 100644 index ab53c7b3..00000000 --- a/src/Infrastructure/BotSharp.Core/Accounts/AccountController.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Text; -using DotNetToolkit.JwtHelper; -using DotNetToolkit; -using EntityFrameworkCore.BootKit; -using Microsoft.Extensions.Configuration; -using System.Linq; - -namespace BotSharp.Core.Accounts -{ - /// - /// The /account endpoint is used to create, retrieve, update, and delete account. - /// - public class AccountController : CoreController - { - private IConfiguration config; - - public AccountController(IConfiguration config) - { - this.config = config; - } - - [HttpGet("/account")] - public VmUser GetUser() - { - /*var user = dc.Table().Find(CurrentUserId); - return user.ToObject();*/ - return new VmUser - { - Email = "botsharp@ai.com", - FirstName = "Bot", - LastName = "Sharp" - }; - } - - /// - /// Get a valid token after login - /// - /// User Email - /// Password - /// - [AllowAnonymous] - [HttpPost("/token")] - [ProducesResponseType(typeof(string), 200)] - public IActionResult Token([FromBody] VmUserLogin userModel) - { - if (string.IsNullOrEmpty(userModel.UserName) || string.IsNullOrEmpty(userModel.Password)) - { - return new BadRequestObjectResult("Username and password should not be empty."); - } - return Ok(JwtToken.GenerateToken(config, "botsharp")); - // validate from local - var user = (from usr in dc.Table() - join auth in dc.Table() on usr.Id equals auth.UserId - where usr.UserName == userModel.UserName - select auth).FirstOrDefault(); - - if (user != null) - { - if (!user.IsActivated) - { - return BadRequest("Account hasn't been activated, please check your email to activate it."); - } - else - { - // validate password - string hash = PasswordHelper.Hash(userModel.Password, user.Salt); - if (user.Password == hash) - { - return Ok(JwtToken.GenerateToken(config, "botsharp")); - } - else - { - return BadRequest("Authorization Failed."); - } - } - } - else - { - return BadRequest("Account doesn't exist"); - } - } - } -} diff --git a/src/Infrastructure/BotSharp.Core/Accounts/AccountCore.cs b/src/Infrastructure/BotSharp.Core/Accounts/AccountCore.cs deleted file mode 100644 index 8c048c6b..00000000 --- a/src/Infrastructure/BotSharp.Core/Accounts/AccountCore.cs +++ /dev/null @@ -1,64 +0,0 @@ -using DotNetToolkit; -using EntityFrameworkCore.BootKit; -using Microsoft.Extensions.Configuration; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace BotSharp.Core.Accounts -{ - public class AccountCore - { - private Database _dc; - private IConfiguration _config; - - public AccountCore(Database dc = null) - { - if (dc == null) - { - dc = new DefaultDataContextLoader().GetDefaultDc(); - } - else - { - _dc = dc; - } - - _config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration"); - } - - public void CreateUser(User user) - { - user.Authenticaiton.IsActivated = false; - user.Authenticaiton.Salt = PasswordHelper.GetSalt(); - user.Authenticaiton.Password = PasswordHelper.Hash(user.Authenticaiton.Password, user.Authenticaiton.Salt); - user.Authenticaiton.ActivationCode = Guid.NewGuid().ToString("N"); - - _dc.Transaction(() => - { - _dc.Table().Add(user); - }); - - - $"Created user {user.Email}, user id: {user.Id}".Log(LogLevel.INFO); - } - - public void Activate(string activationCode) - { - var activation = _dc.Table().FirstOrDefault(x => x.ActivationCode == activationCode && !x.IsActivated); - if (activation == null) - { - } - else - { - _dc.Transaction(() => - { - activation = _dc.Table().FirstOrDefault(x => x.ActivationCode == activationCode); - activation.ActivationCode = String.Empty; - activation.IsActivated = true; - activation.UpdatedTime = DateTime.UtcNow; - }); - } - } - } -} diff --git a/src/Infrastructure/BotSharp.Core/Accounts/AccountDbInitializer.cs b/src/Infrastructure/BotSharp.Core/Accounts/AccountDbInitializer.cs deleted file mode 100644 index dd066622..00000000 --- a/src/Infrastructure/BotSharp.Core/Accounts/AccountDbInitializer.cs +++ /dev/null @@ -1,40 +0,0 @@ -using BotSharp.Core.Abstractions; -using CherubNLP.Tokenize; -using EntityFrameworkCore.BootKit; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -namespace BotSharp.Core.Accounts -{ - public class AccountDbInitializer : IHookDbInitializer - { - public int Priority => 100; - - public void Load(Database dc) - { - ImportAccount(dc); - } - - private void ImportAccount(Database dc) - { - var dataPath = Path.Combine(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "DbInitializer", "Accounts"); - string json = File.ReadAllText(Path.Combine(dataPath, "users.json")); - - var users = JsonConvert.DeserializeObject>(json); - users.ForEach(user => - { - if (!dc.Table().Any(x => x.UserName == user.UserName)) - { - var core = new AccountCore(dc); - core.CreateUser(user); - core.Activate(user.Authenticaiton.ActivationCode); - } - }); - - } - } -} diff --git a/src/Infrastructure/BotSharp.Core/Accounts/User.cs b/src/Infrastructure/BotSharp.Core/Accounts/User.cs deleted file mode 100644 index aa9e3c4b..00000000 --- a/src/Infrastructure/BotSharp.Core/Accounts/User.cs +++ /dev/null @@ -1,60 +0,0 @@ -using EntityFrameworkCore.BootKit; -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Text; - -namespace BotSharp.Core.Accounts -{ - /// - /// User profile - /// - [Table("User")] - public class User : DbRecord, IDbRecord - { - [Required] - [StringLength(64)] - public string UserName { get; set; } - - [Required] - [StringLength(64)] - [DataType(DataType.EmailAddress)] - public string Email { get; set; } - - [StringLength(32)] - public string FirstName { get; set; } - - [StringLength(32)] - public string LastName { get; set; } - - [MaxLength(256)] - public string Description { get; set; } - - [Required] - [DataType(DataType.DateTime)] - public DateTime SignupDate { get; set; } - - [DataType(DataType.Date)] - public DateTime? Birthday { get; set; } - - [MaxLength(36)] - public string Nationality { get; set; } - - [NotMapped] - public string FullName - { - get - { - return FirstName + (string.IsNullOrEmpty(LastName) ? "" : " " + LastName); - } - } - - public UserAuth Authenticaiton { get; set; } - - public User() - { - SignupDate = DateTime.UtcNow; - } - } -} diff --git a/src/Infrastructure/BotSharp.Core/Accounts/UserAuth.cs b/src/Infrastructure/BotSharp.Core/Accounts/UserAuth.cs deleted file mode 100644 index 022bc78d..00000000 --- a/src/Infrastructure/BotSharp.Core/Accounts/UserAuth.cs +++ /dev/null @@ -1,36 +0,0 @@ -using EntityFrameworkCore.BootKit; -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Text; - -namespace BotSharp.Core.Accounts -{ - /// - /// User authentication - /// - [Table("UserAuth")] - public class UserAuth : DbRecord, IDbRecord - { - [StringLength(36)] - public string UserId { get; set; } - - [Required] - [StringLength(256)] - [DataType(DataType.Password)] - public string Password { get; set; } - - [Required] - [StringLength(64)] - public string Salt { get; set; } - - [StringLength(32)] - public string ActivationCode { get; set; } - - public bool IsActivated { get; set; } - - [ForeignKey("UserId")] - public User User { get; set; } - } -} diff --git a/src/Infrastructure/BotSharp.Core/Accounts/VmUser.cs b/src/Infrastructure/BotSharp.Core/Accounts/VmUser.cs deleted file mode 100644 index 5e2626d9..00000000 --- a/src/Infrastructure/BotSharp.Core/Accounts/VmUser.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace BotSharp.Core.Accounts -{ - public class VmUser - { - public String FullName - { - get - { - return $"{FirstName} {LastName}"; - } - } - public String FirstName { get; set; } - public String LastName { get; set; } - public String Email { get; set; } - public String Avatar { get; set; } - } -} diff --git a/src/Infrastructure/BotSharp.Core/Accounts/VmUserLogin.cs b/src/Infrastructure/BotSharp.Core/Accounts/VmUserLogin.cs deleted file mode 100644 index d4817001..00000000 --- a/src/Infrastructure/BotSharp.Core/Accounts/VmUserLogin.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace BotSharp.Core.Accounts -{ - public class VmUserLogin - { - public string UserName { get; set; } - - public string Password { get; set; } - } -} diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index b93316a1..20c0d75e 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -6,28 +6,17 @@ $(BotSharpVersion) $(GeneratePackageOnBuild) - - - SAK - SAK - SAK - SAK - AnyCPU;x64 - Debug;Release; - Haiping Chen SciSharp STACK - AI Bot Platform Builder + LL Application Framework - Open source AI Bot platform builder which is written in C# runs on .Net Core and is enterprise oriented. Integrated with multiple bot engines besides BotSharp bot engine. Modulized pipeline design make NLP tasks plugin easily. Abstract platform and NLP task, migrate existed chatbot from a platform into another platform perfectly through dump and restore. - - If you feel that this project is helpful to you, please Star on the project, we will be very grateful. + Open source LLM application framework to build scalable, flexible and robust AI system. git https://github.com/SciSharp/BotSharp - NLU, Chatbot, Bot, AI Bot, Artificial Intelligence + Chatbot, Bot, LLM, AI, ChatGPT, OpenAI Support dialogue status tracking. Since 2018 Haiping Chen https://github.com/SciSharp/BotSharp @@ -55,29 +44,6 @@ 1701;1702 - - - - - - - - - - - - - - - - - - - - - - - True diff --git a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs index a7f2763f..3df675e1 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs +++ b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs @@ -9,7 +9,7 @@ using BotSharp.Abstraction.Templating; using BotSharp.Core.Instructs; using BotSharp.Abstraction.Instructs; using BotSharp.Abstraction.Routing; -using BotSharp.Core.Routing.Handlers; +using System.Reflection; namespace BotSharp.Core; @@ -53,20 +53,7 @@ public static class BotSharpServiceCollectionExtensions services.AddSingleton((IServiceProvider x) => routingSettings); services.AddScoped(); - - // Register function callback - services.AddScoped(); - - // Register routing and handlers services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); if (myDatabaseSettings.Default == "FileRepository") { @@ -118,7 +105,30 @@ public static class BotSharpServiceCollectionExtensions config.Bind("PluginLoader", pluginSettings); var loader = new PluginLoader(services, config, pluginSettings); - loader.Load(); + loader.Load(assembly => + { + // Register routing handlers + var handlers = assembly.GetTypes() + .Where(x => x.IsClass) + .Where(x => x.GetInterface(nameof(IRoutingHandler)) != null) + .ToArray(); + + foreach (var handler in handlers) + { + services.AddScoped(typeof(IRoutingHandler), handler); + } + + // Register function callback + var functions = assembly.GetTypes() + .Where(x => x.IsClass) + .Where(x => x.GetInterface(nameof(IFunctionCallback)) != null) + .ToArray(); + + foreach (var function in functions) + { + services.AddScoped(typeof(IFunctionCallback), function); + } + }); services.AddSingleton(loader); } diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs index 05e0727a..02b793ad 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs @@ -1,6 +1,7 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; +using System.Drawing; namespace BotSharp.Core.Conversations.Services; @@ -93,9 +94,17 @@ public partial class ConversationService await hook.AfterCompletion(message); } - var agent = await _services.GetRequiredService().GetAgent(message.CurrentAgentId); + var routingSetting = _services.GetRequiredService(); + var agentName = routingSetting.RouterId == message.CurrentAgentId ? + routingSetting.RouterName : + (await _services.GetRequiredService().GetAgent(message.CurrentAgentId)).Name; - _logger.LogInformation($"[{agent?.Name ?? "Router"}] {message.Role}: {message.Content}"); +#if DEBUG + Console.WriteLine($"[{agentName}] {message.Role}: {message.Content}", Color.Pink); +#else + + _logger.LogInformation($"[{agentName}] {message.Role}: {message.Content}"); +#endif await onMessageReceived(message); diff --git a/src/Infrastructure/BotSharp.Core/CoreController.cs b/src/Infrastructure/BotSharp.Core/CoreController.cs deleted file mode 100644 index 1b3f2d76..00000000 --- a/src/Infrastructure/BotSharp.Core/CoreController.cs +++ /dev/null @@ -1,43 +0,0 @@ -using EntityFrameworkCore.BootKit; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace BotSharp.Core -{ - [Authorize] - [Produces("application/json")] - [Route("v1/[controller]")] - public class CoreController : ControllerBase - { - protected Database dc { get; set; } - - public CoreController() - { - dc = new DefaultDataContextLoader().GetDefaultDc(); - } - - /*protected string GetConfig(string path) - { - if (string.IsNullOrEmpty(path)) return String.Empty; - - return Database.Configuration.GetSection(path).Value; - } - - protected List> GetSection(string path) - { - return Database.Configuration.GetSection(path).AsEnumerable().ToList(); - }*/ - - protected string CurrentUserId - { - get - { - return this.User.Claims.FirstOrDefault(x => x.Type.Equals("UserId")).Value; - } - } - } -} diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/PluginLoader.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/PluginLoader.cs index 31011a3a..bd14a827 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/PluginLoader.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/PluginLoader.cs @@ -22,7 +22,7 @@ public class PluginLoader _settings = settings; } - public void Load() + public void Load(Action loaded) { var executingDir = Directory.GetParent(Assembly.GetEntryAssembly().Location).FullName; @@ -44,6 +44,7 @@ public class PluginLoader Console.WriteLine($"Loaded plugin {module.GetType().Name} from {assemblyName}.", Color.Green); } + loaded(assembly); _modules.AddRange(modules); } else diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs index cead4db4..7c881193 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Repositories; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; @@ -11,11 +12,11 @@ public class ContinueExecuteTaskRoutingHandler : RoutingHandlerBase, IRoutingHan public string Description => "Continue to execute user's request without further information retrival."; - public List Parameters => new List + public List Parameters => new List { - "agent_name: the name of the agent", - "args: required parameters extracted from question", - "reason: why continue to execute current task" + new NameDesc("agent_name", "the name of the agent"), + new NameDesc("args", "required parameters extracted from question"), + new NameDesc("reason", "why continue to execute current task") }; public bool IsReasoning => true; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs index d1343f87..35041d27 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; @@ -10,8 +11,9 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler public string Description => "Call this function when user wants to end this conversation or all tasks have been completed."; - public List Parameters => new List + public List Parameters => new List { + new NameDesc("reason", "why this conversation is end") }; public bool IsReasoning => false; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/GetNextInstructionRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/GetNextInstructionRoutingHandler.cs index fa220139..10eafb22 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/GetNextInstructionRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/GetNextInstructionRoutingHandler.cs @@ -10,8 +10,6 @@ public class GetNextInstructionRoutingHandler : RoutingHandlerBase, IRoutingHand public string Description => ""; - public List Parameters => new List { }; - public bool IsReasoning => false; public GetNextInstructionRoutingHandler(IServiceProvider services, ILogger logger, RoutingSettings settings) diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs index 7dd56d0c..7669982d 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; @@ -10,10 +11,10 @@ public class InterruptTaskExecutionRoutingHandler : RoutingHandlerBase, IRouting public string Description => "Can't continue user's request becauase the requirements are not met."; - public List Parameters => new List + public List Parameters => new List { - "reason: the reason why the request is interrupted", - "answer: the content response to user" + new NameDesc("reason", "the reason why the request is interrupted"), + new NameDesc("answer", "the content response to user") }; public bool IsReasoning => true; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs index c108d53b..41d7d874 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; @@ -10,10 +11,10 @@ public class ResponseToUserRoutingHandler : RoutingHandlerBase, IRoutingHandler public string Description => "You know how to response according to the context, don't need to ask specific agent."; - public List Parameters => new List + public List Parameters => new List { - "answer: the content of response", - "reason: why response to user" + new NameDesc("answer", "the content of response"), + new NameDesc("reason", "why response to user") }; public bool IsReasoning => false; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs index f90ef5b0..440e2b0a 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Repositories; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; @@ -11,12 +12,12 @@ public class RetrieveDataFromAgentRoutingHandler : RoutingHandlerBase, IRoutingH public string Description => "Retrieve data from appropriate agent."; - public List Parameters => new List + public List Parameters => new List { - "agent_name: the name of the agent", - "question: the question you will ask the agent to get the necessary data", - "reason: why retrieve data", - "args: required parameters extracted from question and hand over to the next agent" + new NameDesc("agent_name", "the name of the agent"), + new NameDesc("question", "the question you will ask the agent to get the necessary data"), + new NameDesc("reason", "why retrieve data"), + new NameDesc("args", "required parameters extracted from question and hand over to the next agent") }; public bool IsReasoning => true; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index e503c39a..df3173ca 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Functions; using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Models; using BotSharp.Abstraction.Routing.Settings; @@ -12,11 +13,11 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler public string Description => "Route request to appropriate agent."; - public List Parameters => new List + public List Parameters => new List { - "agent_name: the name of the agent from AGENTS", - "reason: why route to this agent", - "args: parameters extracted from context" + new NameDesc("agent_name", "the name of the agent from AGENTS"), + new NameDesc("reason", "why route to this agent"), + new NameDesc("args", "parameters extracted from context") }; public bool IsReasoning => false; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs index 4a7cbba7..607762bf 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; @@ -10,9 +11,9 @@ public class TaskEndRoutingHandler : RoutingHandlerBase, IRoutingHandler public string Description => "Call this function when current task is completed."; - public List Parameters => new List + public List Parameters => new List { - "abandoned_arguments: the arguments next task can't reuse" + new NameDesc("abandoned_arguments", "the arguments next task can't reuse") }; public bool IsReasoning => true; diff --git a/src/Infrastructure/BotSharp.Core/Routing/PromptConst.cs b/src/Infrastructure/BotSharp.Core/Routing/PromptConst.cs deleted file mode 100644 index 3d8d3f26..00000000 --- a/src/Infrastructure/BotSharp.Core/Routing/PromptConst.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace BotSharp.Core.Routing; - -public class PromptConst -{ - public const string ROUTER_PROMPT = @" -You're a Router with reasoning. Follow these steps to handle user's request: -1. Read the CONVERSATION context. -2. Select a appropriate function from FUNCTIONS. -3. Determine which agent from AGENTS is suitable for the current task. - -FUNCTIONS -{% for fn in routing_handlers %} -* {{ fn.name }} -{{ fn.description }} -{% if fn.parameters != empty -%} -Parameters: -{% for arg in fn.parameters -%} -{{ arg }}; -{%- endfor %} -{%- endif %} -{% endfor %} - -AGENTS -{% for agent in routing_records %} -* {{ agent.name }} -{{ agent.description }} -{% if agent.required_fields != empty -%} -Required: {% for field in agent.required_fields %}{{ field }},{% endfor %} -{%- endif %} -{% endfor %} - -CONVERSATION"; -} diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs index af40105b..e7b800bc 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs @@ -5,7 +5,6 @@ using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Models; using BotSharp.Abstraction.Routing.Settings; using BotSharp.Abstraction.Templating; - namespace BotSharp.Core.Routing; public class RoutingService : IRoutingService @@ -113,8 +112,38 @@ public class RoutingService : IRoutingService }; var agents = db.Agents.Where(x => !x.Disabled && x.AllowRouting).ToArray(); - var dict = new Dictionary(); - dict["routing_records"] = agents.Select(x => new RoutingItem + // Assemble prompt + var prompt = @"You're a Router with reasoning. Follow these steps to handle user's request: +1. Read the CONVERSATION context. +2. Select a appropriate function from FUNCTIONS. +3. Determine which agent from AGENTS is suitable for the current task."; + + // Append function + prompt += "\r\n"; + prompt += "\r\nFUNCTIONS"; + GetHandlers().Select((handler, i) => + { + prompt += "\r\n"; + prompt += $"\r\n{i + 1}. {handler.Name}"; + prompt += $"\r\n{handler.Description}"; + + // Append parameters + if (handler.Parameters.Any()) + { + prompt += "\r\nParameters:"; + handler.Parameters.Select((p, i) => + { + prompt += $"\r\n{i + 1}. {p.Name}: {p.Description}"; + return p; + }).ToList(); + } + + return handler; + }).ToList(); + + prompt += "\r\n"; + prompt += "\r\nAGENTS"; + agents.Select(x => new RoutingItem { AgentId = x.Id, Description = x.Description, @@ -122,12 +151,23 @@ public class RoutingService : IRoutingService RequiredFields = x.RoutingRules.Where(x => x.Required) .Select(x => x.Field) .ToArray() - }).ToArray(); + }).Select((agent, i) => + { + prompt += "\r\n"; + prompt += $"\r\n{i + 1}. {agent.Name}"; + prompt += $"\r\n{agent.Description}"; - dict["routing_handlers"] = GetHandlers(); + // Append parameters + if (agent.RequiredFields.Any()) + { + prompt += $"\r\nRequired: {string.Join(',', agent.RequiredFields)}."; + } + return agent; + }).ToList(); - var render = _services.GetRequiredService(); - router.Instruction = render.Render(PromptConst.ROUTER_PROMPT, dict); + prompt += "\r\n"; + prompt += "\r\nCONVERSATION"; + router.Instruction = prompt; return router; } diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/BotSharp.Plugin.AzureOpenAI.csproj b/src/Plugins/BotSharp.Plugin.AzureOpenAI/BotSharp.Plugin.AzureOpenAI.csproj index 2fdd480e..fbe81da8 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/BotSharp.Plugin.AzureOpenAI.csproj +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/BotSharp.Plugin.AzureOpenAI.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/Plugins/BotSharp.Plugin.HuggingFace/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.HuggingFace/Providers/ChatCompletionProvider.cs index 4e39ff7b..cefdd632 100644 --- a/src/Plugins/BotSharp.Plugin.HuggingFace/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.HuggingFace/Providers/ChatCompletionProvider.cs @@ -39,10 +39,10 @@ public class ChatCompletionProvider : IChatCompletion var api = _services.GetRequiredService(); - if (_settings.Model.Contains('/')) + if (_model.Contains('/')) { - var space = _settings.Model.Split('/')[0]; - var model = _settings.Model.Split("/")[1]; + var space = _model.Split('/')[0]; + var model = _model.Split("/")[1]; var response = await api.Post(space, model, new InferenceInput { diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj b/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj index acbfa4fd..ae5411a4 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Plugins/BotSharp.Plugin.WeChat/BotSharp.Plugin.WeChat.csproj b/src/Plugins/BotSharp.Plugin.WeChat/BotSharp.Plugin.WeChat.csproj index fbff2484..d6f25157 100644 --- a/src/Plugins/BotSharp.Plugin.WeChat/BotSharp.Plugin.WeChat.csproj +++ b/src/Plugins/BotSharp.Plugin.WeChat/BotSharp.Plugin.WeChat.csproj @@ -21,7 +21,6 @@ - diff --git a/src/Plugins/BotSharp.Plugin.WeChat/WeChatPlugin.cs b/src/Plugins/BotSharp.Plugin.WeChat/WeChatPlugin.cs index b81d8ea4..806b03e5 100644 --- a/src/Plugins/BotSharp.Plugin.WeChat/WeChatPlugin.cs +++ b/src/Plugins/BotSharp.Plugin.WeChat/WeChatPlugin.cs @@ -6,18 +6,12 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Senparc.CO2NET.AspNet; using Senparc.CO2NET; -using Senparc.Weixin.RegisterServices; -using System; -using System.Collections.Generic; -using System.Text; using Senparc.Weixin; using Senparc.Weixin.MP; using Senparc.Weixin.MP.MessageHandlers.Middleware; using Senparc.Weixin.Entities; using Senparc.CO2NET.RegisterServices; using Microsoft.Extensions.Logging; -using Microsoft.AspNetCore.Http; -using BotSharp.Abstraction.Users; using BotSharp.Plugin.WeChat.Users; namespace BotSharp.Plugin.WeChat diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index 2e0ed4a0..79f2fae8 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -18,6 +18,7 @@ "RouterName": "PizzaBot", "Description": "Pizza restaurant AI Bot", "EnableReasoning": false, + "Provider": "azure-openai", "Model": "gpt-3.5" },