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/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..540f13ca 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
///
@@ -118,6 +123,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.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/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..d217d2c1 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs
@@ -11,13 +11,18 @@ public partial class AgentService
var render = _services.GetRequiredService();
var conv = _services.GetRequiredService();
+ // merge instructions
+ 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())
{
agent.TemplateDict[t.Key] = t.Value;
}
- var res = render.Render(agent.Instruction, agent.TemplateDict);
+ var res = render.Render(string.Join("\r\n", instructions), agent.TemplateDict);
return res;
}
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.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/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.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.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.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs
index 4419048b..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);
@@ -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..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;
@@ -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.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();
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.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);
diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.cs
index c5d45f66..6f424c33 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,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;
@@ -220,10 +223,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.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));
}
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()
}
};
+
}
}