From 28d4f4e9baccb976134a731e6ba30d4232a4a130 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 27 May 2025 15:23:37 -0500 Subject: [PATCH] add utility visibility expression --- .../Agents/IAgentService.cs | 2 + .../Agents/Models/AgentUtility.cs | 4 ++ .../Agents/Hooks/BasicAgentHook.cs | 38 ++++++++++++------- .../Agents/Services/AgentService.LoadAgent.cs | 6 ++- .../Agents/Services/AgentService.Rendering.cs | 17 +++++++++ .../Models/AgentUtilityMongoElement.cs | 3 ++ .../Core/TestAgentService.cs | 6 +++ 7 files changed, 61 insertions(+), 15 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index 45fd3251..b50be071 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -36,6 +36,8 @@ public interface IAgentService FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def); + bool RenderUtility(Agent agent, AgentUtility utility); + /// /// Get agent detail without trigger any hook. /// diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs index ce39c568..1d426600 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs @@ -4,6 +4,10 @@ public class AgentUtility { public string Name { get; set; } public bool Disabled { get; set; } + + [JsonPropertyName("visibility_expression")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? VisibilityExpression { get; set; } public IEnumerable Functions { get; set; } = []; public IEnumerable Templates { get; set; } = []; diff --git a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs index 10fa376c..03e7bb68 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs @@ -19,9 +19,9 @@ public class BasicAgentHook : AgentHookBase var isConvMode = conv.IsConversationMode(); if (!isConvMode) return; + agent.Utilities ??= []; agent.SecondaryFunctions ??= []; agent.SecondaryInstructions ??= []; - agent.Utilities ??= []; var (functions, templates) = GetUtilityContent(agent); @@ -34,7 +34,7 @@ public class BasicAgentHook : AgentHookBase private (IEnumerable, IEnumerable) GetUtilityContent(Agent agent) { var db = _services.GetRequiredService(); - var (functionNames, templateNames) = GetUniqueContent(agent.Utilities); + var (functionNames, templateNames) = FilterUtilityContent(agent.Utilities, agent); if (agent.MergeUtility) { @@ -43,7 +43,7 @@ public class BasicAgentHook : AgentHookBase if (!string.IsNullOrEmpty(entryAgentId)) { var entryAgent = db.GetAgent(entryAgentId, basicsOnly: true); - var (fns, tps) = GetUniqueContent(entryAgent?.Utilities); + var (fns, tps) = FilterUtilityContent(entryAgent?.Utilities, agent); functionNames = functionNames.Concat(fns).Distinct().ToList(); templateNames = templateNames.Concat(tps).Distinct().ToList(); } @@ -55,22 +55,34 @@ public class BasicAgentHook : AgentHookBase return (functions, templates); } - private (IEnumerable, IEnumerable) GetUniqueContent(IEnumerable? utilities) + private (IEnumerable, IEnumerable) FilterUtilityContent(IEnumerable? utilities, Agent agent) { if (utilities.IsNullOrEmpty()) { return ([], []); } - utilities = utilities?.Where(x => !string.IsNullOrEmpty(x.Name) && !x.Disabled)?.ToList() ?? []; - var functionNames = utilities.SelectMany(x => x.Functions) - .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) - .Select(x => x.Name) - .Distinct().ToList(); - var templateNames = utilities.SelectMany(x => x.Templates) - .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) - .Select(x => x.Name) - .Distinct().ToList(); + var agentService = _services.GetRequiredService(); + var innerUtilities = utilities!.Where(x => + { + var isVisible = !string.IsNullOrEmpty(x.Name) && !x.Disabled; + if (!isVisible) + { + return isVisible; + } + + isVisible = agentService.RenderUtility(agent, x); + return isVisible; + }).ToList(); + + var functionNames = innerUtilities.SelectMany(x => x.Functions) + .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) + .Select(x => x.Name) + .Distinct().ToList(); + var templateNames = innerUtilities.SelectMany(x => x.Templates) + .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) + .Select(x => x.Name) + .Distinct().ToList(); return (functionNames, templateNames); } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs index 7fbfffdc..a15b2907 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs @@ -1,4 +1,3 @@ -using BotSharp.Abstraction.Infrastructures; using BotSharp.Abstraction.Routing.Models; using System.Collections.Concurrent; @@ -18,12 +17,15 @@ public partial class AgentService var agent = await GetAgent(id); if (agent == null) return null; + agent.TemplateDict = []; + agent.SecondaryInstructions = []; + agent.SecondaryFunctions = []; + await InheritAgent(agent); OverrideInstructionByChannel(agent); AddOrUpdateParameters(agent); // Populate state into dictionary - agent.TemplateDict = new Dictionary(); PopulateState(agent.TemplateDict); // After agent is loaded diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index f862482c..89979663 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Loggers; using BotSharp.Abstraction.Templating; +using Microsoft.EntityFrameworkCore; using Newtonsoft.Json.Linq; namespace BotSharp.Core.Agents.Services; @@ -137,4 +138,20 @@ public partial class AgentService return content; } + + public bool RenderUtility(Agent agent, AgentUtility utility) + { + if (string.IsNullOrWhiteSpace(utility?.VisibilityExpression)) + { + return true; + } + + var render = _services.GetRequiredService(); + var result = render.Render(utility.VisibilityExpression, new Dictionary + { + { "states", agent.TemplateDict } + }); + + return result == "visible"; + } } \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs index 131226b3..518939cc 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs @@ -7,6 +7,7 @@ public class AgentUtilityMongoElement { public string Name { get; set; } = default!; public bool Disabled { get; set; } + public string? VisibilityExpression { get; set; } public List Functions { get; set; } = []; public List Templates { get; set; } = []; @@ -16,6 +17,7 @@ public class AgentUtilityMongoElement { Name = utility.Name, Disabled = utility.Disabled, + VisibilityExpression = utility.VisibilityExpression, Functions = utility.Functions?.Select(x => new UtilityFunctionMongoElement(x.Name))?.ToList() ?? [], Templates = utility.Templates?.Select(x => new UtilityTemplateMongoElement(x.Name))?.ToList() ?? [] }; @@ -27,6 +29,7 @@ public class AgentUtilityMongoElement { Name = utility.Name, Disabled = utility.Disabled, + VisibilityExpression = utility.VisibilityExpression, Functions = utility.Functions?.Select(x => new UtilityFunction(x.Name))?.ToList() ?? [], Templates = utility.Templates?.Select(x => new UtilityTemplate(x.Name))?.ToList() ?? [] }; diff --git a/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs b/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs index 6716519a..7d58637d 100644 --- a/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs +++ b/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs @@ -6,6 +6,7 @@ using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Plugins.Models; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Utilities; +using NetTopologySuite.Algorithm; namespace BotSharp.Plugin.Google.Core { @@ -61,6 +62,11 @@ namespace BotSharp.Plugin.Google.Core return def.Parameters; } + public bool RenderUtility(Agent agent, AgentUtility utility) + { + return true; + } + public Task GetAgent(string id) { return Task.FromResult(new Agent());