2024-08-04 15:01:08 +00:00
|
|
|
using BotSharp.Abstraction.Routing.Models;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
|
2023-08-14 17:00:01 +00:00
|
|
|
namespace BotSharp.Core.Agents.Services;
|
|
|
|
|
|
|
|
|
|
public partial class AgentService
|
|
|
|
|
{
|
2024-08-04 15:01:08 +00:00
|
|
|
public static ConcurrentDictionary<string, Dictionary<string,string>> AgentParameterTypes = new();
|
|
|
|
|
|
2023-10-25 15:48:25 +00:00
|
|
|
[MemoryCache(10 * 60, perInstanceCache: true)]
|
2023-08-14 17:00:01 +00:00
|
|
|
public async Task<Agent> LoadAgent(string id)
|
|
|
|
|
{
|
2024-07-10 04:36:49 +00:00
|
|
|
if (string.IsNullOrEmpty(id) || id == Guid.Empty.ToString())
|
2023-12-05 00:12:57 +00:00
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-14 17:00:01 +00:00
|
|
|
var hooks = _services.GetServices<IAgentHook>();
|
|
|
|
|
|
|
|
|
|
// Before agent is loaded.
|
|
|
|
|
foreach (var hook in hooks)
|
|
|
|
|
{
|
2023-10-24 21:38:34 +00:00
|
|
|
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != id)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-14 17:00:01 +00:00
|
|
|
hook.OnAgentLoading(ref id);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-25 22:46:00 +00:00
|
|
|
var agent = await GetAgent(id);
|
2023-10-12 21:42:39 +00:00
|
|
|
if (agent == null)
|
|
|
|
|
{
|
2024-06-24 21:39:08 +00:00
|
|
|
return null;
|
2023-10-12 21:42:39 +00:00
|
|
|
}
|
|
|
|
|
|
2024-01-29 18:08:49 +00:00
|
|
|
if (agent.InheritAgentId != null)
|
|
|
|
|
{
|
|
|
|
|
var inheritedAgent = await GetAgent(agent.InheritAgentId);
|
|
|
|
|
agent.Templates.AddRange(inheritedAgent.Templates
|
|
|
|
|
// exclude private template
|
|
|
|
|
.Where(x => !x.Name.StartsWith("."))
|
|
|
|
|
// exclude duplicate name
|
|
|
|
|
.Where(x => !agent.Templates.Exists(t => t.Name == x.Name)));
|
|
|
|
|
|
|
|
|
|
agent.Functions.AddRange(inheritedAgent.Functions
|
|
|
|
|
// exclude private template
|
|
|
|
|
.Where(x => !x.Name.StartsWith("."))
|
|
|
|
|
// exclude duplicate name
|
|
|
|
|
.Where(x => !agent.Functions.Exists(t => t.Name == x.Name)));
|
|
|
|
|
|
|
|
|
|
if (agent.Instruction == null)
|
|
|
|
|
{
|
|
|
|
|
agent.Instruction = inheritedAgent.Instruction;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-04 15:01:08 +00:00
|
|
|
AddOrUpdateParameters(agent);
|
2024-01-29 18:08:49 +00:00
|
|
|
|
2023-10-28 20:59:26 +00:00
|
|
|
agent.TemplateDict = new Dictionary<string, object>();
|
|
|
|
|
|
|
|
|
|
// Populate state into dictionary
|
|
|
|
|
PopulateState(agent.TemplateDict);
|
2023-08-14 17:00:01 +00:00
|
|
|
|
|
|
|
|
// After agent is loaded
|
|
|
|
|
foreach (var hook in hooks)
|
|
|
|
|
{
|
2023-10-24 21:38:34 +00:00
|
|
|
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != id)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-14 17:00:01 +00:00
|
|
|
hook.SetAget(agent);
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(agent.Instruction))
|
|
|
|
|
{
|
2023-10-28 20:59:26 +00:00
|
|
|
hook.OnInstructionLoaded(agent.Instruction, agent.TemplateDict);
|
2023-08-14 17:00:01 +00:00
|
|
|
}
|
|
|
|
|
|
2023-09-28 03:31:58 +00:00
|
|
|
if (agent.Functions != null)
|
2023-08-14 17:00:01 +00:00
|
|
|
{
|
2023-09-29 18:08:42 +00:00
|
|
|
hook.OnFunctionsLoaded(agent.Functions);
|
2023-08-14 17:00:01 +00:00
|
|
|
}
|
|
|
|
|
|
2023-10-19 17:24:00 +00:00
|
|
|
if (agent.Samples != null)
|
2023-08-14 17:00:01 +00:00
|
|
|
{
|
2023-10-19 17:24:00 +00:00
|
|
|
hook.OnSamplesLoaded(agent.Samples);
|
2023-08-14 17:00:01 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-17 04:04:23 +00:00
|
|
|
hook.OnAgentLoaded(agent);
|
2023-08-14 17:00:01 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-17 04:04:23 +00:00
|
|
|
_logger.LogInformation($"Loaded agent {agent}.");
|
|
|
|
|
|
2023-08-14 17:00:01 +00:00
|
|
|
return agent;
|
|
|
|
|
}
|
2023-08-25 15:33:21 +00:00
|
|
|
|
|
|
|
|
private void PopulateState(Dictionary<string, object> dict)
|
|
|
|
|
{
|
2023-09-06 03:19:36 +00:00
|
|
|
var conv = _services.GetRequiredService<IConversationService>();
|
|
|
|
|
foreach (var t in conv.States.GetStates())
|
2023-08-25 15:33:21 +00:00
|
|
|
{
|
|
|
|
|
dict[t.Key] = t.Value;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-04 15:01:08 +00:00
|
|
|
|
|
|
|
|
private void AddOrUpdateParameters(Agent agent)
|
|
|
|
|
{
|
|
|
|
|
var agentId = agent.Id ?? agent.Name;
|
|
|
|
|
if (AgentParameterTypes.ContainsKey(agentId)) return;
|
|
|
|
|
|
|
|
|
|
AddOrUpdateRoutesParameters(agentId, agent.RoutingRules);
|
|
|
|
|
AddOrUpdateFunctionsParameters(agentId, agent.Functions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddOrUpdateRoutesParameters(string agentId, List<RoutingRule> routingRules)
|
|
|
|
|
{
|
|
|
|
|
if(!AgentParameterTypes.TryGetValue(agentId, out var parameterTypes)) parameterTypes = new();
|
|
|
|
|
foreach (var rule in routingRules.Where(x => x.Required))
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(rule.FieldType)) continue;
|
|
|
|
|
parameterTypes.TryAdd(rule.Field, rule.FieldType);
|
|
|
|
|
}
|
|
|
|
|
AgentParameterTypes.TryAdd(agentId, parameterTypes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddOrUpdateFunctionsParameters(string agentId, List<FunctionDef> functions)
|
|
|
|
|
{
|
|
|
|
|
if (!AgentParameterTypes.TryGetValue(agentId, out var parameterTypes)) parameterTypes = new();
|
|
|
|
|
var parameters = functions.Select(p => p.Parameters);
|
|
|
|
|
foreach (var param in parameters)
|
|
|
|
|
{
|
|
|
|
|
foreach (JsonProperty prop in param.Properties.RootElement.EnumerateObject())
|
|
|
|
|
{
|
|
|
|
|
var name = prop.Name;
|
|
|
|
|
var node = prop.Value;
|
|
|
|
|
if (node.TryGetProperty("type", out var type))
|
|
|
|
|
{
|
|
|
|
|
parameterTypes.TryAdd(name, type.GetString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AgentParameterTypes.TryAdd(agentId, parameterTypes);
|
|
|
|
|
}
|
2023-08-14 17:00:01 +00:00
|
|
|
}
|