diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index c8aee271..e67cd6b8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -26,6 +26,8 @@ public interface IAgentService bool RenderFunction(Agent agent, FunctionDef def); + FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def); + /// /// Get agent detail without trigger any hook. /// diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index 9ce7a7a8..810e101a 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 Newtonsoft.Json.Linq; namespace BotSharp.Core.Agents.Services; @@ -32,6 +33,64 @@ public partial class AgentService return true; } + public FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def) + { + var parameterDef = def?.Parameters; + var propertyDef = parameterDef?.Properties; + if (propertyDef == null) return null; + + var visibleExpress = "visibility_expression"; + var root = propertyDef.RootElement; + var iterator = root.EnumerateObject(); + var list = new List(); + while (iterator.MoveNext()) + { + var prop = iterator.Current; + var name = prop.Name; + var node = prop.Value; + var matched = true; + if (node.TryGetProperty(visibleExpress, out var element)) + { + var expression = element.GetString(); + var render = _services.GetRequiredService(); + var result = render.Render(expression, new Dictionary + { + { "states", agent.TemplateDict } + }); + matched = result == "visible"; + } + + if (matched) + { + list.Add(name); + } + } + + var rootObject = JObject.Parse(root.GetRawText()); + var clonedRoot = rootObject.DeepClone() as JObject; + var required = parameterDef?.Required ?? new List(); + foreach (var property in rootObject.Properties()) + { + if (list.Contains(property.Name)) + { + var value = clonedRoot.GetValue(property.Name) as JObject; + if (value != null && value.ContainsKey(visibleExpress)) + { + value.Remove(visibleExpress); + } + } + else + { + clonedRoot.Remove(property.Name); + required.Remove(property.Name); + } + } + + parameterDef.Properties = JsonSerializer.Deserialize(clonedRoot.ToString()); + parameterDef.Required = required; + return parameterDef; ; + } + public string RenderedTemplate(Agent agent, string templateName) { // render liquid template diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs index e3f6afca..0e5cc0ab 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs @@ -221,11 +221,12 @@ public class ChatCompletionProvider : IChatCompletion { if (agentService.RenderFunction(agent, function)) { + var property = agentService.RenderFunctionProperty(agent, function); chatCompletionsOptions.Functions.Add(new FunctionDefinition { Name = function.Name, Description = function.Description, - Parameters = BinaryData.FromObjectAsJson(function.Parameters) + Parameters = BinaryData.FromObjectAsJson(property) }); } } diff --git a/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs index 3423347e..7d529df1 100644 --- a/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs @@ -222,7 +222,7 @@ public class ChatCompletionProvider : IChatCompletion return (prompt, messages.ToArray(), functions.ToArray()); } - private string GetPrompt(List messages,List functions) + private string GetPrompt(List messages, List functions) { var prompt = string.Empty;