diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs index 0a8b38e8..669ebaba 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs @@ -14,5 +14,6 @@ public enum AgentField Function, Template, Response, - Sample + Sample, + LlmConfig } diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs index 3e127125..7cf8750d 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs @@ -71,6 +71,12 @@ public class Agent public List RoutingRules { get; set; } = new List(); + /// + /// Agent LLM Config, i.e., provider & model + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public AgentLlmConfig? LlmConfig { get; set; } + /// /// For rendering deferral /// @@ -181,4 +187,10 @@ public class Agent RoutingRules = rules ?? new List(); return this; } + + public Agent SetLlmConfig(AgentLlmConfig? llmConfig) + { + LlmConfig = llmConfig; + return this; + } } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs index be9ef658..b88322dc 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs @@ -39,7 +39,8 @@ public partial class AgentService .SetInstruction(foundAgent.Instruction) .SetTemplates(foundAgent.Templates) .SetFunctions(foundAgent.Functions) - .SetResponses(foundAgent.Responses); + .SetResponses(foundAgent.Responses) + .SetLlmConfig(foundAgent.LlmConfig); } var user = _db.GetUserById(_user.Id); diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs index 292b83bb..e0a225e2 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs @@ -27,6 +27,7 @@ public partial class AgentService record.Templates = agent.Templates ?? new List(); record.Responses = agent.Responses ?? new List(); record.Samples = agent.Samples ?? new List(); + record.LlmConfig = agent.LlmConfig; _db.UpdateAgent(record, updateField); await Task.CompletedTask; @@ -58,7 +59,8 @@ public partial class AgentService .SetTemplates(foundAgent.Templates) .SetFunctions(foundAgent.Functions) .SetResponses(foundAgent.Responses) - .SetSamples(foundAgent.Samples); + .SetSamples(foundAgent.Samples) + .SetLlmConfig(foundAgent.LlmConfig); _db.UpdateAgent(clonedAgent, AgentField.All); } diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs index 8b90ae79..c5b22d89 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs @@ -246,6 +246,9 @@ public class FileRepository : IBotSharpRepository case AgentField.Sample: UpdateAgentSamples(agent.Id, agent.Samples); break; + case AgentField.LlmConfig: + UpdateAgentLlmConfig(agent.Id, agent.LlmConfig); + break; case AgentField.All: UpdateAgentAllFields(agent); break; @@ -431,6 +434,17 @@ public class FileRepository : IBotSharpRepository File.WriteAllLines(file, samples); } + private void UpdateAgentLlmConfig(string agentId, AgentLlmConfig? config) + { + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + agent.LlmConfig = config; + agent.UpdatedDateTime = DateTime.UtcNow; + var json = JsonSerializer.Serialize(agent, _options); + File.WriteAllText(agentFile, json); + } + private void UpdateAgentAllFields(Agent inputAgent) { var (agent, agentFile) = GetAgentFromFile(inputAgent.Id); @@ -493,10 +507,10 @@ public class FileRepository : IBotSharpRepository var templates = FetchTemplates(dir); var responses = FetchResponses(dir); return record.SetInstruction(instruction) - .SetFunctions(functions) - .SetSamples(samples) - .SetTemplates(templates) - .SetResponses(responses); + .SetFunctions(functions) + .SetSamples(samples) + .SetTemplates(templates) + .SetResponses(responses); } return null; diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs index eb84453c..12d17e51 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs @@ -149,4 +149,12 @@ public class AgentController : ControllerBase, IApiAdapter model.Id = agentId; await _agentService.UpdateAgent(model, AgentField.Sample); } + + [HttpPut("/agent/{agentId}/llm-config")] + public async Task UpdateAgentLlmConfig([FromRoute] string agentId, [FromBody] AgentUpdateModel agent) + { + var model = agent.ToAgent(); + model.Id = agentId; + await _agentService.UpdateAgent(model, AgentField.LlmConfig); + } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs index 9af1dda6..fe6ce7e2 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentCreationModel.cs @@ -43,6 +43,7 @@ public class AgentCreationModel /// public List Profiles { get; set; } = new List(); public List RoutingRules { get; set; } = new List(); + public AgentLlmConfig? LlmConfig { get; set; } public Agent ToAgent() { @@ -61,7 +62,8 @@ public class AgentCreationModel Profiles = Profiles, RoutingRules = RoutingRules? .Select(x => RoutingRuleUpdateModel.ToDomainElement(x))? - .ToList() ?? new List() + .ToList() ?? new List(), + LlmConfig = LlmConfig }; } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs index c340b57a..b394b3bb 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentUpdateModel.cs @@ -47,6 +47,8 @@ public class AgentUpdateModel public List? RoutingRules { get; set; } + public AgentLlmConfig? LlmConfig { get; set; } + public Agent ToAgent() { var agent = new Agent() @@ -63,7 +65,8 @@ public class AgentUpdateModel Instruction = Instruction ?? string.Empty, Templates = Templates ?? new List(), Functions = Functions ?? new List(), - Responses = Responses ?? new List() + Responses = Responses ?? new List(), + LlmConfig = LlmConfig }; return agent; diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs index 2ef67efd..c09f417a 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs @@ -26,6 +26,10 @@ public class AgentViewModel [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public List RoutingRules { get; set; } + [JsonPropertyName("llmConfig")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public AgentLlmConfig? LlmConfig { get; set; } + [JsonPropertyName("created_datetime")] public DateTime CreatedDateTime { get; set; } @@ -49,6 +53,7 @@ public class AgentViewModel AllowRouting = agent.AllowRouting, Profiles = agent.Profiles, RoutingRules = agent.RoutingRules, + LlmConfig = agent.LlmConfig, CreatedDateTime = agent.CreatedDateTime, UpdatedDateTime = agent.UpdatedDateTime }; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs index 5e7c2f35..c9e7298b 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs @@ -16,6 +16,7 @@ public class AgentDocument : MongoBase public bool Disabled { get; set; } public List Profiles { get; set; } public List RoutingRules { get; set; } + public AgentLlmConfigMongoElement? LlmConfig { get; set; } public DateTime CreatedTime { get; set; } public DateTime UpdatedTime { get; set; } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentLlmConfigMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentLlmConfigMongoElement.cs new file mode 100644 index 00000000..f5217fd5 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentLlmConfigMongoElement.cs @@ -0,0 +1,31 @@ +using BotSharp.Abstraction.Agents.Models; + +namespace BotSharp.Plugin.MongoStorage.Models; + +public class AgentLlmConfigMongoElement +{ + public string? Provider { get; set; } + public string Model { get; set; } + + public static AgentLlmConfigMongoElement? ToMongoElement(AgentLlmConfig? config) + { + if (config == null) return null; + + return new AgentLlmConfigMongoElement + { + Provider = config.Provider, + Model = config.Model + }; + } + + public static AgentLlmConfig? ToDomainElement(AgentLlmConfigMongoElement? config) + { + if (config == null) return null; + + return new AgentLlmConfig + { + Provider = config.Provider, + Model = config.Model + }; + } +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs index cc7ea6e0..0dc83366 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs @@ -82,6 +82,7 @@ public class MongoRepository : IBotSharpRepository RoutingRules = x.RoutingRules? .Select(r => RoutingRuleMongoElement.ToMongoElement(r))? .ToList() ?? new List(), + LlmConfig = AgentLlmConfigMongoElement.ToMongoElement(x.LlmConfig), CreatedTime = x.CreatedDateTime, UpdatedTime = x.UpdatedDateTime }).ToList(); @@ -102,6 +103,7 @@ public class MongoRepository : IBotSharpRepository .Set(x => x.Disabled, agent.Disabled) .Set(x => x.Profiles, agent.Profiles) .Set(x => x.RoutingRules, agent.RoutingRules) + .Set(x => x.LlmConfig, agent.LlmConfig) .Set(x => x.CreatedTime, agent.CreatedTime) .Set(x => x.UpdatedTime, agent.UpdatedTime); _dc.Agents.UpdateOne(filter, update, _options); @@ -211,6 +213,9 @@ public class MongoRepository : IBotSharpRepository case AgentField.Sample: UpdateAgentSamples(agent.Id, agent.Samples); break; + case AgentField.LlmConfig: + UpdateAgentLlmConfig(agent.Id, agent.LlmConfig); + break; case AgentField.All: UpdateAgentAllFields(agent); break; @@ -362,6 +367,17 @@ public class MongoRepository : IBotSharpRepository _dc.Agents.UpdateOne(filter, update); } + private void UpdateAgentLlmConfig(string agentId, AgentLlmConfig? config) + { + var llmConfig = AgentLlmConfigMongoElement.ToMongoElement(config); + var filter = Builders.Filter.Eq(x => x.Id, agentId); + var update = Builders.Update + .Set(x => x.LlmConfig, llmConfig) + .Set(x => x.UpdatedTime, DateTime.UtcNow); + + _dc.Agents.UpdateOne(filter, update); + } + private void UpdateAgentAllFields(Agent agent) { var filter = Builders.Filter.Eq(x => x.Id, agent.Id); @@ -377,6 +393,7 @@ public class MongoRepository : IBotSharpRepository .Set(x => x.Functions, agent.Functions.Select(f => FunctionDefMongoElement.ToMongoElement(f)).ToList()) .Set(x => x.Responses, agent.Responses.Select(r => AgentResponseMongoElement.ToMongoElement(r)).ToList()) .Set(x => x.Samples, agent.Samples) + .Set(x => x.LlmConfig, AgentLlmConfigMongoElement.ToMongoElement(agent.LlmConfig)) .Set(x => x.IsPublic, agent.IsPublic) .Set(x => x.UpdatedTime, DateTime.UtcNow); @@ -413,7 +430,8 @@ public class MongoRepository : IBotSharpRepository Profiles = agent.Profiles, RoutingRules = !agent.RoutingRules.IsNullOrEmpty() ? agent.RoutingRules .Select(r => RoutingRuleMongoElement.ToDomainElement(agent.Id, agent.Name, r)) - .ToList() : new List() + .ToList() : new List(), + LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(agent.LlmConfig) }; } @@ -469,7 +487,8 @@ public class MongoRepository : IBotSharpRepository Profiles = x.Profiles, RoutingRules = !x.RoutingRules.IsNullOrEmpty() ? x.RoutingRules .Select(r => RoutingRuleMongoElement.ToDomainElement(x.Id, x.Name, r)) - .ToList() : new List() + .ToList() : new List(), + LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(x.LlmConfig) }).ToList(); } @@ -482,8 +501,8 @@ public class MongoRepository : IBotSharpRepository var filter = new AgentFilter { - IsPublic = true, - AgentIds = agentIds + AgentIds = agentIds, + IsPublic = true }; var agents = GetAgents(filter); return agents; @@ -533,6 +552,7 @@ public class MongoRepository : IBotSharpRepository RoutingRules = x.RoutingRules? .Select(r => RoutingRuleMongoElement.ToMongoElement(r))? .ToList() ?? new List(), + LlmConfig = AgentLlmConfigMongoElement.ToMongoElement(x.LlmConfig), CreatedTime = x.CreatedDateTime, UpdatedTime = x.UpdatedDateTime }).ToList();