add agent llm config

This commit is contained in:
Jicheng Lu 2023-12-13 14:26:46 -06:00
parent e51c47365a
commit 92ff9e6f3c
22 changed files with 133 additions and 24 deletions

View file

@ -14,5 +14,6 @@ public enum AgentField
Function, Function,
Template, Template,
Response, Response,
Sample Sample,
LlmConfig
} }

View file

@ -66,6 +66,12 @@ public class Agent
public List<RoutingRule> RoutingRules { get; set; } public List<RoutingRule> RoutingRules { get; set; }
= new List<RoutingRule>(); = new List<RoutingRule>();
/// <summary>
/// Agent LLM Config, i.e., provider & model
/// </summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public AgentLlmConfig? LlmConfig { get; set; }
/// <summary> /// <summary>
/// For rendering deferral /// For rendering deferral
/// </summary> /// </summary>
@ -176,4 +182,10 @@ public class Agent
RoutingRules = rules ?? new List<RoutingRule>(); RoutingRules = rules ?? new List<RoutingRule>();
return this; return this;
} }
public Agent SetLlmConfig(AgentLlmConfig? llmConfig)
{
LlmConfig = llmConfig;
return this;
}
} }

View file

@ -0,0 +1,9 @@
namespace BotSharp.Abstraction.Agents.Models;
public class AgentLlmConfig
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Provider { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string Model { get; set; }
}

View file

@ -2,7 +2,7 @@ namespace BotSharp.Abstraction.Evaluations.Settings;
public class EvaluatorSetting public class EvaluatorSetting
{ {
public string EvaluatorId { get; set; } public string AgentId { get; set; }
public string Provider { get; set; } public string Provider { get; set; }
public string Model { get; set; } public string Model { get; set; }
} }

View file

@ -22,14 +22,14 @@ public class RoutingContext
/// Agent that can handl user original goal. /// Agent that can handl user original goal.
/// </summary> /// </summary>
public string OriginAgentId public string OriginAgentId
=> _stack.Where(x => x != _setting.RouterId).Last(); => _stack.Where(x => x != _setting.AgentId).Last();
public bool IsEmpty => !_stack.Any(); public bool IsEmpty => !_stack.Any();
public string GetCurrentAgentId() public string GetCurrentAgentId()
{ {
if (_stack.Count == 0) if (_stack.Count == 0)
{ {
_stack.Push(_setting.RouterId); _stack.Push(_setting.AgentId);
} }
return _stack.Peek(); return _stack.Peek();
} }

View file

@ -5,7 +5,7 @@ public class RoutingSettings
/// <summary> /// <summary>
/// Router Agent Id /// Router Agent Id
/// </summary> /// </summary>
public string RouterId { get; set; } = string.Empty; public string AgentId { get; set; } = string.Empty;
public string Planner { get; set; } = string.Empty; public string Planner { get; set; } = string.Empty;
public string Provider { get; set; } = string.Empty; public string Provider { get; set; } = string.Empty;

View file

@ -39,7 +39,8 @@ public partial class AgentService
.SetInstruction(foundAgent.Instruction) .SetInstruction(foundAgent.Instruction)
.SetTemplates(foundAgent.Templates) .SetTemplates(foundAgent.Templates)
.SetFunctions(foundAgent.Functions) .SetFunctions(foundAgent.Functions)
.SetResponses(foundAgent.Responses); .SetResponses(foundAgent.Responses)
.SetLlmConfig(foundAgent.LlmConfig);
} }
var user = _db.GetUserById(_user.Id); var user = _db.GetUserById(_user.Id);

View file

