From 7c79bc72b34bcea3b7dcf1f18d951ce84e04a393 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Sun, 22 Dec 2024 16:36:18 -0600 Subject: [PATCH 1/6] refine code --- .../BotSharp.Abstraction/Agents/IAgentService.cs | 2 +- .../BotSharp.Abstraction/Agents/Models/Agent.cs | 6 ++++++ .../BotSharp.Core/Agents/Hooks/BasicAgentHook.cs | 16 +++++++++------- .../Agents/Services/AgentService.LoadAgent.cs | 8 ++++++-- .../Agents/Services/AgentService.Rendering.cs | 6 +++++- .../Functions/ReadImageFn.cs | 15 +++++++++------ .../Providers/Chat/ChatCompletionProvider.cs | 12 ++++++++---- .../Providers/ProviderHelper.cs | 10 ++++++---- 8 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index b8945f40..91beea8b 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -18,7 +18,7 @@ public interface IAgentService /// /// /// - Task LoadAgent(string id); + Task LoadAgent(string id, bool loadUtility = true); /// /// Inherit from an agent diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs index 41b3800c..80d6db07 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs @@ -118,6 +118,12 @@ public class Agent [JsonIgnore] public Dictionary TemplateDict { get; set; } = new(); + [JsonIgnore] + public List SecondaryFunctions { get; set; } = []; + + [JsonIgnore] + public List SecondaryInstructions { get; set; } = []; + public override string ToString() => $"{Name} {Id}"; diff --git a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs index 65d454c8..1101f160 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs @@ -4,6 +4,8 @@ public class BasicAgentHook : AgentHookBase { public override string SelfId => string.Empty; + private const string UTIL_PREFIX = "util-"; + public BasicAgentHook(IServiceProvider services, AgentSettings settings) : base(services, settings) { @@ -17,22 +19,23 @@ public class BasicAgentHook : AgentHookBase var isConvMode = conv.IsConversationMode(); if (!isConvMode) return; - agent.Functions ??= []; + agent.SecondaryFunctions ??= []; + agent.SecondaryInstructions ??= []; agent.Utilities ??= []; var (functions, templates) = GetUtilityContent(agent); foreach (var fn in functions) { - if (!agent.Functions.Any(x => x.Name.Equals(fn.Name, StringComparison.OrdinalIgnoreCase))) + if (!agent.SecondaryFunctions.Any(x => x.Name.Equals(fn.Name, StringComparison.OrdinalIgnoreCase))) { - agent.Functions.Add(fn); + agent.SecondaryFunctions.Add(fn); } } foreach (var prompt in templates) { - agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n"; + agent.SecondaryInstructions.Add(prompt); } } @@ -67,14 +70,13 @@ public class BasicAgentHook : AgentHookBase return ([], []); } - var prefix = "util-"; 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(prefix)) + .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(prefix)) + .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) .Select(x => x.Name) .Distinct().ToList(); diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs index 0e9c2e3c..9e6ad8ee 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs @@ -8,7 +8,7 @@ public partial class AgentService public static ConcurrentDictionary> AgentParameterTypes = new(); [MemoryCache(10 * 60, perInstanceCache: true)] - public async Task LoadAgent(string id) + public async Task LoadAgent(string id, bool loadUtility = true) { if (string.IsNullOrEmpty(id) || id == Guid.Empty.ToString()) { @@ -67,7 +67,11 @@ public partial class AgentService hook.OnSamplesLoaded(agent.Samples); } - hook.OnAgentUtilityLoaded(agent); + if (loadUtility) + { + hook.OnAgentUtilityLoaded(agent); + } + hook.OnAgentLoaded(agent); } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index ba76e310..b0038f35 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs @@ -11,13 +11,17 @@ public partial class AgentService var render = _services.GetRequiredService(); var conv = _services.GetRequiredService(); + // merge instructions + var texts = new List { agent.Instruction }; + texts.AddRange(agent.SecondaryInstructions ?? []); + // update states foreach (var t in conv.States.GetStates()) { agent.TemplateDict[t.Key] = t.Value; } - var res = render.Render(agent.Instruction, agent.TemplateDict); + var res = render.Render(string.Join("\r\n", texts), agent.TemplateDict); return res; } diff --git a/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs b/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs index e2c4f8c2..64b5a7ae 100644 --- a/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs +++ b/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs @@ -24,17 +24,20 @@ public class ReadImageFn : IFunctionCallback var wholeDialogs = conv.GetDialogHistory(); var dialogs = AssembleFiles(conv.ConversationId, args?.ImageUrls, wholeDialogs); - var agentId = !string.IsNullOrWhiteSpace(message.CurrentAgentId) ? message.CurrentAgentId : BuiltInAgentId.UtilityAssistant; - var agent = await agentService.LoadAgent(agentId); - var fileAgent = new Agent + var agent = new Agent { - Id = agent?.Id ?? Guid.Empty.ToString(), - Name = agent?.Name ?? "Unkown", + Id = BuiltInAgentId.UtilityAssistant, + Name = "Utility Agent", Instruction = !string.IsNullOrWhiteSpace(args?.UserRequest) ? args.UserRequest : "Please describe the image(s).", TemplateDict = new Dictionary() }; - var response = await GetChatCompletion(fileAgent, dialogs); + if (!string.IsNullOrEmpty(message.CurrentAgentId)) + { + agent = await agentService.LoadAgent(message.CurrentAgentId, loadUtility: false); + } + + var response = await GetChatCompletion(agent, dialogs); message.Content = response; return true; } diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs index 50151513..244a3a73 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs @@ -1,5 +1,7 @@ using BotSharp.Abstraction.Files.Utilities; +using BotSharp.Abstraction.Templating; using OpenAI.Chat; +using static System.Net.Mime.MediaTypeNames; namespace BotSharp.Plugin.OpenAI.Providers.Chat; @@ -208,7 +210,9 @@ public class ChatCompletionProvider : IChatCompletion MaxOutputTokenCount = maxTokens }; - foreach (var function in agent.Functions) + + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { if (!agentService.RenderFunction(agent, function)) continue; @@ -220,10 +224,10 @@ public class ChatCompletionProvider : IChatCompletion functionParameters: BinaryData.FromObjectAsJson(property))); } - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { - var instruction = agentService.RenderedInstruction(agent); - messages.Add(new SystemChatMessage(instruction)); + var text = agentService.RenderedInstruction(agent); + messages.Add(new SystemChatMessage(text)); } if (!string.IsNullOrEmpty(agent.Knowledges)) diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs index 7ab56b5d..1f73a71d 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs @@ -9,10 +9,12 @@ public class ProviderHelper { var settingsService = services.GetRequiredService(); var settings = settingsService.GetSetting(provider, model); - var options = string.IsNullOrEmpty(settings.Endpoint) - ? null - : new OpenAIClientOptions { Endpoint = new Uri(settings.Endpoint) }; - return new OpenAIClient(new ApiKeyCredential(settings.ApiKey), options); + //var options = string.IsNullOrEmpty(settings.Endpoint) + // ? null + // : new OpenAIClientOptions { Endpoint = new Uri(settings.Endpoint) }; + //return new OpenAIClient(new ApiKeyCredential(settings.ApiKey), options); + var client = new OpenAIClient(new ApiKeyCredential(settings.ApiKey)); + return client; } public static List GetChatSamples(List lines) From 1d964f59a63f3c98c5d70eec62d713f54e57dfba Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Sun, 22 Dec 2024 16:37:08 -0600 Subject: [PATCH 2/6] clean code --- .../BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs index 1f73a71d..b385b380 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/ProviderHelper.cs @@ -9,10 +9,6 @@ public class ProviderHelper { var settingsService = services.GetRequiredService(); var settings = settingsService.GetSetting(provider, model); - //var options = string.IsNullOrEmpty(settings.Endpoint) - // ? null - // : new OpenAIClientOptions { Endpoint = new Uri(settings.Endpoint) }; - //return new OpenAIClient(new ApiKeyCredential(settings.ApiKey), options); var client = new OpenAIClient(new ApiKeyCredential(settings.ApiKey)); return client; } From b8a550c934611b34e81f38150093741139d2a650 Mon Sep 17 00:00:00 2001 From: Chen Gong Date: Tue, 24 Dec 2024 13:21:18 -0600 Subject: [PATCH 3/6] add agent level knowledge base --- .../Agents/Enums/AgentField.cs | 1 + .../Agents/Models/Agent.cs | 5 ++++ .../Agents/Models/AgentKnowledgeBase.cs | 23 ++++++++++++++++ .../Services/AgentService.UpdateAgent.cs | 1 + .../FileRepository/FileRepository.Agent.cs | 17 ++++++++++++ .../ViewModels/Agents/AgentUpdateModel.cs | 8 ++++++ .../ViewModels/Agents/AgentViewModel.cs | 4 +++ .../Collections/AgentDocument.cs | 1 + .../Models/AgentKnowledgeBaseMongoElement.cs | 26 +++++++++++++++++++ .../Repository/MongoRepository.Agent.cs | 18 +++++++++++++ 10 files changed, 104 insertions(+) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentKnowledgeBase.cs create mode 100644 src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentKnowledgeBaseMongoElement.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs index 34e8ac19..346bcf31 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs @@ -18,6 +18,7 @@ public enum AgentField Sample, LlmConfig, Utility, + KnowledgeBase, MaxMessageCount } diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs index 41b3800c..e89b7914 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs @@ -99,6 +99,11 @@ public class Agent /// public List Utilities { get; set; } = new(); + /// + /// Agent knowledge bases + /// + public List KnowledgeBases { get; set; } = []; + /// /// Inherit from agent /// diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentKnowledgeBase.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentKnowledgeBase.cs new file mode 100644 index 00000000..8727701b --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentKnowledgeBase.cs @@ -0,0 +1,23 @@ +namespace BotSharp.Abstraction.Agents.Models; + +public class AgentKnowledgeBase +{ + public string? Name { get; set; } + public bool Disabled { get; set; } + + public AgentKnowledgeBase() + { + + } + + public AgentKnowledgeBase(string name, bool enabled) + { + Name = name; + Disabled = enabled; + } + + public override string ToString() + { + return Name ?? string.Empty; + } +} diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs index ffea8f8d..31585a09 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs @@ -39,6 +39,7 @@ public partial class AgentService record.Responses = agent.Responses ?? []; record.Samples = agent.Samples ?? []; record.Utilities = agent.Utilities ?? []; + record.KnowledgeBases = agent.KnowledgeBases ?? []; if (agent.LlmConfig != null && !agent.LlmConfig.IsInherit) { record.LlmConfig = agent.LlmConfig; diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs index a838870f..0a8d5b65 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs @@ -57,6 +57,9 @@ namespace BotSharp.Core.Repository case AgentField.Utility: UpdateAgentUtilities(agent.Id, agent.MergeUtility, agent.Utilities); break; + case AgentField.KnowledgeBase: + UpdateAgentKnowledgeBases(agent.Id, agent.KnowledgeBases); + break; case AgentField.MaxMessageCount: UpdateAgentMaxMessageCount(agent.Id, agent.MaxMessageCount); break; @@ -168,6 +171,19 @@ namespace BotSharp.Core.Repository File.WriteAllText(agentFile, json); } + private void UpdateAgentKnowledgeBases(string agentId, List knowledgeBases) + { + if (knowledgeBases == null) return; + + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + agent.KnowledgeBases = knowledgeBases; + agent.UpdatedDateTime = DateTime.UtcNow; + var json = JsonSerializer.Serialize(agent, _options); + File.WriteAllText(agentFile, json); + } + private void UpdateAgentRoutingRules(string agentId, List rules) { if (rules == null) return; @@ -310,6 +326,7 @@ namespace BotSharp.Core.Repository agent.Type = inputAgent.Type; agent.Profiles = inputAgent.Profiles; agent.Utilities = inputAgent.Utilities; + agent.KnowledgeBases = inputAgent.KnowledgeBases; agent.RoutingRules = inputAgent.RoutingRules; agent.LlmConfig = inputAgent.LlmConfig; agent.MaxMessageCount = inputAgent.MaxMessageCount; diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs index 141f0662..66618186 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs @@ -39,6 +39,13 @@ public class AgentUpdateModel /// public List? Utilities { get; set; } + /// + /// knowledge bases + /// + /// + [JsonPropertyName("knowledge_bases")] + public List? KnowledgeBases { get; set; } + /// /// Functions /// @@ -90,6 +97,7 @@ public class AgentUpdateModel Functions = Functions ?? new List(), Responses = Responses ?? new List(), Utilities = Utilities ?? new List(), + KnowledgeBases = KnowledgeBases ?? [], LlmConfig = LlmConfig }; diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs index 36a8900f..e9479109 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs @@ -25,6 +25,9 @@ public class AgentViewModel public bool MergeUtility { get; set; } public List Utilities { get; set; } + [JsonPropertyName("knowledge_bases")] + public List KnowledgeBases { get; set; } + [JsonPropertyName("is_public")] public bool IsPublic { get; set; } @@ -75,6 +78,7 @@ public class AgentViewModel Responses = agent.Responses, Samples = agent.Samples, Utilities = agent.Utilities, + KnowledgeBases = agent.KnowledgeBases, IsPublic= agent.IsPublic, Disabled = agent.Disabled, MergeUtility = agent.MergeUtility, diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs index 3a775025..19945124 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs @@ -18,6 +18,7 @@ public class AgentDocument : MongoBase public List Responses { get; set; } public List Samples { get; set; } public List Utilities { get; set; } + public List KnowledgeBases { get; set; } public List Profiles { get; set; } public List RoutingRules { get; set; } public AgentLlmConfigMongoElement? LlmConfig { get; set; } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentKnowledgeBaseMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentKnowledgeBaseMongoElement.cs new file mode 100644 index 00000000..f9ee8c34 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentKnowledgeBaseMongoElement.cs @@ -0,0 +1,26 @@ +using BotSharp.Abstraction.Agents.Models; + +namespace BotSharp.Plugin.MongoStorage.Models; + +public class AgentKnowledgeBaseMongoElement +{ + public string Name { get; set; } + public bool Disabled { get; set; } + public static AgentKnowledgeBaseMongoElement ToMongoElement(AgentKnowledgeBase knowledgeBase) + { + return new AgentKnowledgeBaseMongoElement + { + Name = knowledgeBase.Name ?? string.Empty, + Disabled = knowledgeBase.Disabled, + }; + } + + public static AgentKnowledgeBase ToDomainElement(AgentKnowledgeBaseMongoElement knowledgeBase) + { + return new AgentKnowledgeBase + { + Name = knowledgeBase.Name, + Disabled = knowledgeBase.Disabled + }; + } +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs index 9bd72e3e..afa6a5a9 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs @@ -58,6 +58,9 @@ public partial class MongoRepository case AgentField.Utility: UpdateAgentUtilities(agent.Id, agent.MergeUtility, agent.Utilities); break; + case AgentField.KnowledgeBase: + UpdateAgentKnowledgeBases(agent.Id, agent.KnowledgeBases); + break; case AgentField.MaxMessageCount: UpdateAgentMaxMessageCount(agent.Id, agent.MaxMessageCount); break; @@ -239,6 +242,20 @@ public partial class MongoRepository _dc.Agents.UpdateOne(filter, update); } + private void UpdateAgentKnowledgeBases(string agentId, List knowledgeBases) + { + if (knowledgeBases == null) return; + + var elements = knowledgeBases?.Select(x => AgentKnowledgeBaseMongoElement.ToMongoElement(x))?.ToList() ?? []; + + var filter = Builders.Filter.Eq(x => x.Id, agentId); + var update = Builders.Update + .Set(x => x.KnowledgeBases, elements) + .Set(x => x.UpdatedTime, DateTime.UtcNow); + + _dc.Agents.UpdateOne(filter, update); + } + private void UpdateAgentLlmConfig(string agentId, AgentLlmConfig? config) { var llmConfig = AgentLlmConfigMongoElement.ToMongoElement(config); @@ -279,6 +296,7 @@ public partial class MongoRepository .Set(x => x.Responses, agent.Responses.Select(r => AgentResponseMongoElement.ToMongoElement(r)).ToList()) .Set(x => x.Samples, agent.Samples) .Set(x => x.Utilities, agent.Utilities.Select(u => AgentUtilityMongoElement.ToMongoElement(u)).ToList()) + .Set(x => x.KnowledgeBases, agent.KnowledgeBases.Select(u => AgentKnowledgeBaseMongoElement.ToMongoElement(u)).ToList()) .Set(x => x.LlmConfig, AgentLlmConfigMongoElement.ToMongoElement(agent.LlmConfig)) .Set(x => x.IsPublic, agent.IsPublic) .Set(x => x.UpdatedTime, DateTime.UtcNow); From ac72106e11b3394fcb3cb238cd2ccbe7ac75c25e Mon Sep 17 00:00:00 2001 From: Jicheng Lu Date: Thu, 26 Dec 2024 00:18:02 -0600 Subject: [PATCH 4/6] clean code --- .../Agents/Services/AgentService.Rendering.cs | 7 ++++--- .../Providers/ChatCompletionProvider.cs | 5 +++-- .../Providers/Chat/ChatCompletionProvider.cs | 5 +++-- .../Providers/Chat/GeminiChatCompletionProvider.cs | 5 +++-- .../Providers/Chat/PalmChatCompletionProvider.cs | 7 ++++--- .../Providers/ChatCompletionProvider.cs | 7 +++++-- .../MicrosoftExtensionsAIChatCompletionProvider.cs | 3 ++- .../Providers/Chat/ChatCompletionProvider.cs | 1 - .../Providers/ChatCompletionProvider.cs | 5 +++-- 9 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index b0038f35..d217d2c1 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs @@ -12,8 +12,9 @@ public partial class AgentService var conv = _services.GetRequiredService(); // merge instructions - var texts = new List { agent.Instruction }; - texts.AddRange(agent.SecondaryInstructions ?? []); + var instructions = new List { agent.Instruction }; + var secondaryInstructions = agent.SecondaryInstructions?.Where(x => !string.IsNullOrWhiteSpace(x)).ToList() ?? []; + instructions.AddRange(secondaryInstructions); // update states foreach (var t in conv.States.GetStates()) @@ -21,7 +22,7 @@ public partial class AgentService agent.TemplateDict[t.Key] = t.Value; } - var res = render.Render(string.Join("\r\n", texts), agent.TemplateDict); + var res = render.Render(string.Join("\r\n", instructions), agent.TemplateDict); return res; } diff --git a/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs index 8b90d29f..45ef200e 100644 --- a/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs @@ -101,7 +101,7 @@ public class ChatCompletionProvider : IChatCompletion var agentService = _services.GetRequiredService(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { instruction += agentService.RenderedInstruction(agent); } @@ -197,7 +197,8 @@ public class ChatCompletionProvider : IChatCompletion ReferenceHandler = ReferenceHandler.IgnoreCycles, }; - foreach (var fn in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var fn in functions) { /*var inputschema = new InputSchema() { diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs index a1684c9d..bfce9d98 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs @@ -230,7 +230,8 @@ public class ChatCompletionProvider : IChatCompletion MaxOutputTokenCount = maxTokens }; - foreach (var function in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { if (!agentService.RenderFunction(agent, function)) continue; @@ -242,7 +243,7 @@ public class ChatCompletionProvider : IChatCompletion functionParameters: BinaryData.FromObjectAsJson(property))); } - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { var instruction = agentService.RenderedInstruction(agent); messages.Add(new SystemChatMessage(instruction)); diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs index 4419048b..c37284b0 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs @@ -107,7 +107,7 @@ public class GeminiChatCompletionProvider : IChatCompletion var funcDeclarations = new List(); var systemPrompts = new List(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { var instruction = agentService.RenderedInstruction(agent); contents.Add(new Content(instruction) @@ -119,7 +119,8 @@ public class GeminiChatCompletionProvider : IChatCompletion } var funcPrompts = new List(); - foreach (var function in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { if (!agentService.RenderFunction(agent, function)) continue; diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs index 851792a6..5c507ee9 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs @@ -99,7 +99,7 @@ public class PalmChatCompletionProvider : IChatCompletion var agentService = _services.GetRequiredService(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { prompt += agentService.RenderedInstruction(agent); } @@ -110,10 +110,11 @@ public class PalmChatCompletionProvider : IChatCompletion var messages = conversations.Select(c => new PalmChatMessage(c.Content, c.Role == AgentRole.User ? "user" : "AI")) .ToList(); - if (agent.Functions != null && agent.Functions.Count > 0) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + if (!functions.IsNullOrEmpty()) { prompt += "\r\n\r\n[Functions] defined in JSON Schema:\r\n"; - prompt += JsonSerializer.Serialize(agent.Functions, new JsonSerializerOptions + prompt += JsonSerializer.Serialize(functions, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true diff --git a/src/Plugins/BotSharp.Plugin.MetaGLM/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.MetaGLM/Providers/ChatCompletionProvider.cs index c702a7ec..f99293f4 100644 --- a/src/Plugins/BotSharp.Plugin.MetaGLM/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.MetaGLM/Providers/ChatCompletionProvider.cs @@ -1,3 +1,5 @@ +using BotSharp.Abstraction.Utilities; + namespace BotSharp.Plugin.MetaGLM.Providers; public class ChatCompletionProvider : IChatCompletion @@ -86,7 +88,7 @@ public class ChatCompletionProvider : IChatCompletion List messages = new List(); List toolcalls = new List(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { var instruction = agentService.RenderedInstruction(agent); messages.Add(new MessageItem("system", instruction)); @@ -105,7 +107,8 @@ public class ChatCompletionProvider : IChatCompletion new MessageItem("assistant", message.Content)); } - foreach (var function in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { var functionTool = ConvertToFunctionTool(function); toolcalls.Add(functionTool); diff --git a/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs index 67f1e513..37869050 100644 --- a/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs @@ -66,7 +66,8 @@ public sealed class MicrosoftExtensionsAIChatCompletionProvider : IChatCompletio if (_services.GetService() is { } agentService) { - foreach (var function in agent.Functions) + var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in functions) { if (agentService.RenderFunction(agent, function)) { diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs index 845cd978..6f424c33 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs @@ -210,7 +210,6 @@ public class ChatCompletionProvider : IChatCompletion MaxOutputTokenCount = maxTokens }; - var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []); foreach (var function in functions) { diff --git a/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs index d15345e6..5edf4708 100644 --- a/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.SparkDesk/Providers/ChatCompletionProvider.cs @@ -176,7 +176,7 @@ public class ChatCompletionProvider : IChatCompletion var agentService = _services.GetRequiredService(); var messages = new List(); - if (!string.IsNullOrEmpty(agent.Instruction)) + if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty()) { var instruction = agentService.RenderedInstruction(agent); messages.Add(ChatMessage.FromSystem(instruction)); @@ -193,7 +193,8 @@ public class ChatCompletionProvider : IChatCompletion ChatMessage.FromAssistant(message.Content)); } - foreach (var function in agent.Functions) + var agentFuncs = agent.Functions.Concat(agent.SecondaryFunctions ?? []); + foreach (var function in agentFuncs) { functions.Add(ConvertToFunctionDef(function)); } From 83b3dbd97415f54d9fbc2e2eebd1aafcaffe456d Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Thu, 26 Dec 2024 09:55:59 -0600 Subject: [PATCH 5/6] refine ai client --- .../Providers/Chat/GeminiChatCompletionProvider.cs | 4 ++-- .../Providers/Chat/PalmChatCompletionProvider.cs | 4 ++-- .../Providers/ProviderHelper.cs | 14 ++++++++------ .../Providers/Text/GeminiTextCompletionProvider.cs | 4 ++-- .../Providers/Text/PalmTextCompletionProvider.cs | 4 ++-- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs index c37284b0..b52013dd 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs @@ -13,7 +13,7 @@ public class GeminiChatCompletionProvider : IChatCompletion private string _model; - public string Provider => "google-gemini"; + public string Provider => "google-ai"; public GeminiChatCompletionProvider( IServiceProvider services, @@ -33,7 +33,7 @@ public class GeminiChatCompletionProvider : IChatCompletion await hook.BeforeGenerating(agent, conversations); } - var client = ProviderHelper.GetGeminiClient(_services); + var client = ProviderHelper.GetGeminiClient(Provider, _model, _services); var aiModel = client.GenerativeModel(_model); var (prompt, request) = PrepareOptions(aiModel, agent, conversations); diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs index 5c507ee9..c62aebb8 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs @@ -16,7 +16,7 @@ public class PalmChatCompletionProvider : IChatCompletion private string _model; - public string Provider => "google-ai"; + public string Provider => "google-palm"; public PalmChatCompletionProvider( IServiceProvider services, @@ -36,7 +36,7 @@ public class PalmChatCompletionProvider : IChatCompletion await hook.BeforeGenerating(agent, conversations); } - var client = ProviderHelper.GetPalmClient(_services); + var client = ProviderHelper.GetPalmClient(Provider, _model, _services); var (prompt, messages, hasFunctions) = PrepareOptions(agent, conversations); RoleDialogModel msg; diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/ProviderHelper.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/ProviderHelper.cs index 75435f90..5ca1058a 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/ProviderHelper.cs +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/ProviderHelper.cs @@ -5,17 +5,19 @@ namespace BotSharp.Plugin.GoogleAi.Providers; public static class ProviderHelper { - public static GoogleAI GetGeminiClient(IServiceProvider services) + public static GoogleAI GetGeminiClient(string provider, string model, IServiceProvider services) { - var settings = services.GetRequiredService(); - var client = new GoogleAI(settings.Gemini.ApiKey); + var settingsService = services.GetRequiredService(); + var settings = settingsService.GetSetting(provider, model); + var client = new GoogleAI(settings.ApiKey); return client; } - public static GooglePalmClient GetPalmClient(IServiceProvider services) + public static GooglePalmClient GetPalmClient(string provider, string model, IServiceProvider services) { - var settings = services.GetRequiredService(); - var client = new GooglePalmClient(settings.PaLM.ApiKey); + var settingsService = services.GetRequiredService(); + var settings = settingsService.GetSetting(provider, model); + var client = new GooglePalmClient(settings.ApiKey); return client; } } diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Text/GeminiTextCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Text/GeminiTextCompletionProvider.cs index e6e3f4b3..e14071f7 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Text/GeminiTextCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Text/GeminiTextCompletionProvider.cs @@ -13,7 +13,7 @@ public class GeminiTextCompletionProvider : ITextCompletion private readonly ITokenStatistics _tokenStatistics; private string _model; - public string Provider => "google-gemini"; + public string Provider => "google-ai"; public GeminiTextCompletionProvider( IServiceProvider services, @@ -45,7 +45,7 @@ public class GeminiTextCompletionProvider : ITextCompletion await hook.BeforeGenerating(agent, new List { userMessage }); } - var client = ProviderHelper.GetGeminiClient(_services); + var client = ProviderHelper.GetGeminiClient(Provider, _model, _services); var aiModel = client.GenerativeModel(_model); PrepareOptions(aiModel); diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Text/PalmTextCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Text/PalmTextCompletionProvider.cs index c7e64fe8..ebaf6c5f 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Text/PalmTextCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Text/PalmTextCompletionProvider.cs @@ -13,7 +13,7 @@ public class PalmTextCompletionProvider : ITextCompletion private string _model; - public string Provider => "google-ai"; + public string Provider => "google-palm"; public PalmTextCompletionProvider( IServiceProvider services, @@ -38,7 +38,7 @@ public class PalmTextCompletionProvider : ITextCompletion await hook.BeforeGenerating(agent, new List { userMessage }); } - var client = ProviderHelper.GetPalmClient(_services); + var client = ProviderHelper.GetPalmClient(Provider, _model, _services); _tokenStatistics.StartTimer(); var response = await client.GenerateTextAsync(text, null); _tokenStatistics.StopTimer(); From 8c8dc1e6a268d982a5e6165e7991d6820e88f657 Mon Sep 17 00:00:00 2001 From: Joanna Ren <101223@smsassist.com> Date: Thu, 26 Dec 2024 21:56:25 -0600 Subject: [PATCH 6/6] update sql button render --- .../Handlers/RouteToAgentRoutingHandler.cs | 2 +- .../Hooks/SqlDriverPlanningHook.cs | 51 ++++++++++--------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index c26174a1..f79c6719 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -31,7 +31,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler type: "boolean", required: true), new ParameterPropertyDef("is_new_task", - "whether the user is requesting a new task that is different from the previous topic.", + "whether the user is requesting a new task that is different from the previous topic. Set the first round of conversation to false.", type: "boolean") }; diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverPlanningHook.cs b/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverPlanningHook.cs index 224f8fd6..bb008319 100644 --- a/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverPlanningHook.cs +++ b/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverPlanningHook.cs @@ -23,9 +23,9 @@ public class SqlDriverPlanningHook : IPlanningHook public async Task OnSourceCodeGenerated(string planner, RoleDialogModel msg, string language) { // envoke validate - if (language != "sql") - { - return; + if (language != "sql") + { + return; } var routing = _services.GetRequiredService(); @@ -42,7 +42,7 @@ public class SqlDriverPlanningHook : IPlanningHook var conversationStateService = _services.GetRequiredService(); var conversationId = conversationStateService.GetConversationId(); msg.PostbackFunctionName = "execute_sql"; - msg.RichContent = BuildRunQueryButton(planner, msg.Content); + msg.RichContent = BuildRunQueryButton(conversationId, msg.Content); msg.StopCompletion = true; return; } @@ -71,7 +71,7 @@ public class SqlDriverPlanningHook : IPlanningHook public async Task OnPlanningCompleted(string planner, RoleDialogModel msg) { - + } public async Task GetSummaryAdditionalRequirements(string planner, RoleDialogModel message) @@ -91,8 +91,27 @@ public class SqlDriverPlanningHook : IPlanningHook string pattern = @"```sql\s*([\s\S]*?)\s*```"; var sql = Regex.Match(text, pattern).Groups[1].Value; var state = _services.GetRequiredService(); - var deleteTable = state.GetState("tmp_table"); - var deleteSql = $"DROP TABLE IF EXISTS {deleteTable};"; + var tmpTable = state.GetState("tmp_table"); + + var elements = new List() { }; + elements.Add(new ElementButton + { + Type = "text", + Title = "Execute SQL Statement", + Payload = sql, + IsPrimary = true + }); + + if (tmpTable != string.Empty) + { + var deleteSql = $"DROP TABLE IF EXISTS {tmpTable};"; + elements.Add(new ElementButton + { + Type = "text", + Title = "Delete Temp Table", + Payload = deleteSql + }); + } return new RichContent { @@ -105,23 +124,9 @@ public class SqlDriverPlanningHook : IPlanningHook Message = new ButtonTemplateMessage { Text = text, - Buttons = new List - { - new ElementButton - { - Type = "text", - Title = "Execute the SQL Statement", - Payload = sql, - IsPrimary = true - }, - new ElementButton - { - Type = "text", - Title = "Purge Cache", - Payload = deleteSql - } - }.ToArray() + Buttons = elements.ToArray() } }; + } }