diff --git a/.gitignore b/.gitignore index cb5e824e..ab28c2e0 100644 --- a/.gitignore +++ b/.gitignore @@ -286,6 +286,10 @@ __pycache__/ /docs/_build *.bin -/src/WebStarter/data/conversations +src/WebStarter/Properties/PublishProfiles +src/WebStarter/Properties/ServiceDependencies XMLs logs +wwwroot +appsettings.Production.json +*.csproj.user \ No newline at end of file diff --git a/BotSharp.sln b/BotSharp.sln index e161ed0d..0c99deee 100644 --- a/BotSharp.sln +++ b/BotSharp.sln @@ -81,6 +81,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.HttpHandler EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.SqlDriver", "src\Plugins\BotSharp.Plugin.SqlDriver\BotSharp.Plugin.SqlDriver.csproj", "{D775DB67-A4B4-44E5-9144-522689590057}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.Dashboard", "src\Plugins\BotSharp.Plugin.Dashboard\BotSharp.Plugin.Dashboard.csproj", "{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -313,6 +315,14 @@ Global {D775DB67-A4B4-44E5-9144-522689590057}.Release|Any CPU.Build.0 = Release|Any CPU {D775DB67-A4B4-44E5-9144-522689590057}.Release|x64.ActiveCfg = Release|Any CPU {D775DB67-A4B4-44E5-9144-522689590057}.Release|x64.Build.0 = Release|Any CPU + {267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Debug|x64.ActiveCfg = Debug|Any CPU + {267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Debug|x64.Build.0 = Debug|Any CPU + {267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Release|Any CPU.Build.0 = Release|Any CPU + {267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Release|x64.ActiveCfg = Release|Any CPU + {267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -353,6 +363,7 @@ Global {5CA3335E-E6AD-46FD-B277-29BBC3A16500} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749} {32D9E720-6FE6-4F29-94B1-B10B05BFAD75} = {51AFE054-AE99-497D-A593-69BAEFB5106F} {D775DB67-A4B4-44E5-9144-522689590057} = {51AFE054-AE99-497D-A593-69BAEFB5106F} + {267998C1-55C2-4ADC-8361-2CDFA5EA6D6C} = {51AFE054-AE99-497D-A593-69BAEFB5106F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19} diff --git a/README.md b/README.md index 12541290..aa892ce0 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ BotSharp uses component design, the kernel is kept to a minimum, and business fu #### Tools - BotSharp.Plugin.RoutingSpeeder +- BotSharp.Plugin.WebDriver - BotSharp.Plugin.PizzaBot #### UIs diff --git a/docs/static/screenshots/agent-builder-agents.png b/docs/static/screenshots/agent-builder-agents.png index 5f8643a9..db661494 100644 Binary files a/docs/static/screenshots/agent-builder-agents.png and b/docs/static/screenshots/agent-builder-agents.png differ diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs index 0fdeffe3..81aacb85 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs @@ -8,6 +8,7 @@ public enum AgentField IsPublic, Disabled, Type, + InheritAgentId, Profiles, RoutingRule, Instruction, diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs index a36ccc26..68e636b8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs @@ -33,7 +33,8 @@ public class Agent /// Templates /// [JsonIgnore] - public List? Templates { get; set; } + public List Templates { get; set; } + = new List(); /// /// Samples @@ -46,7 +47,8 @@ public class Agent /// Functions /// [JsonIgnore] - public List Functions { get; set; } = new List(); + public List Functions { get; set; } + = new List(); /// /// Responses @@ -62,9 +64,6 @@ public class Agent public bool IsPublic { get; set; } - [JsonIgnore] - public bool IsHost { get; set; } - [JsonIgnore] public PluginDef Plugin { get; set; } @@ -83,6 +82,11 @@ public class Agent public List Profiles { get; set; } = new List(); + /// + /// Inherit from agent + /// + public string? InheritAgentId { get; set; } + public List RoutingRules { get; set; } = new List(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs index d41a8831..0e1d4787 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs @@ -13,6 +13,7 @@ public interface IConversationService Task UpdateConversationTitle(string id, string title); Task> GetLastConversations(); Task DeleteConversation(string id); + Task TruncateConversation(string conversationId, string messageId); /// /// Send message to LLM diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/TruncateMessageRequest.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/TruncateMessageRequest.cs new file mode 100644 index 00000000..088697cd --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/TruncateMessageRequest.cs @@ -0,0 +1,6 @@ +namespace BotSharp.Abstraction.Conversations.Models; + +public class TruncateMessageRequest +{ + public string? TruncateMessageId { get; set; } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs b/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs index 95d72492..438cc060 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs @@ -1,6 +1,6 @@ namespace BotSharp.Abstraction.Models; -public class MessageConfig +public class MessageConfig : TruncateMessageRequest { /// /// Completion Provider diff --git a/src/Infrastructure/BotSharp.Abstraction/Plugins/PluginDependencyAttribute.cs b/src/Infrastructure/BotSharp.Abstraction/Plugins/PluginDependencyAttribute.cs new file mode 100644 index 00000000..7b5e93cb --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Plugins/PluginDependencyAttribute.cs @@ -0,0 +1,11 @@ +namespace BotSharp.Abstraction.Plugins; + +public class PluginDependencyAttribute : Attribute +{ + public string[] PluginNames { get; set; } + + public PluginDependencyAttribute(params string[] pluginNames) + { + PluginNames = pluginNames; + } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index cd800cf9..5ca241e6 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -46,8 +46,11 @@ public interface IBotSharpRepository PagedItems GetConversations(ConversationFilter filter); void UpdateConversationTitle(string conversationId, string title); List GetLastConversations(); + bool TruncateConversation(string conversationId, string messageId); + #endregion + #region Statistics + void IncrementConversationCount(); #endregion - #region Execution Log void AddExecutionLogs(string conversationId, List logs); List GetExecutionLogs(string conversationId); diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingRule.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingRule.cs index b652ced1..b0353ce6 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingRule.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingRule.cs @@ -26,7 +26,7 @@ public class RoutingRule public override string ToString() { - return $"{AgentName} {Field}"; + return $"{Type} {AgentName} {Field}"; } public RoutingRule() diff --git a/src/Infrastructure/BotSharp.Abstraction/Planning/IExecutor.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Planning/IExecutor.cs similarity index 57% rename from src/Infrastructure/BotSharp.Abstraction/Planning/IExecutor.cs rename to src/Infrastructure/BotSharp.Abstraction/Routing/Planning/IExecutor.cs index 187fcfcc..c8bffe6c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Planning/IExecutor.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Planning/IExecutor.cs @@ -1,11 +1,10 @@ using BotSharp.Abstraction.Functions.Models; -using BotSharp.Abstraction.Routing; -namespace BotSharp.Abstraction.Planning; +namespace BotSharp.Abstraction.Routing.Planning; public interface IExecutor { - Task Execute(IRoutingService routing, + Task Execute(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message, List dialogs); diff --git a/src/Infrastructure/BotSharp.Abstraction/Planning/IPlaner.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Planning/IPlaner.cs similarity index 90% rename from src/Infrastructure/BotSharp.Abstraction/Planning/IPlaner.cs rename to src/Infrastructure/BotSharp.Abstraction/Routing/Planning/IPlaner.cs index a6136ea8..4053f81c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Planning/IPlaner.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Planning/IPlaner.cs @@ -1,6 +1,6 @@ using BotSharp.Abstraction.Functions.Models; -namespace BotSharp.Abstraction.Planning; +namespace BotSharp.Abstraction.Routing.Planning; /// /// Task breakdown and execution plan diff --git a/src/Infrastructure/BotSharp.Abstraction/Statistics/Model/Statistics.cs b/src/Infrastructure/BotSharp.Abstraction/Statistics/Model/Statistics.cs new file mode 100644 index 00000000..5f4f1e5c --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Statistics/Model/Statistics.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Abstraction.Statistics.Model +{ + public class Statistics + { + public string Id { get; set; } = string.Empty; + public int ConversationCount { get; set; } + public DateTime UpdatedDateTime { get; set; } + } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Statistics/Settings/StatisticsSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Statistics/Settings/StatisticsSettings.cs new file mode 100644 index 00000000..2758dfc3 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Statistics/Settings/StatisticsSettings.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Abstraction.Statistics.Settings +{ + public class StatisticsSettings + { + public string DataDir { get; set; } + } +} diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs index ce74d7c4..01ca0c03 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs @@ -107,9 +107,9 @@ public partial class AgentService foreach (var file in Directory.GetFiles(templateDir)) { var fileName = file.Split(Path.DirectorySeparatorChar).Last(); - var splits = fileName.ToLower().Split('.'); - var name = splits[0]; - var extension = splits[1]; + var splitIdx = fileName.LastIndexOf("."); + var name = fileName.Substring(0, splitIdx); + var extension = fileName.Substring(splitIdx + 1); if (extension.IsEqualTo(_agentSettings.TemplateFormat)) { var content = File.ReadAllText(file); diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs index 15be18f9..6f840edb 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs @@ -13,20 +13,12 @@ public partial class AgentService { var agents = _db.GetAgents(filter); - // Set IsRouter var routeSetting = _services.GetRequiredService(); foreach (var agent in agents) { agent.Plugin = GetPlugin(agent.Id); } - // Set IsHost - var agentSetting = _services.GetRequiredService(); - foreach (var agent in agents) - { - agent.IsHost = agentSetting.HostAgentId == agent.Id; - } - agents = agents.Where(x => x.Installed).ToList(); var pager = filter?.Pager ?? new Pagination(); return new PagedItems diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs index ab40b134..a6910603 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs @@ -32,6 +32,27 @@ public partial class AgentService throw new Exception($"Can't load agent by id: {id}"); } + if (agent.InheritAgentId != null) + { + var inheritedAgent = await GetAgent(agent.InheritAgentId); + agent.Templates.AddRange(inheritedAgent.Templates + // exclude private template + .Where(x => !x.Name.StartsWith(".")) + // exclude duplicate name + .Where(x => !agent.Templates.Exists(t => t.Name == x.Name))); + + agent.Functions.AddRange(inheritedAgent.Functions + // exclude private template + .Where(x => !x.Name.StartsWith(".")) + // exclude duplicate name + .Where(x => !agent.Functions.Exists(t => t.Name == x.Name))); + + if (agent.Instruction == null) + { + agent.Instruction = inheritedAgent.Instruction; + } + } + agent.TemplateDict = new Dictionary(); // Populate state into dictionary diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index fadeacd1..8e79687f 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -50,11 +50,15 @@ + - + + + + @@ -83,7 +87,19 @@ PreserveNewest - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + PreserveNewest diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs b/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs index 00d55555..13885fec 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs @@ -1,12 +1,12 @@ using BotSharp.Abstraction.Instructs; using BotSharp.Abstraction.Messaging; -using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Plugins.Models; +using BotSharp.Abstraction.Routing.Planning; using BotSharp.Abstraction.Settings; using BotSharp.Abstraction.Templating; using BotSharp.Core.Instructs; using BotSharp.Core.Messaging; -using BotSharp.Core.Planning; +using BotSharp.Core.Routing.Planning; using BotSharp.Core.Templating; using Microsoft.Extensions.Configuration; diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.TruncateMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.TruncateMessage.cs new file mode 100644 index 00000000..ca2719d3 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.TruncateMessage.cs @@ -0,0 +1,13 @@ +using BotSharp.Abstraction.Repositories; + +namespace BotSharp.Core.Conversations.Services; + +public partial class ConversationService : IConversationService +{ + public async Task TruncateConversation(string conversationId, string messageId) + { + var db = _services.GetRequiredService(); + var isSaved = db.TruncateConversation(conversationId, messageId); + return await Task.FromResult(isSaved); + } +} diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderPlugin.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderPlugin.cs index 469447a2..74f1aa83 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderPlugin.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderPlugin.cs @@ -21,10 +21,11 @@ public class LlmProviderPlugin : IBotSharpPlugin services.AddScoped(provider => { var settingService = provider.GetRequiredService(); + var loger = provider.GetRequiredService>(); var llmProviders = settingService.Bind>("LlmProviders"); foreach (var llmProvider in llmProviders) { - Console.WriteLine($"Loaded LlmProvider {llmProvider.Provider} settings with {llmProvider.Models.Count} models."); + loger.LogInformation($"Loaded LlmProvider {llmProvider.Provider} settings with {llmProvider.Models.Count} models."); } return llmProviders; }); diff --git a/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs b/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs index ccab8874..d8a9a1bb 100644 --- a/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs +++ b/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs @@ -16,6 +16,14 @@ public partial class InstructService : IInstructService _logger = logger; } + /// + /// Execute completion by using specified instruction or template + /// + /// Agent (static agent) + /// Additional message provided by user + /// Template name + /// System prompt + /// public async Task Execute(string agentId, RoleDialogModel message, string? templateName = null, string? instruction = null) { var agentService = _services.GetRequiredService(); diff --git a/src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs b/src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs index 0d54f4af..0932041d 100644 --- a/src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs +++ b/src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs @@ -27,12 +27,17 @@ public class PluginLoader _settings = settings; } - public void Load(Action loaded) + public void Load(Action loaded, string? plugin = null) { _executingDir = Directory.GetParent(Assembly.GetEntryAssembly().Location).FullName; _settings.Assemblies.ToList().ForEach(assemblyName => { + if (plugin != null && plugin != assemblyName) + { + return; + } + var assemblyPath = Path.Combine(_executingDir, assemblyName + ".dll"); if (File.Exists(assemblyPath)) { @@ -45,38 +50,66 @@ public class PluginLoader foreach (var module in modules) { - module.RegisterDI(_services, _config); - // string classSummary = GetSummaryComment(module.GetType()); - var name = string.IsNullOrEmpty(module.Name) ? module.GetType().Name : module.Name; - _modules.Add(module); - _plugins.Add(new PluginDef + if (_plugins.Exists(x => x.Id == module.Id)) { - Id = module.Id, - Name = name, - Module = module, - Description = module.Description, - Assembly = assemblyName, - IconUrl = module.IconUrl, - AgentIds = module.AgentIds - }); - Console.Write($"Loaded plugin "); - Console.Write(name, Color.Green); - Console.WriteLine($" from {assemblyName}."); - if (!string.IsNullOrEmpty(module.Description)) - { - Console.WriteLine(module.Description); + continue; } + + // Solve plugin dependency + var attr = module.GetType().GetCustomAttribute(); + if (attr != null) + { + foreach (var plugin in attr.PluginNames) + { + if (!_plugins.Any(x => x.Assembly == plugin)) + { + Load(loaded, plugin); + } + + if (!_plugins.Any(x => x.Assembly == plugin)) + { + Console.WriteLine($"Load dependent plugin {plugin} failed by {module.Name}.", Color.Red); + } + } + } + + InitModule(assemblyName, module); } loaded(assembly); } else { - Console.WriteLine($"Can't find assemble {assemblyPath}."); + Console.WriteLine($"Can't find assemble {assemblyPath}.", Color.Red); } }); } + private void InitModule(string assembly, IBotSharpPlugin module) + { + module.RegisterDI(_services, _config); + // string classSummary = GetSummaryComment(module.GetType()); + var name = string.IsNullOrEmpty(module.Name) ? module.GetType().Name : module.Name; + _modules.Add(module); + _plugins.Add(new PluginDef + { + Id = module.Id, + Name = name, + Module = module, + Description = module.Description, + Assembly = assembly, + IconUrl = module.IconUrl, + AgentIds = module.AgentIds + }); + Console.Write($"Loaded plugin "); + Console.Write(name, Color.Green); + Console.WriteLine($" from {assembly}."); + if (!string.IsNullOrEmpty(module.Description)) + { + Console.WriteLine(module.Description); + } + } + public List GetPlugins(IServiceProvider services) { // Apply user configurations @@ -124,6 +157,13 @@ public class PluginLoader var agent = agentService.LoadAgent(agentId).Result; agent.Disabled = false; agentService.UpdateAgent(agent, AgentField.Disabled); + + if (agent.InheritAgentId != null) + { + agent = agentService.LoadAgent(agent.InheritAgentId).Result; + agent.Disabled = false; + agentService.UpdateAgent(agent, AgentField.Disabled); + } } } else diff --git a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs index c8b75e7e..8adf711a 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs @@ -178,8 +178,18 @@ public class BotSharpDbContext : Database, IBotSharpRepository { throw new NotImplementedException(); } - #endregion + public bool TruncateConversation(string conversationId, string messageId) + { + throw new NotImplementedException(); + } + #endregion + #region Stats + public void IncrementConversationCount() + { + throw new NotImplementedException(); + } + #endregion #region User public User? GetUserByEmail(string email) diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs index b2476921..c9aebd1e 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs @@ -31,6 +31,9 @@ namespace BotSharp.Core.Repository case AgentField.Type: UpdateAgentType(agent.Id, agent.Type); break; + case AgentField.InheritAgentId: + UpdateAgentInheritAgentId(agent.Id, agent.InheritAgentId); + break; case AgentField.Profiles: UpdateAgentProfiles(agent.Id, agent.Profiles); break; @@ -123,6 +126,17 @@ namespace BotSharp.Core.Repository File.WriteAllText(agentFile, json); } + private void UpdateAgentInheritAgentId(string agentId, string? inheritAgentId) + { + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + agent.InheritAgentId = inheritAgentId; + agent.UpdatedDateTime = DateTime.UtcNow; + var json = JsonSerializer.Serialize(agent, _options); + File.WriteAllText(agentFile, json); + } + private void UpdateAgentProfiles(string agentId, List profiles) { if (profiles.IsNullOrEmpty()) return; @@ -379,9 +393,9 @@ namespace BotSharp.Core.Repository foreach (var file in Directory.GetFiles(dir)) { var fileName = file.Split(Path.DirectorySeparatorChar).Last(); - var splits = ParseFileNameByPath(fileName.ToLower()); - var name = splits[0]; - var extension = splits[1]; + var splitIdx = fileName.LastIndexOf("."); + var name = fileName.Substring(0, splitIdx); + var extension = fileName.Substring(splitIdx + 1); if (name.IsEqualTo(templateName) && extension.IsEqualTo(_agentSettings.TemplateFormat)) { return File.ReadAllText(file); diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs index 76122be6..8131bdd2 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Repositories.Models; +using System.Globalization; using System.IO; namespace BotSharp.Core.Repository @@ -256,6 +257,35 @@ namespace BotSharp.Core.Repository } + public bool TruncateConversation(string conversationId, string messageId) + { + if (string.IsNullOrEmpty(conversationId) || string.IsNullOrEmpty(messageId)) return false; + + var dialogs = new List(); + var convDir = FindConversationDirectory(conversationId); + if (string.IsNullOrEmpty(convDir)) return false; + + var dialogDir = Path.Combine(convDir, DIALOG_FILE); + dialogs = CollectDialogElements(dialogDir); + if (dialogs.IsNullOrEmpty()) return false; + + var foundIdx = dialogs.FindIndex(x => x.MetaData?.MessageId == messageId); + if (foundIdx < 0) return false; + + // Handle truncated dialogs + var isSaved = HandleTruncatedDialogs(dialogDir, dialogs, foundIdx); + if (!isSaved) return false; + + // Handle truncated states + var refTime = dialogs.ElementAt(foundIdx).MetaData.CreateTime; + var stateDir = Path.Combine(convDir, STATE_FILE); + var states = CollectConversationStates(stateDir); + isSaved = HandleTruncatedStates(stateDir, states, refTime); + + return isSaved; + } + + #region Private methods private string? FindConversationDirectory(string conversationId) { @@ -304,8 +334,9 @@ namespace BotSharp.Core.Repository foreach (var element in dialogs) { var meta = element.MetaData; + var createTime = meta.CreateTime.ToString("MM/dd/yyyy hh:mm:ss.fff tt", CultureInfo.InvariantCulture); var source = meta.FunctionName ?? meta.SenderId; - var metaStr = $"{meta.CreateTime}|{meta.Role}|{meta.AgentId}|{meta.MessageId}|{source}"; + var metaStr = $"{createTime}|{meta.Role}|{meta.AgentId}|{meta.MessageId}|{source}"; dialogTexts.Add(metaStr); var content = $" - {element.Content}"; dialogTexts.Add(content); @@ -325,6 +356,49 @@ namespace BotSharp.Core.Repository states = JsonSerializer.Deserialize>(stateStr, _options); return states ?? new List(); } + + private bool HandleTruncatedDialogs(string dialogDir, List dialogs, int foundIdx) + { + var truncatedDialogs = dialogs.Where((x, idx) => idx < foundIdx).ToList(); + var isSaved = SaveTruncatedDialogs(dialogDir, truncatedDialogs); + return isSaved; + } + + private bool HandleTruncatedStates(string stateDir, List states, DateTime refTime) + { + var truncatedStates = new List(); + foreach (var state in states) + { + var values = state.Values.Where(x => x.UpdateTime < refTime).ToList(); + if (values.Count == 0) continue; + + state.Values = values; + truncatedStates.Add(state); + } + + var isSaved = SaveTruncatedStates(stateDir, truncatedStates); + return isSaved; + } + + private bool SaveTruncatedDialogs(string dialogDir, List dialogs) + { + if (string.IsNullOrEmpty(dialogDir) || dialogs == null) return false; + if (!File.Exists(dialogDir)) File.Create(dialogDir); + + var texts = ParseDialogElements(dialogs); + File.WriteAllLines(dialogDir, texts); + return true; + } + + private bool SaveTruncatedStates(string stateDir, List states) + { + if (string.IsNullOrEmpty(stateDir) || states == null) return false; + if (!File.Exists(stateDir)) File.Create(stateDir); + + var stateStr = JsonSerializer.Serialize(states, _options); + File.WriteAllText(stateDir, stateStr); + return true; + } #endregion } } diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Stats.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Stats.cs new file mode 100644 index 00000000..b9c3b664 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Stats.cs @@ -0,0 +1,57 @@ +using BotSharp.Abstraction.Statistics.Model; +using System.IO; + +namespace BotSharp.Core.Repository +{ + public partial class FileRepository + { + public void IncrementConversationCount() + { + var statsFileDirectory = FindCurrentStatsDirectory(); + if (statsFileDirectory == null) + { + statsFileDirectory = CreateStatsFileDirectory(); + } + var fileName = GenerateStatsFileName(); + var statsFile = Path.Combine(statsFileDirectory, fileName); + if (!File.Exists(statsFile)) + { + File.WriteAllText(statsFile, JsonSerializer.Serialize(new Statistics() + { + Id = Guid.NewGuid().ToString(), + UpdatedDateTime = DateTime.UtcNow + }, _options)); + } + var json = File.ReadAllText(statsFile); + var stats = JsonSerializer.Deserialize(json, _options); + stats.ConversationCount += 1; + stats.UpdatedDateTime = DateTime.UtcNow; + File.WriteAllText(statsFile, JsonSerializer.Serialize(stats, _options)); + } + public string? CreateStatsFileDirectory() + { + var dir = GenerateStatsDirectoryName(); + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + return dir; + } + private string? FindCurrentStatsDirectory() + { + var dir = GenerateStatsDirectoryName(); + if (!Directory.Exists(dir)) return null; + + return dir; + } + private string GenerateStatsDirectoryName() + { + return Path.Combine(_dbSettings.FileRepository, _statisticsSetting.DataDir, DateTime.UtcNow.Year.ToString(), DateTime.UtcNow.ToString("MM")); + } + private string GenerateStatsFileName() + { + var fileName = DateTime.UtcNow.ToString("MMdd"); + return $"{fileName}-{STATS_FILE}"; + } + } +} diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs index 6874ed02..cca7d2e7 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs @@ -11,6 +11,7 @@ using BotSharp.Abstraction.Routing.Settings; using BotSharp.Abstraction.Evaluations.Settings; using System.Text.Encodings.Web; using BotSharp.Abstraction.Plugins.Models; +using BotSharp.Abstraction.Statistics.Settings; namespace BotSharp.Core.Repository; @@ -20,6 +21,7 @@ public partial class FileRepository : IBotSharpRepository private readonly BotSharpDatabaseSettings _dbSettings; private readonly AgentSettings _agentSettings; private readonly ConversationSetting _conversationSettings; + private readonly StatisticsSettings _statisticsSetting; private JsonSerializerOptions _options; private const string AGENT_FILE = "agent.json"; @@ -29,6 +31,7 @@ public partial class FileRepository : IBotSharpRepository private const string USER_FILE = "user.json"; private const string USER_AGENT_FILE = "agents.json"; private const string CONVERSATION_FILE = "conversation.json"; + private const string STATS_FILE = "stats.json"; private const string DIALOG_FILE = "dialogs.txt"; private const string STATE_FILE = "state.json"; private const string EXECUTION_LOG_FILE = "execution.log"; @@ -38,12 +41,14 @@ public partial class FileRepository : IBotSharpRepository IServiceProvider services, BotSharpDatabaseSettings dbSettings, AgentSettings agentSettings, - ConversationSetting conversationSettings) + ConversationSetting conversationSettings, + StatisticsSettings statisticsSettings) { _services = services; _dbSettings = dbSettings; _agentSettings = agentSettings; _conversationSettings = conversationSettings; + _statisticsSetting = statisticsSettings; _options = new JsonSerializerOptions { @@ -176,10 +181,10 @@ public partial class FileRepository : IBotSharpRepository return (agent, agentFile); } - private string FetchInstruction(string fileDir) + private string? FetchInstruction(string fileDir) { var file = Path.Combine(fileDir, $"{AGENT_INSTRUCTION_FILE}.{_agentSettings.TemplateFormat}"); - if (!File.Exists(file)) return string.Empty; + if (!File.Exists(file)) return null; var instruction = File.ReadAllText(file); return instruction; @@ -212,9 +217,9 @@ public partial class FileRepository : IBotSharpRepository foreach (var file in Directory.GetFiles(templateDir)) { var fileName = file.Split(Path.DirectorySeparatorChar).Last(); - var splits = fileName.ToLower().Split('.'); - var name = string.Join('.', splits.Take(splits.Length - 1)); - var extension = splits.Last(); + var splitIdx = fileName.LastIndexOf("."); + var name = fileName.Substring(0, splitIdx); + var extension = fileName.Substring(splitIdx + 1); if (extension.Equals(_agentSettings.TemplateFormat, StringComparison.OrdinalIgnoreCase)) { var content = File.ReadAllText(file); diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs index 66fe6759..646dd481 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs @@ -4,7 +4,7 @@ using BotSharp.Abstraction.Repositories; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; -using BotSharp.Core.Planning; +using BotSharp.Core.Routing.Planning; namespace BotSharp.Core.Routing.Handlers; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs index 00068306..da58b98b 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs @@ -1,7 +1,7 @@ using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; -using BotSharp.Core.Planning; +using BotSharp.Core.Routing.Planning; namespace BotSharp.Core.Routing.Handlers; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs index 3e397089..54f3e66c 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs @@ -2,7 +2,7 @@ using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Models; using BotSharp.Abstraction.Routing.Settings; -using BotSharp.Core.Planning; +using BotSharp.Core.Routing.Planning; namespace BotSharp.Core.Routing.Handlers; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs index 0b299f25..5e431f84 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs @@ -1,7 +1,7 @@ using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; -using BotSharp.Core.Planning; +using BotSharp.Core.Routing.Planning; namespace BotSharp.Core.Routing.Handlers; diff --git a/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/HFPlanner.cs similarity index 97% rename from src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs rename to src/Infrastructure/BotSharp.Core/Routing/Planning/HFPlanner.cs index 8f4e0033..9cff003a 100644 --- a/src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/HFPlanner.cs @@ -1,12 +1,12 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Functions.Models; -using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Repositories; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Routing.Models; +using BotSharp.Abstraction.Routing.Planning; using BotSharp.Abstraction.Templating; -namespace BotSharp.Core.Planning; +namespace BotSharp.Core.Routing.Planning; /// /// Human feedback based planner diff --git a/src/Infrastructure/BotSharp.Core/Planning/InstructExecutor.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/InstructExecutor.cs similarity index 92% rename from src/Infrastructure/BotSharp.Core/Planning/InstructExecutor.cs rename to src/Infrastructure/BotSharp.Core/Routing/Planning/InstructExecutor.cs index 0d02cd95..0f436edd 100644 --- a/src/Infrastructure/BotSharp.Core/Planning/InstructExecutor.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/InstructExecutor.cs @@ -1,8 +1,8 @@ using BotSharp.Abstraction.Functions.Models; -using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Routing; +using BotSharp.Abstraction.Routing.Planning; -namespace BotSharp.Core.Planning; +namespace BotSharp.Core.Routing.Planning; public class InstructExecutor : IExecutor { diff --git a/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/NaivePlanner.cs similarity index 96% rename from src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs rename to src/Infrastructure/BotSharp.Core/Routing/Planning/NaivePlanner.cs index 78112559..fa4b20a0 100644 --- a/src/Infrastructure/BotSharp.Core/Planning/NaivePlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/NaivePlanner.cs @@ -1,11 +1,11 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Functions.Models; -using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Routing.Models; +using BotSharp.Abstraction.Routing.Planning; using BotSharp.Abstraction.Templating; -namespace BotSharp.Core.Planning; +namespace BotSharp.Core.Routing.Planning; public class NaivePlanner : IPlaner { @@ -32,7 +32,7 @@ public class NaivePlanner : IPlaner var completion = CompletionProvider.GetTextCompletion(_services);*/ // chat completion - var completion = CompletionProvider.GetChatCompletion(_services, + var completion = CompletionProvider.GetChatCompletion(_services, provider: router?.LlmConfig?.Provider, model: router?.LlmConfig?.Model); @@ -44,7 +44,7 @@ public class NaivePlanner : IPlaner { // text completion // text = await completion.GetCompletion(content, router.Id, messageId); - var dialogs = new List + var dialogs = new List { new RoleDialogModel(AgentRole.User, next) { @@ -91,7 +91,7 @@ public class NaivePlanner : IPlaner if (inst.UnmatchedAgent) { var unmatchedAgentId = context.GetCurrentAgentId(); - + // Exclude the wrong routed agent var agents = router.TemplateDict["routing_agents"] as RoutableAgent[]; router.TemplateDict["routing_agents"] = agents.Where(x => x.AgentId != unmatchedAgentId).ToArray(); @@ -123,8 +123,8 @@ public class NaivePlanner : IPlaner private void FixMalformedResponse(FunctionCallFromLlm args) { var agentService = _services.GetRequiredService(); - var agents = agentService.GetAgents(new AgentFilter - { + var agents = agentService.GetAgents(new AgentFilter + { Type = AgentType.Task }).Result.Items.ToList(); var malformed = false; diff --git a/src/Infrastructure/BotSharp.Core/Planning/SequentialPlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs similarity index 97% rename from src/Infrastructure/BotSharp.Core/Planning/SequentialPlanner.cs rename to src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs index 8f571266..1b24152a 100644 --- a/src/Infrastructure/BotSharp.Core/Planning/SequentialPlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs @@ -1,11 +1,11 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Functions.Models; -using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Models; +using BotSharp.Abstraction.Routing.Planning; using BotSharp.Abstraction.Templating; -namespace BotSharp.Core.Planning; +namespace BotSharp.Core.Routing.Planning; public class SequentialPlanner : IPlaner { @@ -91,7 +91,7 @@ public class SequentialPlanner : IPlaner context.Empty(); return false; } - + // Handover to Router; context.Pop(); diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs index 946e6057..677157d6 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs @@ -1,10 +1,9 @@ -using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Models; using BotSharp.Abstraction.Routing.Settings; using BotSharp.Abstraction.Settings; -using BotSharp.Core.Planning; using BotSharp.Core.Routing.Hooks; +using BotSharp.Core.Routing.Planning; using Microsoft.Extensions.Configuration; namespace BotSharp.Core.Routing; diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetPlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetPlanner.cs index 01de9a29..2d47f1ab 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetPlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetPlanner.cs @@ -1,7 +1,7 @@ using BotSharp.Abstraction.Agents.Models; -using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Routing.Enums; -using BotSharp.Core.Planning; +using BotSharp.Abstraction.Routing.Planning; +using BotSharp.Core.Routing.Planning; namespace BotSharp.Core.Routing; diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs index b94903af..8a34d684 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs @@ -1,10 +1,10 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Functions.Models; -using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Repositories; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Models; +using BotSharp.Abstraction.Routing.Planning; using BotSharp.Abstraction.Routing.Settings; using System.Drawing; diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01e2fc5c-2c89-4ec7-8470-7688608b496c/agent.json b/src/Infrastructure/BotSharp.Core/data/agents/01e2fc5c-2c89-4ec7-8470-7688608b496c/agent.json index b17531f4..536ca340 100644 --- a/src/Infrastructure/BotSharp.Core/data/agents/01e2fc5c-2c89-4ec7-8470-7688608b496c/agent.json +++ b/src/Infrastructure/BotSharp.Core/data/agents/01e2fc5c-2c89-4ec7-8470-7688608b496c/agent.json @@ -1,12 +1,11 @@ { "id": "01e2fc5c-2c89-4ec7-8470-7688608b496c", "name": "Chatbot", - "description": "AI chatbot that can do variaty of tasks", + "description": "Chatbot is used to test the performance of different large models and does not interact with external APIs.", "type": "task", "createdDateTime": "2024-01-15T10:39:32Z", "updatedDateTime": "2024-01-15T14:39:32Z", - "iconUrl": "/images/users/bot.png", + "iconUrl": "/images/logo.png", "disabled": false, - "isPublic": true, - "profiles": [ "standalone" ] + "isPublic": true } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/welcome.liquid b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/.welcome.liquid similarity index 100% rename from src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/welcome.liquid rename to src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/.welcome.liquid diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.sequential.liquid b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.sequential.liquid index a1025e50..32de085b 100644 --- a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.sequential.liquid +++ b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.sequential.liquid @@ -1,2 +1,2 @@ -In order to execute the instructions listed by the user in the order specified by the user. +In order to execute the listed instructions in the order specified by the user. What is the next step based on the CONVERSATION? \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json b/src/Infrastructure/BotSharp.Core/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json new file mode 100644 index 00000000..e9bac6f5 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json @@ -0,0 +1,11 @@ +{ + "id": "dfd9b46d-d00c-40af-8a75-3fbdc2b89869", + "name": "Evaluator", + "description": "Evaluate the performance of the LLM agents", + "createdDateTime": "2023-08-18T00:00:00Z", + "updatedDateTime": "2023-08-18T00:00:00Z", + "disabled": true, + "llmConfig": { + "model": "gpt-35-turbo-instruct" + } +} \ No newline at end of file diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/instruction.liquid b/src/Infrastructure/BotSharp.Core/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/instruction.liquid similarity index 100% rename from tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/instruction.liquid rename to src/Infrastructure/BotSharp.Core/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/instruction.liquid diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.executor.liquid b/src/Infrastructure/BotSharp.Core/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.executor.liquid similarity index 100% rename from tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.executor.liquid rename to src/Infrastructure/BotSharp.Core/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.executor.liquid diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.reviewer.liquid b/src/Infrastructure/BotSharp.Core/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.reviewer.liquid similarity index 100% rename from tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.reviewer.liquid rename to src/Infrastructure/BotSharp.Core/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.reviewer.liquid diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs index 9183be01..35873b9e 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs @@ -25,23 +25,37 @@ public class AgentController : ControllerBase [HttpGet("/agent/{id}")] public async Task GetAgent([FromRoute] string id) { - var agent = await _agentService.GetAgent(id); - return AgentViewModel.FromAgent(agent); + var agents = await GetAgents(new AgentFilter + { + AgentIds = new List { id } + }); + return agents.Items.First(); } - + [HttpGet("/agents")] public async Task> GetAgents([FromQuery] AgentFilter filter) { + var agentSetting = _services.GetRequiredService(); var pagedAgents = await _agentService.GetAgents(filter); + + // prerender agent var items = new List(); foreach (var agent in pagedAgents.Items) { var renderedAgent = await _agentService.LoadAgent(agent.Id); items.Add(renderedAgent); } + + // Set IsHost + var agents = items.Select(x => AgentViewModel.FromAgent(x)).ToList(); + foreach(var agent in agents) + { + agent.IsHost = agentSetting.HostAgentId == agent.Id; + } + return new PagedItems { - Items = items.Select(x => AgentViewModel.FromAgent(x)).ToList(), + Items = agents, Count = pagedAgents.Count }; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index 58378ba5..ae65fde9 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -37,6 +37,7 @@ public class ConversationController : ControllerBase var conversations = await service.GetConversations(filter); var userService = _services.GetRequiredService(); + var agentService = _services.GetRequiredService(); var list = conversations.Items .Select(x => ConversationViewModel.FromSession(x)) .ToList(); @@ -45,6 +46,9 @@ public class ConversationController : ControllerBase { var user = await userService.GetUser(item.User.Id); item.User = UserViewModel.FromUser(user); + + var agent = await agentService.GetAgent(item.AgentId); + item.AgentName = agent.Name; } return new PagedItems @@ -110,14 +114,26 @@ public class ConversationController : ControllerBase return response; } + [HttpDelete("/conversation/{conversationId}/message/{messageId}")] + public async Task DeleteConversationMessage([FromRoute] string conversationId, [FromRoute] string messageId) + { + var conversationService = _services.GetRequiredService(); + var response = await conversationService.TruncateConversation(conversationId, messageId); + return response; + } + [HttpPost("/conversation/{agentId}/{conversationId}")] public async Task SendMessage([FromRoute] string agentId, [FromRoute] string conversationId, [FromBody] NewMessageModel input) { - var inputMsg = new RoleDialogModel(AgentRole.User, input.Text); - var conv = _services.GetRequiredService(); + if (!string.IsNullOrEmpty(input.TruncateMessageId)) + { + await conv.TruncateConversation(conversationId, input.TruncateMessageId); + } + + var inputMsg = new RoleDialogModel(AgentRole.User, input.Text); conv.SetConversationId(conversationId, input.States); conv.States.SetState("channel", input.Channel) .SetState("provider", input.Provider) diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/PluginController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/PluginController.cs index 54cdae14..42299e6f 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/PluginController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/PluginController.cs @@ -28,7 +28,6 @@ public class PluginController : ControllerBase { var menu = new List { - new PluginMenuDef("Dashboard", link: "/page/dashboard", icon: "bx bx-home-circle", weight: 1), new PluginMenuDef("Apps", weight: 5) { IsHeader = true, @@ -54,15 +53,15 @@ public class PluginController : ControllerBase return menu; } - [HttpPost("/plugin/{id}/enable")] - public PluginDef EnablePlugin([FromRoute] string id) + [HttpPost("/plugin/{id}/install")] + public PluginDef InstallPlugin([FromRoute] string id) { var loader = _services.GetRequiredService(); return loader.UpdatePluginStatus(_services, id, true); } - [HttpPost("/plugin/{id}/disable")] - public PluginDef DisablePluginStats([FromRoute] string id) + [HttpPost("/plugin/{id}/remove")] + public PluginDef RemovePluginStats([FromRoute] string id) { var loader = _services.GetRequiredService(); return loader.UpdatePluginStatus(_services, id, false); diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs index 3c35b3af..536f5b5d 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs @@ -62,7 +62,6 @@ public class AgentViewModel Responses = agent.Responses, Samples = agent.Samples, IsPublic= agent.IsPublic, - IsHost = agent.IsHost, Disabled = agent.Disabled, IconUrl = agent.IconUrl, Profiles = agent.Profiles ?? new List(), diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs index a863763e..0823023d 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs @@ -9,13 +9,13 @@ public class ConversationViewModel [JsonPropertyName("agent_id")] public string AgentId { get; set; } + [JsonPropertyName("agent_name")] + public string AgentName { get; set; } + public string Title { get; set; } = string.Empty; public UserViewModel User { get; set; } = new UserViewModel(); - [JsonPropertyName("unread_msg_count")] - public int UnreadMsgCount { get; set; } - public string Event { get; set; } public string Channel { get; set; } = ConversationChannel.OpenAPI; diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs index bf563670..ca8d7e01 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs @@ -292,7 +292,9 @@ public class ChatCompletionProvider : IChatCompletion else if (x.Role == ChatRole.User) { var m = x as ChatRequestUserMessage; - return $"{m.Role}: {m.Content}"; + return !string.IsNullOrEmpty(m.Name) ? + $"{m.Name}: {m.Content}" : + $"{m.Role}: {m.Content}"; } else if (x.Role == ChatRole.Assistant) { diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs index bad8cf2b..8275daa7 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs @@ -36,7 +36,7 @@ public class ChatHubConversationHook : ConversationHookBase var agent = await agentService.LoadAgent(conversation.AgentId); // Check if the Welcome template exists. - var welcomeTemplate = agent.Templates?.FirstOrDefault(x => x.Name == "welcome"); + var welcomeTemplate = agent.Templates?.FirstOrDefault(x => x.Name == ".welcome"); if (welcomeTemplate != null) { var richContentService = _services.GetRequiredService(); diff --git a/src/Plugins/BotSharp.Plugin.Dashboard/BotSharp.Plugin.Dashboard.csproj b/src/Plugins/BotSharp.Plugin.Dashboard/BotSharp.Plugin.Dashboard.csproj new file mode 100644 index 00000000..5736c64f --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.Dashboard/BotSharp.Plugin.Dashboard.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.1 + enable + + + + + + + diff --git a/src/Plugins/BotSharp.Plugin.Dashboard/DashboardPlugin.cs b/src/Plugins/BotSharp.Plugin.Dashboard/DashboardPlugin.cs new file mode 100644 index 00000000..572bff90 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.Dashboard/DashboardPlugin.cs @@ -0,0 +1,32 @@ +using BotSharp.Abstraction.Conversations; +using BotSharp.Abstraction.Plugins; +using BotSharp.Abstraction.Plugins.Models; +using BotSharp.Abstraction.Settings; +using BotSharp.Abstraction.Statistics.Settings; +using BotSharp.Plugin.Dashboard.Hooks; + +namespace BotSharp.Plugin.Dashboard; + +public class DashboardPlugin : IBotSharpPlugin +{ + public string Id => "d42a0c21-b461-44f6-ada2-499510d260af"; + public string Name => "Dashboard"; + public string Description => "Dashboard that offers real-time statistics on model performance, usage trends, and user feedback"; + + public void RegisterDI(IServiceCollection services, IConfiguration config) + { + services.AddScoped(); + services.AddScoped(provider => + { + var settingService = provider.GetRequiredService(); + return settingService.Bind("Statistics"); + }); + } + + public bool AttachMenu(List menu) + { + var section = menu.First(x => x.Label == "Apps"); + menu.Add(new PluginMenuDef("Dashboard", link: "/page/dashboard", icon: "bx bx-home-circle", weight: section.Weight - 1)); + return true; + } +} diff --git a/src/Plugins/BotSharp.Plugin.Dashboard/Hooks/StatsConversationHook.cs b/src/Plugins/BotSharp.Plugin.Dashboard/Hooks/StatsConversationHook.cs new file mode 100644 index 00000000..5c16a173 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.Dashboard/Hooks/StatsConversationHook.cs @@ -0,0 +1,20 @@ +using BotSharp.Abstraction.Conversations; +using BotSharp.Abstraction.Plugins.Models; +using BotSharp.Abstraction.Repositories; + +namespace BotSharp.Plugin.Dashboard.Hooks; + +public class StatsConversationHook : ConversationHookBase +{ + private readonly IServiceProvider _services; + public StatsConversationHook(IServiceProvider services) + { + _services = services; + } + + public override async Task OnConversationInitialized(Conversation conversation) + { + var db = _services.GetRequiredService(); + db.IncrementConversationCount(); + } +} diff --git a/src/Plugins/BotSharp.Plugin.Dashboard/Using.cs b/src/Plugins/BotSharp.Plugin.Dashboard/Using.cs new file mode 100644 index 00000000..8cb9a723 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.Dashboard/Using.cs @@ -0,0 +1,13 @@ +global using System; +global using System.Collections.Generic; +global using System.Text; +global using System.Threading.Tasks; +global using System.Linq; +global using System.Text.Json; +global using BotSharp.Abstraction.Conversations.Models; +global using BotSharp.Abstraction.Agents.Models; +global using BotSharp.Abstraction.MLTasks; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using System.Text.Json.Serialization; +global using BotSharp.Abstraction.Utilities; \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj b/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj index 7f15d294..bb24ad19 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -35,7 +35,7 @@ - + diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs index 603f312e..8e2f4dd4 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs @@ -7,6 +7,7 @@ public class AgentDocument : MongoBase public string Name { get; set; } public string Description { get; set; } public string Type { get; set; } + public string? InheritAgentId { get; set; } public string? IconUrl { get; set; } public string Instruction { get; set; } public List Templates { get; set; } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/RoutingRuleMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/RoutingRuleMongoElement.cs index 1a40b0f7..571c6d09 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/RoutingRuleMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/RoutingRuleMongoElement.cs @@ -9,6 +9,7 @@ public class RoutingRuleMongoElement public string Description { get; set; } public bool Required { get; set; } public string? RedirectTo { get; set; } + public string Type { get; set; } public RoutingRuleMongoElement() { @@ -22,7 +23,8 @@ public class RoutingRuleMongoElement Field = routingRule.Field, Description = routingRule.Description, Required = routingRule.Required, - RedirectTo = routingRule.RedirectTo + RedirectTo = routingRule.RedirectTo, + Type = routingRule.Type, }; } @@ -35,7 +37,8 @@ public class RoutingRuleMongoElement Field = rule.Field, Description = rule.Description, Required = rule.Required, - RedirectTo = rule.RedirectTo + RedirectTo = rule.RedirectTo, + Type = rule.Type, }; } } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs index 9a0f0cee..58fe44ff 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs @@ -32,6 +32,9 @@ public partial class MongoRepository case AgentField.Type: UpdateAgentType(agent.Id, agent.Type); break; + case AgentField.InheritAgentId: + UpdateAgentInheritAgentId(agent.Id, agent.InheritAgentId); + break; case AgentField.Profiles: UpdateAgentProfiles(agent.Id, agent.Profiles); break; @@ -119,6 +122,16 @@ public partial class MongoRepository _dc.Agents.UpdateOne(filter, update); } + private void UpdateAgentInheritAgentId(string agentId, string? inheritAgentId) + { + var filter = Builders.Filter.Eq(x => x.Id, agentId); + var update = Builders.Update + .Set(x => x.InheritAgentId, inheritAgentId) + .Set(x => x.UpdatedTime, DateTime.UtcNow); + + _dc.Agents.UpdateOne(filter, update); + } + private void UpdateAgentProfiles(string agentId, List profiles) { if (profiles.IsNullOrEmpty()) return; @@ -268,6 +281,7 @@ public partial class MongoRepository IsPublic = agent.IsPublic, Disabled = agent.Disabled, Type = agent.Type, + InheritAgentId = agent.InheritAgentId, Profiles = agent.Profiles, RoutingRules = !agent.RoutingRules.IsNullOrEmpty() ? agent.RoutingRules .Select(r => RoutingRuleMongoElement.ToDomainElement(agent.Id, agent.Name, r)) @@ -329,6 +343,7 @@ public partial class MongoRepository IsPublic = x.IsPublic, Disabled = x.Disabled, Type = x.Type, + InheritAgentId = x.InheritAgentId, Profiles = x.Profiles, RoutingRules = !x.RoutingRules.IsNullOrEmpty() ? x.RoutingRules .Select(r => RoutingRuleMongoElement.ToDomainElement(x.Id, x.Name, r)) @@ -393,6 +408,7 @@ public partial class MongoRepository Samples = x.Samples ?? new List(), IsPublic = x.IsPublic, Type = x.Type, + InheritAgentId = x.InheritAgentId, Disabled = x.Disabled, Profiles = x.Profiles, RoutingRules = x.RoutingRules? diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs index 15a2406b..0a1c2530 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs @@ -263,4 +263,42 @@ public partial class MongoRepository UpdatedTime = c.UpdatedTime }).ToList(); } + + public bool TruncateConversation(string conversationId, string messageId) + { + if (string.IsNullOrEmpty(conversationId) || string.IsNullOrEmpty(messageId)) return false; + + var dialogFilter = Builders.Filter.Eq(x => x.ConversationId, conversationId); + var foundDialog = _dc.ConversationDialogs.Find(dialogFilter).FirstOrDefault(); + if (foundDialog == null || foundDialog.Dialogs.IsNullOrEmpty()) return false; + + var foundIdx = foundDialog.Dialogs.FindIndex(x => x.MetaData?.MessageId == messageId); + if (foundIdx < 0) return false; + + // Handle truncated dialogs + var truncatedDialogs = foundDialog.Dialogs.Where((x, idx) => idx < foundIdx).ToList(); + + // Handle truncated states + var refTime = foundDialog.Dialogs.ElementAt(foundIdx).MetaData.CreateTime; + var stateFilter = Builders.Filter.Eq(x => x.ConversationId, conversationId); + var foundStates = _dc.ConversationStates.Find(stateFilter).FirstOrDefault(); + if (foundStates == null || foundStates.States.IsNullOrEmpty()) return false; + + var truncatedStates = new List(); + foreach (var state in foundStates.States) + { + var values = state.Values.Where(x => x.UpdateTime < refTime).ToList(); + if (values.Count == 0) continue; + + state.Values = values; + truncatedStates.Add(state); + } + + // Save + foundDialog.Dialogs = truncatedDialogs; + foundStates.States = truncatedStates; + _dc.ConversationDialogs.ReplaceOne(dialogFilter, foundDialog); + _dc.ConversationStates.ReplaceOne(stateFilter, foundStates); + return true; + } } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Stats.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Stats.cs new file mode 100644 index 00000000..eea27ee9 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Stats.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Plugin.MongoStorage.Repository +{ + public partial class MongoRepository + { + #region Statistics + public void IncrementConversationCount() + { + + } + #endregion + } +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Transaction.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Transaction.cs index 17e59c2e..470b1fb1 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Transaction.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Transaction.cs @@ -55,6 +55,7 @@ public partial class MongoRepository Samples = x.Samples ?? new List(), IsPublic = x.IsPublic, Type = x.Type, + InheritAgentId = x.InheritAgentId, Disabled = x.Disabled, Profiles = x.Profiles, RoutingRules = x.RoutingRules? @@ -78,6 +79,7 @@ public partial class MongoRepository .Set(x => x.Samples, agent.Samples) .Set(x => x.IsPublic, agent.IsPublic) .Set(x => x.Type, agent.Type) + .Set(x => x.InheritAgentId, agent.InheritAgentId) .Set(x => x.Disabled, agent.Disabled) .Set(x => x.Profiles, agent.Profiles) .Set(x => x.RoutingRules, agent.RoutingRules) diff --git a/src/Plugins/BotSharp.Plugin.PaddleSharp/BotSharp.Plugin.PaddleSharp.csproj b/src/Plugins/BotSharp.Plugin.PaddleSharp/BotSharp.Plugin.PaddleSharp.csproj index d6c862d4..6dcaf95e 100644 --- a/src/Plugins/BotSharp.Plugin.PaddleSharp/BotSharp.Plugin.PaddleSharp.csproj +++ b/src/Plugins/BotSharp.Plugin.PaddleSharp/BotSharp.Plugin.PaddleSharp.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/BotSharp.Plugin.RoutingSpeeder.csproj b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/BotSharp.Plugin.RoutingSpeeder.csproj index 857154cf..0dc946cb 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/BotSharp.Plugin.RoutingSpeeder.csproj +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/BotSharp.Plugin.RoutingSpeeder.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/BotSharp.Plugin.SqlDriver.csproj b/src/Plugins/BotSharp.Plugin.SqlDriver/BotSharp.Plugin.SqlDriver.csproj index 4f6f352c..aa5124f8 100644 --- a/src/Plugins/BotSharp.Plugin.SqlDriver/BotSharp.Plugin.SqlDriver.csproj +++ b/src/Plugins/BotSharp.Plugin.SqlDriver/BotSharp.Plugin.SqlDriver.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj index 205f32bf..7c4d6a76 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 @@ -11,7 +11,7 @@ - + diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs index 0df3c6ee..b8e2e5b2 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs @@ -16,6 +16,11 @@ public class PlaywrightInstance : IDisposable { _playwright = await Playwright.CreateAsync(); + /*_browser = await _playwright.Chromium.LaunchPersistentContextAsync(@"C:\Users\haipi\AppData\Local\Google\Chrome\User Data", new BrowserTypeLaunchPersistentContextOptions + { + Headless = false, + Channel = "chrome", + });*/ _browser = await _playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = false, diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ChangeListValue.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ChangeListValue.cs index d3cb5c7d..75e8ad6a 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ChangeListValue.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ChangeListValue.cs @@ -57,23 +57,11 @@ public partial class PlaywrightWebDriver } var driverService = _services.GetRequiredService(); - var htmlElementContextOut = await driverService.LocateElement(agent, string.Join("", str), context.ElementName, messageId); - - if (htmlElementContextOut.Index < 0) - { - throw new Exception($"Can't locate the web element {context.ElementName}."); - } - - ILocator element = default; - if (!string.IsNullOrEmpty(htmlElementContextOut.ElementId)) - { - // await _instance.Page.WaitForSelectorAsync($"#{htmlElementContextOut.ElementId}", new PageWaitForSelectorOptions { Timeout = 3 }); - element = _instance.Page.Locator($"#{htmlElementContextOut.ElementId}"); - } - else - { - element = _instance.Page.Locator(htmlElementContextOut.TagName).Nth(htmlElementContextOut.Index); - } + var htmlElementContextOut = await driverService.LocateElement(agent, + string.Join("", str), + context.ElementName, + messageId); + ILocator element = Locator(htmlElementContextOut); try { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ClickButton.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ClickButton.cs index d7fbed3d..82e9683d 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ClickButton.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.ClickButton.cs @@ -1,11 +1,11 @@ -using BotSharp.Plugin.WebDriver.Services; - namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver; public partial class PlaywrightWebDriver { public async Task ClickElement(Agent agent, BrowsingContextIn context, string messageId) { + var driverService = _services.GetRequiredService(); + // Retrieve the page raw html and infer the element path var body = await _instance.Page.QuerySelectorAsync("body"); @@ -23,18 +23,19 @@ public partial class PlaywrightWebDriver var text = await btn.TextContentAsync(); var name = await btn.GetAttributeAsync("name"); var id = await btn.GetAttributeAsync("id"); - str.Add($""); + str.Add(driverService.AssembleMarkup("button", new MarkupProperties + { + Id = id, + Name = name, + Text = text + })); } - var driverService = _services.GetRequiredService(); - var htmlElementContextOut = await driverService.LocateElement(agent, string.Join("", str), context.ElementName, messageId); - - var tags = await _instance.Page.QuerySelectorAllAsync(htmlElementContextOut.TagName); - var button = tags[htmlElementContextOut.Index]; - if (button.AsElement() == null) - { - throw new Exception($"Can't find web element {context.ElementName}"); - } - await button.ClickAsync(); + var htmlElementContextOut = await driverService.LocateElement(agent, + string.Join("", str), + context.ElementName, + messageId); + ILocator element = Locator(htmlElementContextOut); + await element.ClickAsync(); } } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.InputUserText.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.InputUserText.cs index 80c288a5..5362602f 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.InputUserText.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.InputUserText.cs @@ -1,11 +1,11 @@ -using BotSharp.Plugin.WebDriver.Services; - namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver; public partial class PlaywrightWebDriver { public async Task InputUserText(Agent agent, BrowsingContextIn context, string messageId) { + var driverService = _services.GetRequiredService(); + // Retrieve the page raw html and infer the element path var body = await _instance.Page.QuerySelectorAsync("body"); @@ -14,32 +14,47 @@ public partial class PlaywrightWebDriver foreach (var input in inputs) { var text = await input.TextContentAsync(); + var id = await input.GetAttributeAsync("id"); var name = await input.GetAttributeAsync("name"); var type = await input.GetAttributeAsync("type"); - str.Add($"{text}"); + str.Add(driverService.AssembleMarkup("input", new MarkupProperties + { + Id = id, + Name = name, + Type = type, + Text = text + })); } inputs = await body.QuerySelectorAllAsync("textarea"); foreach (var input in inputs) { var text = await input.TextContentAsync(); + var id = await input.GetAttributeAsync("id"); var name = await input.GetAttributeAsync("name"); var type = await input.GetAttributeAsync("type"); - str.Add($""); + str.Add(driverService.AssembleMarkup("textarea", new MarkupProperties + { + Id = id, + Name = name, + Type = type, + Text = text + })); } + + var htmlElementContextOut = await driverService.LocateElement(agent, + string.Join("", str), + context.ElementName, + messageId); + ILocator element = Locator(htmlElementContextOut); - var driverService = _services.GetRequiredService(); - var htmlElementContextOut = await driverService.LocateElement(agent, string.Join("", str), context.ElementName, messageId); - - if (htmlElementContextOut.Index < 0) - { - throw new Exception($"Can't locate the web element {context.ElementName}."); - } - - var element = _instance.Page.Locator(htmlElementContextOut.TagName).Nth(htmlElementContextOut.Index); try { await element.FillAsync(context.InputText); + if (context.PressEnter) + { + await element.PressAsync("Enter"); + } } catch (Exception ex) { diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.cs index abfc300f..c513bf1c 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.cs @@ -11,4 +11,24 @@ public partial class PlaywrightWebDriver _services = services; _instance = instance; } + + private ILocator Locator(HtmlElementContextOut context) + { + ILocator element = default; + if (!string.IsNullOrEmpty(context.ElementId)) + { + // await _instance.Page.WaitForSelectorAsync($"#{htmlElementContextOut.ElementId}", new PageWaitForSelectorOptions { Timeout = 3 }); + element = _instance.Page.Locator($"#{context.ElementId}"); + } + else + { + if (context.Index < 0) + { + throw new Exception($"Can't locate the web element {context.Index}."); + } + element = _instance.Page.Locator(context.TagName).Nth(context.Index); + } + + return element; + } } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/BrowsingContextIn.cs b/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/BrowsingContextIn.cs index 73c2753b..efd327eb 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/BrowsingContextIn.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/BrowsingContextIn.cs @@ -13,6 +13,9 @@ public class BrowsingContextIn [JsonPropertyName("input_text")] public string? InputText { get; set; } + [JsonPropertyName("press_enter")] + public bool PressEnter { get; set; } + [JsonPropertyName("update_value")] public string? UpdateValue { get; set; } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Models/MarkupProperties.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Models/MarkupProperties.cs new file mode 100644 index 00000000..410bf50c --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Models/MarkupProperties.cs @@ -0,0 +1,9 @@ +namespace BotSharp.Plugin.WebDriver.Models; + +internal class MarkupProperties +{ + public string? Id { get; set; } + public string? Name { get; set; } + public string? Type { get; set; } + public string? Text { get; set; } +} diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Services/WebDriverService.AssembleMarkup.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Services/WebDriverService.AssembleMarkup.cs new file mode 100644 index 00000000..14eb5c6c --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Services/WebDriverService.AssembleMarkup.cs @@ -0,0 +1,33 @@ +using BotSharp.Plugin.WebDriver.LlmContexts; + +namespace BotSharp.Plugin.WebDriver.Services; + +public partial class WebDriverService +{ + internal string AssembleMarkup(string tagName, MarkupProperties properties) + { + var html = $"<{tagName}"; + if (!string.IsNullOrEmpty(properties.Id)) + { + html += $" id=\"{properties.Id}\""; + } + + if (!string.IsNullOrEmpty(properties.Name)) + { + html += $" name=\"{properties.Name}\""; + } + + if (!string.IsNullOrEmpty(properties.Type)) + { + html += $" type=\"{properties.Type}\""; + } + + if (!string.IsNullOrEmpty(properties.Text)) + { + html += $">{properties.Text}"; + return html; + } + + return html + $">"; + } +} diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Using.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Using.cs index ca78d12b..9a0e6ecc 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Using.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Using.cs @@ -14,4 +14,6 @@ global using BotSharp.Abstraction.Templating; global using BotSharp.Plugin.WebDriver.LlmContexts; global using Microsoft.Extensions.DependencyInjection; global using System.Linq; -global using BotSharp.Abstraction.Utilities; \ No newline at end of file +global using BotSharp.Abstraction.Utilities; +global using BotSharp.Plugin.WebDriver.Models; +global using BotSharp.Plugin.WebDriver.Services; \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/data/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json b/src/Plugins/BotSharp.Plugin.WebDriver/data/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json index e06597f9..2d928f12 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/data/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json +++ b/src/Plugins/BotSharp.Plugin.WebDriver/data/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json @@ -1,12 +1,13 @@ { "id": "f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b", "name": "Web Driver", - "description": "Perform a specific action on a web browser", + "description": "Perform the web page related task in browser by using automation tools.", "type": "task", "createdDateTime": "2024-01-02T00:00:00Z", "updatedDateTime": "2024-01-02T00:00:00Z", "isPublic": true, + "profiles": [ "web-driver" ], "llmConfig": { - "max_recursion_depth": 10 + "max_recursion_depth": 5 } } \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/data/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json b/src/Plugins/BotSharp.Plugin.WebDriver/data/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json index 49e4770b..87723841 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/data/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json +++ b/src/Plugins/BotSharp.Plugin.WebDriver/data/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json @@ -51,10 +51,14 @@ "type": "string", "description": "the html input box element name." }, - "input_text": { - "type": "string", - "description": "non-sensitive text user provided." - } + "input_text": { + "type": "string", + "description": "non-sensitive text user provided." + }, + "press_enter": { + "type": "boolean", + "description": "whether to press ENTER" + } }, "required": ["element_name", "input_text"] } diff --git a/src/WebStarter/WebStarter.csproj b/src/WebStarter/WebStarter.csproj index 02894f13..42f4ef2a 100644 --- a/src/WebStarter/WebStarter.csproj +++ b/src/WebStarter/WebStarter.csproj @@ -29,6 +29,7 @@ + diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index 310d6908..54aa1fac 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -82,7 +82,9 @@ "EnableLlmCompletionLog": false, "EnableExecutionLog": true }, - + "Stats": { + "DataDir": "stats" + }, "LlamaSharp": { "Interactive": true, "ModelDir": "C:/Users/haipi/Downloads", @@ -161,8 +163,10 @@ "PluginLoader": { "Assemblies": [ - "BotSharp.Plugin.MongoStorage", "BotSharp.Core", + "BotSharp.Logger", + "BotSharp.Plugin.MongoStorage", + "BotSharp.Plugin.Dashboard", "BotSharp.Plugin.AzureOpenAI", "BotSharp.Plugin.GoogleAI", "BotSharp.Plugin.MetaAI", diff --git a/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj b/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj index 77ba7e96..4328eb4d 100644 --- a/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj +++ b/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj @@ -20,6 +20,8 @@ + + @@ -27,11 +29,6 @@ - - - - - @@ -42,6 +39,12 @@ + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -63,21 +66,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - PreserveNewest diff --git a/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs b/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs index d3d4c3a6..6fa37ce6 100644 --- a/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs +++ b/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs @@ -11,6 +11,7 @@ public class PizzaBotPlugin : IBotSharpPlugin public string IconUrl => "https://cdn-icons-png.flaticon.com/512/6978/6978255.png"; public string[] AgentIds => new[] { + "8970b1e5-d260-4e2c-90b1-f1415a257c18", "b284db86-e9c2-4c25-a59e-4649797dd130", "c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd", "dfd9b46d-d00c-40af-8a75-3fbdc2b89869", diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/8970b1e5-d260-4e2c-90b1-f1415a257c18/agent.json b/tests/BotSharp.Plugin.PizzaBot/data/agents/8970b1e5-d260-4e2c-90b1-f1415a257c18/agent.json new file mode 100644 index 00000000..e57ba894 --- /dev/null +++ b/tests/BotSharp.Plugin.PizzaBot/data/agents/8970b1e5-d260-4e2c-90b1-f1415a257c18/agent.json @@ -0,0 +1,18 @@ +{ + "id": "8970b1e5-d260-4e2c-90b1-f1415a257c18", + "name": "Pizza Bot", + "description": "AI assistant that can help customer place pizza order.", + "type": "routing", + "createdDateTime": "2023-08-18T10:39:32.2349685Z", + "updatedDateTime": "2023-08-18T14:39:32.2349686Z", + "iconUrl": "https://cdn-icons-png.flaticon.com/512/6978/6978255.png", + "disabled": true, + "isPublic": true, + "profiles": [ "pizza" ], + "routingRules": [ + { + "type": "planner", + "field": "NaviePlanner" + } + ] +} \ No newline at end of file diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/task.place_pizza_order.liquid b/tests/BotSharp.Plugin.PizzaBot/data/agents/8970b1e5-d260-4e2c-90b1-f1415a257c18/templates/task.place_pizza_order.liquid similarity index 100% rename from tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/task.place_pizza_order.liquid rename to tests/BotSharp.Plugin.PizzaBot/data/agents/8970b1e5-d260-4e2c-90b1-f1415a257c18/templates/task.place_pizza_order.liquid diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json b/tests/BotSharp.Plugin.PizzaBot/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json index 09c08cb6..949e201c 100644 --- a/tests/BotSharp.Plugin.PizzaBot/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json +++ b/tests/BotSharp.Plugin.PizzaBot/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json @@ -4,7 +4,7 @@ "createdDateTime": "2023-08-18T14:39:32.2349685Z", "updatedDateTime": "2023-08-18T14:39:32.2349686Z", "id": "b284db86-e9c2-4c25-a59e-4649797dd130", - "allowRouting": true, + "disabled": true, "isPublic": true, "profiles": [ "pizza" ], "routingRules": [ diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json b/tests/BotSharp.Plugin.PizzaBot/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json index 23323f63..4751fb78 100644 --- a/tests/BotSharp.Plugin.PizzaBot/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json +++ b/tests/BotSharp.Plugin.PizzaBot/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json @@ -4,7 +4,7 @@ "createdDateTime": "2023-07-26T02:29:25.123224Z", "updatedDateTime": "2023-07-26T02:29:25.123274Z", "id": "c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd", - "allowRouting": true, + "disabled": true, "isPublic": true, "profiles": [ "pizza" ] } \ No newline at end of file diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json b/tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json deleted file mode 100644 index 26f15972..00000000 --- a/tests/BotSharp.Plugin.PizzaBot/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "EvaluationAgent", - "description": "Evaluate the performance of the LLM agents", - "createdDateTime": "2023-08-18T00:00:00Z", - "updatedDateTime": "2023-08-18T00:00:00Z", - "id": "dfd9b46d-d00c-40af-8a75-3fbdc2b89869", - "llmConfig": { - "model": "gpt-35-turbo-instruct" - } - } \ No newline at end of file diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json b/tests/BotSharp.Plugin.PizzaBot/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json index eba914f7..af5d6cd9 100644 --- a/tests/BotSharp.Plugin.PizzaBot/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json +++ b/tests/BotSharp.Plugin.PizzaBot/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json @@ -4,8 +4,9 @@ "createdDateTime": "2023-07-26T02:29:25.123224Z", "updatedDateTime": "2023-07-26T02:29:25.123274Z", "id": "fe8c60aa-b114-4ef3-93cb-a8efeac80f75", - "allowRouting": true, + "disabled": true, "isPublic": true, + "profiles": [ "pizza" ], "routingRules": [ { "field": "order_number", diff --git a/tests/BotSharp.Plugin.SemanticKernel.UnitTests/BotSharp.Plugin.SemanticKernel.UnitTests.csproj b/tests/BotSharp.Plugin.SemanticKernel.UnitTests/BotSharp.Plugin.SemanticKernel.UnitTests.csproj index a85f0dbc..27e9bec9 100644 --- a/tests/BotSharp.Plugin.SemanticKernel.UnitTests/BotSharp.Plugin.SemanticKernel.UnitTests.csproj +++ b/tests/BotSharp.Plugin.SemanticKernel.UnitTests/BotSharp.Plugin.SemanticKernel.UnitTests.csproj @@ -12,7 +12,7 @@ - +