@ -27,6 +27,7 @@ public partial class AgentService
record.Templates = agent.Templates ?? new List<AgentTemplate>(); record.Templates = agent.Templates ?? new List<AgentTemplate>();
record.Responses = agent.Responses ?? new List<AgentResponse>(); record.Responses = agent.Responses ?? new List<AgentResponse>();
record.Samples = agent.Samples ?? new List<string>(); record.Samples = agent.Samples ?? new List<string>();
record.LlmConfig = agent.LlmConfig;
_db.UpdateAgent(record, updateField); _db.UpdateAgent(record, updateField);
await Task.CompletedTask; await Task.CompletedTask;
@ -58,7 +59,8 @@ public partial class AgentService
.SetTemplates(foundAgent.Templates) .SetTemplates(foundAgent.Templates)
.SetFunctions(foundAgent.Functions) .SetFunctions(foundAgent.Functions)
.SetResponses(foundAgent.Responses) .SetResponses(foundAgent.Responses)
.SetSamples(foundAgent.Samples); .SetSamples(foundAgent.Samples)
.SetLlmConfig(foundAgent.LlmConfig);
_db.UpdateAgent(clonedAgent, AgentField.All); _db.UpdateAgent(clonedAgent, AgentField.All);
} }

View file

@ -59,7 +59,7 @@ public partial class ConversationService
var routing = _services.GetRequiredService<IRoutingService>(); var routing = _services.GetRequiredService<IRoutingService>();
var settings = _services.GetRequiredService<RoutingSettings>(); var settings = _services.GetRequiredService<RoutingSettings>();
response = agentId == settings.RouterId ? response = agentId == settings.AgentId ?
await routing.InstructLoop(message) : await routing.InstructLoop(message) :
await routing.ExecuteDirectly(agent, message); await routing.ExecuteDirectly(agent, message);

View file

@ -20,7 +20,7 @@ public class EvaluatingService : IEvaluatingService
public async Task<Conversation> Execute(string task, EvaluationRequest request) public async Task<Conversation> Execute(string task, EvaluationRequest request)
{ {
var agentService = _services.GetRequiredService<IAgentService>(); var agentService = _services.GetRequiredService<IAgentService>();
var evaluator = await agentService.GetAgent(_settings.EvaluatorId); var evaluator = await agentService.GetAgent(_settings.AgentId);
// Task execution mode // Task execution mode
evaluator.Instruction = evaluator.Templates.First(x => x.Name == "instruction.executor").Content; evaluator.Instruction = evaluator.Templates.First(x => x.Name == "instruction.executor").Content;
var taskPrompt = evaluator.Templates.First(x => x.Name == $"task.{task}").Content; var taskPrompt = evaluator.Templates.First(x => x.Name == $"task.{task}").Content;

View file

@ -246,6 +246,9 @@ public class FileRepository : IBotSharpRepository
case AgentField.Sample: case AgentField.Sample:
UpdateAgentSamples(agent.Id, agent.Samples); UpdateAgentSamples(agent.Id, agent.Samples);
break; break;
case AgentField.LlmConfig:
UpdateAgentLlmConfig(agent.Id, agent.LlmConfig);
break;
case AgentField.All: case AgentField.All:
UpdateAgentAllFields(agent); UpdateAgentAllFields(agent);
break; break;
@ -431,6 +434,17 @@ public class FileRepository : IBotSharpRepository
File.WriteAllLines(file, samples); 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) private void UpdateAgentAllFields(Agent inputAgent)
{ {
var (agent, agentFile) = GetAgentFromFile(inputAgent.Id); var (agent, agentFile) = GetAgentFromFile(inputAgent.Id);
@ -493,10 +507,10 @@ public class FileRepository : IBotSharpRepository
var templates = FetchTemplates(dir); var templates = FetchTemplates(dir);
var responses = FetchResponses(dir); var responses = FetchResponses(dir);
return record.SetInstruction(instruction) return record.SetInstruction(instruction)
.SetFunctions(functions) .SetFunctions(functions)
.SetSamples(samples) .SetSamples(samples)
.SetTemplates(templates) .SetTemplates(templates)
.SetResponses(responses); .SetResponses(responses);
} }
return null; return null;

View file

@ -7,7 +7,7 @@ namespace BotSharp.Core.Routing.Hooks;
public class RoutingAgentHook : AgentHookBase public class RoutingAgentHook : AgentHookBase
{ {
private readonly RoutingSettings _routingSetting; private readonly RoutingSettings _routingSetting;
public override string SelfId => _routingSetting.RouterId; public override string SelfId => _routingSetting.AgentId;
public RoutingAgentHook(IServiceProvider services, AgentSettings settings, RoutingSettings routingSetting) public RoutingAgentHook(IServiceProvider services, AgentSettings settings, RoutingSettings routingSetting)
: base(services, settings) : base(services, settings)

View file

@ -64,7 +64,7 @@ public partial class RoutingService : IRoutingService
public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message) public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message)
{ {
var agentService = _services.GetRequiredService<IAgentService>(); var agentService = _services.GetRequiredService<IAgentService>();
_router = await agentService.LoadAgent(_settings.RouterId); _router = await agentService.LoadAgent(_settings.AgentId);
RoleDialogModel response = default; RoleDialogModel response = default;

View file

@ -149,4 +149,12 @@ public class AgentController : ControllerBase, IApiAdapter
model.Id = agentId; model.Id = agentId;
await _agentService.UpdateAgent(model, AgentField.Sample); 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);
}
} }

View file

@ -43,6 +43,7 @@ public class AgentCreationModel
/// </summary> /// </summary>
public List<string> Profiles { get; set; } = new List<string>(); public List<string> Profiles { get; set; } = new List<string>();
public List<RoutingRuleUpdateModel> RoutingRules { get; set; } = new List<RoutingRuleUpdateModel>(); public List<RoutingRuleUpdateModel> RoutingRules { get; set; } = new List<RoutingRuleUpdateModel>();
public AgentLlmConfig? LlmConfig { get; set; }
public Agent ToAgent() public Agent ToAgent()
{ {
@ -61,7 +62,8 @@ public class AgentCreationModel
Profiles = Profiles, Profiles = Profiles,
RoutingRules = RoutingRules? RoutingRules = RoutingRules?
.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))? .Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?
.ToList() ?? new List<RoutingRule>() .ToList() ?? new List<RoutingRule>(),
LlmConfig = LlmConfig
}; };
} }
} }

View file

@ -47,6 +47,8 @@ public class AgentUpdateModel
public List<RoutingRuleUpdateModel>? RoutingRules { get; set; } public List<RoutingRuleUpdateModel>? RoutingRules { get; set; }
public AgentLlmConfig? LlmConfig { get; set; }
public Agent ToAgent() public Agent ToAgent()
{ {
var agent = new Agent() var agent = new Agent()
@ -63,7 +65,8 @@ public class AgentUpdateModel
Instruction = Instruction ?? string.Empty, Instruction = Instruction ?? string.Empty,
Templates = Templates ?? new List<AgentTemplate>(), Templates = Templates ?? new List<AgentTemplate>(),
Functions = Functions ?? new List<FunctionDef>(), Functions = Functions ?? new List<FunctionDef>(),
Responses = Responses ?? new List<AgentResponse>() Responses = Responses ?? new List<AgentResponse>(),
LlmConfig = LlmConfig
}; };
return agent; return agent;

View file

@ -26,6 +26,10 @@ public class AgentViewModel
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public List<RoutingRule> RoutingRules { get; set; } public List<RoutingRule> RoutingRules { get; set; }
[JsonPropertyName("llmConfig")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public AgentLlmConfig? LlmConfig { get; set; }
[JsonPropertyName("created_datetime")] [JsonPropertyName("created_datetime")]
public DateTime CreatedDateTime { get; set; } public DateTime CreatedDateTime { get; set; }
@ -49,6 +53,7 @@ public class AgentViewModel
AllowRouting = agent.AllowRouting, AllowRouting = agent.AllowRouting,
Profiles = agent.Profiles, Profiles = agent.Profiles,
RoutingRules = agent.RoutingRules, RoutingRules = agent.RoutingRules,
LlmConfig = agent.LlmConfig,
CreatedDateTime = agent.CreatedDateTime, CreatedDateTime = agent.CreatedDateTime,
UpdatedDateTime = agent.UpdatedDateTime UpdatedDateTime = agent.UpdatedDateTime
}; };

View file

@ -16,6 +16,7 @@ public class AgentDocument : MongoBase
public bool Disabled { get; set; } public bool Disabled { get; set; }
public List<string> Profiles { get; set; } public List<string> Profiles { get; set; }
public List<RoutingRuleMongoElement> RoutingRules { get; set; } public List<RoutingRuleMongoElement> RoutingRules { get; set; }
public AgentLlmConfigMongoElement? LlmConfig { get; set; }
public DateTime CreatedTime { get; set; } public DateTime CreatedTime { get; set; }
public DateTime UpdatedTime { get; set; } public DateTime UpdatedTime { get; set; }

View file

@ -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
};
}
}

View file

@ -82,6 +82,7 @@ public class MongoRepository : IBotSharpRepository
RoutingRules = x.RoutingRules? RoutingRules = x.RoutingRules?
.Select(r => RoutingRuleMongoElement.ToMongoElement(r))? .Select(r => RoutingRuleMongoElement.ToMongoElement(r))?
.ToList() ?? new List<RoutingRuleMongoElement>(), .ToList() ?? new List<RoutingRuleMongoElement>(),
LlmConfig = AgentLlmConfigMongoElement.ToMongoElement(x.LlmConfig),
CreatedTime = x.CreatedDateTime, CreatedTime = x.CreatedDateTime,
UpdatedTime = x.UpdatedDateTime UpdatedTime = x.UpdatedDateTime
}).ToList(); }).ToList();
@ -102,6 +103,7 @@ public class MongoRepository : IBotSharpRepository
.Set(x => x.Disabled, agent.Disabled) .Set(x => x.Disabled, agent.Disabled)
.Set(x => x.Profiles, agent.Profiles) .Set(x => x.Profiles, agent.Profiles)
.Set(x => x.RoutingRules, agent.RoutingRules) .Set(x => x.RoutingRules, agent.RoutingRules)
.Set(x => x.LlmConfig, agent.LlmConfig)
.Set(x => x.CreatedTime, agent.CreatedTime) .Set(x => x.CreatedTime, agent.CreatedTime)
.Set(x => x.UpdatedTime, agent.UpdatedTime); .Set(x => x.UpdatedTime, agent.UpdatedTime);
_dc.Agents.UpdateOne(filter, update, _options); _dc.Agents.UpdateOne(filter, update, _options);
@ -211,6 +213,9 @@ public class MongoRepository : IBotSharpRepository
case AgentField.Sample: case AgentField.Sample:
UpdateAgentSamples(agent.Id, agent.Samples); UpdateAgentSamples(agent.Id, agent.Samples);
break; break;
case AgentField.LlmConfig:
UpdateAgentLlmConfig(agent.Id, agent.LlmConfig);
break;
case AgentField.All: case AgentField.All:
UpdateAgentAllFields(agent); UpdateAgentAllFields(agent);
break; break;
@ -362,6 +367,17 @@ public class MongoRepository : IBotSharpRepository
_dc.Agents.UpdateOne(filter, update); _dc.Agents.UpdateOne(filter, update);
} }
private void UpdateAgentLlmConfig(string agentId, AgentLlmConfig? config)
{
var llmConfig = AgentLlmConfigMongoElement.ToMongoElement(config);
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agentId);
var update = Builders<AgentDocument>.Update
.Set(x => x.LlmConfig, llmConfig)
.Set(x => x.UpdatedTime, DateTime.UtcNow);
_dc.Agents.UpdateOne(filter, update);
}
private void UpdateAgentAllFields(Agent agent) private void UpdateAgentAllFields(Agent agent)
{ {
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agent.Id); var filter = Builders<AgentDocument>.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.Functions, agent.Functions.Select(f => FunctionDefMongoElement.ToMongoElement(f)).ToList())
.Set(x => x.Responses, agent.Responses.Select(r => AgentResponseMongoElement.ToMongoElement(r)).ToList()) .Set(x => x.Responses, agent.Responses.Select(r => AgentResponseMongoElement.ToMongoElement(r)).ToList())
.Set(x => x.Samples, agent.Samples) .Set(x => x.Samples, agent.Samples)
.Set(x => x.LlmConfig, AgentLlmConfigMongoElement.ToMongoElement(agent.LlmConfig))
.Set(x => x.IsPublic, agent.IsPublic) .Set(x => x.IsPublic, agent.IsPublic)
.Set(x => x.UpdatedTime, DateTime.UtcNow); .Set(x => x.UpdatedTime, DateTime.UtcNow);
@ -413,7 +430,8 @@ public class MongoRepository : IBotSharpRepository
Profiles = agent.Profiles, Profiles = agent.Profiles,
RoutingRules = !agent.RoutingRules.IsNullOrEmpty() ? agent.RoutingRules RoutingRules = !agent.RoutingRules.IsNullOrEmpty() ? agent.RoutingRules
.Select(r => RoutingRuleMongoElement.ToDomainElement(agent.Id, agent.Name, r)) .Select(r => RoutingRuleMongoElement.ToDomainElement(agent.Id, agent.Name, r))
.ToList() : new List<RoutingRule>() .ToList() : new List<RoutingRule>(),
LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(agent.LlmConfig)
}; };
} }
@ -469,7 +487,8 @@ public class MongoRepository : IBotSharpRepository
Profiles = x.Profiles, Profiles = x.Profiles,
RoutingRules = !x.RoutingRules.IsNullOrEmpty() ? x.RoutingRules RoutingRules = !x.RoutingRules.IsNullOrEmpty() ? x.RoutingRules
.Select(r => RoutingRuleMongoElement.ToDomainElement(x.Id, x.Name, r)) .Select(r => RoutingRuleMongoElement.ToDomainElement(x.Id, x.Name, r))
.ToList() : new List<RoutingRule>() .ToList() : new List<RoutingRule>(),
LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(x.LlmConfig)
}).ToList(); }).ToList();
} }
@ -482,8 +501,8 @@ public class MongoRepository : IBotSharpRepository
var filter = new AgentFilter var filter = new AgentFilter
{ {
IsPublic = true, AgentIds = agentIds,
AgentIds = agentIds IsPublic = true
}; };
var agents = GetAgents(filter); var agents = GetAgents(filter);
return agents; return agents;
@ -533,6 +552,7 @@ public class MongoRepository : IBotSharpRepository
RoutingRules = x.RoutingRules? RoutingRules = x.RoutingRules?
.Select(r => RoutingRuleMongoElement.ToMongoElement(r))? .Select(r => RoutingRuleMongoElement.ToMongoElement(r))?
.ToList() ?? new List<RoutingRuleMongoElement>(), .ToList() ?? new List<RoutingRuleMongoElement>(),
LlmConfig = AgentLlmConfigMongoElement.ToMongoElement(x.LlmConfig),
CreatedTime = x.CreatedDateTime, CreatedTime = x.CreatedDateTime,
UpdatedTime = x.UpdatedDateTime UpdatedTime = x.UpdatedDateTime
}).ToList(); }).ToList();

View file

@ -53,7 +53,7 @@ public class RoutingConversationHook: ConversationHookBase
public override async Task OnResponseGenerated(RoleDialogModel message) public override async Task OnResponseGenerated(RoleDialogModel message)
{ {
var routerSettings = _services.GetRequiredService<RoutingSettings>(); var routerSettings = _services.GetRequiredService<RoutingSettings>();
bool saveFlag = message.CurrentAgentId != routerSettings.RouterId; bool saveFlag = message.CurrentAgentId != routerSettings.AgentId;
if (saveFlag) if (saveFlag)
{ {

View file

@ -56,7 +56,7 @@ public class TwilioService
{ {
Gather.InputEnum.Speech Gather.InputEnum.Speech
}, },
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.RouterId}") Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.AgentId}")
}; };
gather.Say(message); gather.Say(message);
response.Append(gather); response.Append(gather);
@ -82,7 +82,7 @@ public class TwilioService
var gather = new Gather() var gather = new Gather()
{ {
Input = new List<Gather.InputEnum>() { Gather.InputEnum.Speech }, Input = new List<Gather.InputEnum>() { Gather.InputEnum.Speech },
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.RouterId}"), Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.AgentId}"),
ActionOnEmptyResult = true ActionOnEmptyResult = true
}; };
if (!string.IsNullOrEmpty(message)) if (!string.IsNullOrEmpty(message))