add agent channel instructions
This commit is contained in:
parent
3276b7cd8a
commit
8b86ea50d0
|
|
@ -20,6 +20,13 @@ public interface IAgentService
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Agent> LoadAgent(string id);
|
Task<Agent> LoadAgent(string id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inherit from host agent
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="agent"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task InheritAgent(Agent agent);
|
||||||
|
|
||||||
string RenderedInstruction(Agent agent);
|
string RenderedInstruction(Agent agent);
|
||||||
|
|
||||||
string RenderedTemplate(Agent agent, string templateName);
|
string RenderedTemplate(Agent agent, string templateName);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
using BotSharp.Abstraction.Functions.Models;
|
using BotSharp.Abstraction.Functions.Models;
|
||||||
using BotSharp.Abstraction.Plugins.Models;
|
using BotSharp.Abstraction.Plugins.Models;
|
||||||
using BotSharp.Abstraction.Routing.Models;
|
|
||||||
using BotSharp.Abstraction.Tasks.Models;
|
using BotSharp.Abstraction.Tasks.Models;
|
||||||
|
|
||||||
namespace BotSharp.Abstraction.Agents.Models;
|
namespace BotSharp.Abstraction.Agents.Models;
|
||||||
|
|
@ -21,8 +20,7 @@ public class Agent
|
||||||
/// Default LLM settings
|
/// Default LLM settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public AgentLlmConfig LlmConfig { get; set; }
|
public AgentLlmConfig LlmConfig { get; set; } = new();
|
||||||
= new AgentLlmConfig();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instruction
|
/// Instruction
|
||||||
|
|
@ -30,33 +28,35 @@ public class Agent
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string? Instruction { get; set; }
|
public string? Instruction { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Channel instructions
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public List<ChannelInstruction> ChannelInstructions { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Templates
|
/// Templates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<AgentTemplate> Templates { get; set; }
|
public List<AgentTemplate> Templates { get; set; } = new();
|
||||||
= new List<AgentTemplate>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Agent tasks
|
/// Agent tasks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<AgentTask> Tasks { get; set; }
|
public List<AgentTask> Tasks { get; set; } = new();
|
||||||
= new List<AgentTask>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Samples
|
/// Samples
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<string> Samples { get; set; }
|
public List<string> Samples { get; set; } = new();
|
||||||
= new List<string>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Functions
|
/// Functions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<FunctionDef> Functions { get; set; }
|
public List<FunctionDef> Functions { get; set; } = new();
|
||||||
= new List<FunctionDef>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Responses
|
/// Responses
|
||||||
|
|
@ -93,23 +93,20 @@ public class Agent
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Agent utilities
|
/// Agent utilities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> Utilities { get; set; }
|
public List<string> Utilities { get; set; } = new();
|
||||||
= new List<string>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inherit from agent
|
/// Inherit from agent
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? InheritAgentId { get; set; }
|
public string? InheritAgentId { get; set; }
|
||||||
|
|
||||||
public List<RoutingRule> RoutingRules { get; set; }
|
public List<RoutingRule> RoutingRules { get; set; } = new();
|
||||||
= new List<RoutingRule>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For rendering deferral
|
/// For rendering deferral
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Dictionary<string, object> TemplateDict { get; set; }
|
public Dictionary<string, object> TemplateDict { get; set; } = new();
|
||||||
= new Dictionary<string, object>();
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> $"{Name} {Id}";
|
=> $"{Name} {Id}";
|
||||||
|
|
@ -124,6 +121,7 @@ public class Agent
|
||||||
Description = agent.Description,
|
Description = agent.Description,
|
||||||
Type = agent.Type,
|
Type = agent.Type,
|
||||||
Instruction = agent.Instruction,
|
Instruction = agent.Instruction,
|
||||||
|
ChannelInstructions = agent.ChannelInstructions,
|
||||||
Functions = agent.Functions,
|
Functions = agent.Functions,
|
||||||
Responses = agent.Responses,
|
Responses = agent.Responses,
|
||||||
Samples = agent.Samples,
|
Samples = agent.Samples,
|
||||||
|
|
@ -145,6 +143,12 @@ public class Agent
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Agent SetChannelInstructions(List<ChannelInstruction> instructions)
|
||||||
|
{
|
||||||
|
ChannelInstructions = instructions ?? new List<ChannelInstruction>();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Agent SetTemplates(List<AgentTemplate> templates)
|
public Agent SetTemplates(List<AgentTemplate> templates)
|
||||||
{
|
{
|
||||||
Templates = templates ?? new List<AgentTemplate>();
|
Templates = templates ?? new List<AgentTemplate>();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace BotSharp.Abstraction.Agents.Models;
|
||||||
|
|
||||||
|
public class ChannelInstruction
|
||||||
|
{
|
||||||
|
public string Channel { get; set; }
|
||||||
|
public string Instruction { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ namespace BotSharp.Abstraction.Knowledges.Models;
|
||||||
|
|
||||||
public class KnowledgeSearchResult
|
public class KnowledgeSearchResult
|
||||||
{
|
{
|
||||||
public IDictionary<string, string> Data { get; set; } = new Dictionary<string, string>();
|
public Dictionary<string, string> Data { get; set; } = new();
|
||||||
public double Score { get; set; }
|
public double Score { get; set; }
|
||||||
public float[]? Vector { get; set; }
|
public float[]? Vector { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,41 +41,49 @@ public partial class AgentService
|
||||||
});
|
});
|
||||||
|
|
||||||
Utilities.ClearCache();
|
Utilities.ClearCache();
|
||||||
|
|
||||||
return await Task.FromResult(agentRecord);
|
return await Task.FromResult(agentRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Agent FetchAgentFileByName(string agentName, string filePath)
|
private (string, List<ChannelInstruction>) FetchInstructionsFromFile(string fileDir)
|
||||||
{
|
{
|
||||||
foreach (var dir in Directory.GetDirectories(filePath))
|
var defaultInstruction = string.Empty;
|
||||||
|
var channelInstructions = new List<ChannelInstruction>();
|
||||||
|
|
||||||
|
var instructionDir = Path.Combine(fileDir, "instructions");
|
||||||
|
if (!Directory.Exists(instructionDir))
|
||||||
{
|
{
|
||||||
var agentJson = File.ReadAllText(Path.Combine(dir, "agent.json"));
|
return (defaultInstruction, channelInstructions);
|
||||||
var agent = JsonSerializer.Deserialize<Agent>(agentJson, _options);
|
|
||||||
if (agent != null && agent.Name.IsEqualTo(agentName))
|
|
||||||
{
|
|
||||||
var functions = FetchFunctionsFromFile(dir);
|
|
||||||
var instruction = FetchInstructionFromFile(dir);
|
|
||||||
var responses = FetchResponsesFromFile(dir);
|
|
||||||
var templates = FetchTemplatesFromFile(dir);
|
|
||||||
var samples = FetchSamplesFromFile(dir);
|
|
||||||
return agent.SetInstruction(instruction)
|
|
||||||
.SetTemplates(templates)
|
|
||||||
.SetFunctions(functions)
|
|
||||||
.SetResponses(responses)
|
|
||||||
.SetSamples(samples);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
foreach (var file in Directory.GetFiles(instructionDir))
|
||||||
}
|
{
|
||||||
|
var extension = Path.GetExtension(file).Substring(1);
|
||||||
|
if (!extension.IsEqualTo(_agentSettings.TemplateFormat))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
private string FetchInstructionFromFile(string fileDir)
|
var segments = Path.GetFileName(file).Split(".", StringSplitOptions.RemoveEmptyEntries);
|
||||||
{
|
if (segments.IsNullOrEmpty() || !segments[0].IsEqualTo("instruction"))
|
||||||
var file = Path.Combine(fileDir, $"instruction.{_agentSettings.TemplateFormat}");
|
{
|
||||||
if (!File.Exists(file)) return null;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var instruction = File.ReadAllText(file);
|
if (segments.Length == 2)
|
||||||
return instruction;
|
{
|
||||||
|
defaultInstruction = File.ReadAllText(file);
|
||||||
|
}
|
||||||
|
else if (segments.Length == 3)
|
||||||
|
{
|
||||||
|
var item = new ChannelInstruction
|
||||||
|
{
|
||||||
|
Channel = segments[1],
|
||||||
|
Instruction = File.ReadAllText(file)
|
||||||
|
};
|
||||||
|
channelInstructions.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (defaultInstruction, channelInstructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AgentTemplate> FetchTemplatesFromFile(string fileDir)
|
private List<AgentTemplate> FetchTemplatesFromFile(string fileDir)
|
||||||
|
|
@ -86,10 +94,10 @@ public partial class AgentService
|
||||||
|
|
||||||
foreach (var file in Directory.GetFiles(templateDir))
|
foreach (var file in Directory.GetFiles(templateDir))
|
||||||
{
|
{
|
||||||
var name = Path.GetFileNameWithoutExtension(file);
|
|
||||||
var extension = Path.GetExtension(file).Substring(1);
|
var extension = Path.GetExtension(file).Substring(1);
|
||||||
if (extension.IsEqualTo(_agentSettings.TemplateFormat))
|
if (extension.IsEqualTo(_agentSettings.TemplateFormat))
|
||||||
{
|
{
|
||||||
|
var name = Path.GetFileNameWithoutExtension(file);
|
||||||
var content = File.ReadAllText(file);
|
var content = File.ReadAllText(file);
|
||||||
templates.Add(new AgentTemplate(name, content));
|
templates.Add(new AgentTemplate(name, content));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,29 @@ public partial class AgentService
|
||||||
}
|
}
|
||||||
|
|
||||||
profile.Plugin = GetPlugin(profile.Id);
|
profile.Plugin = GetPlugin(profile.Id);
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task InheritAgent(Agent agent)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(agent?.InheritAgentId)) return;
|
||||||
|
|
||||||
|
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 (string.IsNullOrWhiteSpace(agent.Instruction))
|
||||||
|
{
|
||||||
|
agent.Instruction = inheritedAgent.Instruction;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,31 +34,12 @@ public partial class AgentService
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agent.InheritAgentId != null)
|
await InheritAgent(agent);
|
||||||
{
|
OverrideInstructionByChannel(agent);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AddOrUpdateParameters(agent);
|
AddOrUpdateParameters(agent);
|
||||||
|
|
||||||
agent.TemplateDict = new Dictionary<string, object>();
|
|
||||||
|
|
||||||
// Populate state into dictionary
|
// Populate state into dictionary
|
||||||
|
agent.TemplateDict = new Dictionary<string, object>();
|
||||||
PopulateState(agent.TemplateDict);
|
PopulateState(agent.TemplateDict);
|
||||||
|
|
||||||
// After agent is loaded
|
// After agent is loaded
|
||||||
|
|
@ -94,6 +75,23 @@ public partial class AgentService
|
||||||
return agent;
|
return agent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OverrideInstructionByChannel(Agent agent)
|
||||||
|
{
|
||||||
|
var instructions = agent.ChannelInstructions;
|
||||||
|
if (instructions.IsNullOrEmpty()) return;
|
||||||
|
|
||||||
|
var state = _services.GetRequiredService<IConversationStateService>();
|
||||||
|
var channel = state.GetState("channel");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(channel))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var found = instructions.FirstOrDefault(x => x.Channel.IsEqualTo(channel));
|
||||||
|
agent.Instruction = !string.IsNullOrWhiteSpace(found?.Instruction) ? found.Instruction : agent.Instruction;
|
||||||
|
}
|
||||||
|
|
||||||
private void PopulateState(Dictionary<string, object> dict)
|
private void PopulateState(Dictionary<string, object> dict)
|
||||||
{
|
{
|
||||||
var conv = _services.GetRequiredService<IConversationService>();
|
var conv = _services.GetRequiredService<IConversationService>();
|
||||||
|
|
@ -114,18 +112,27 @@ public partial class AgentService
|
||||||
|
|
||||||
private void AddOrUpdateRoutesParameters(string agentId, List<RoutingRule> routingRules)
|
private void AddOrUpdateRoutesParameters(string agentId, List<RoutingRule> routingRules)
|
||||||
{
|
{
|
||||||
if(!AgentParameterTypes.TryGetValue(agentId, out var parameterTypes)) parameterTypes = new();
|
if(!AgentParameterTypes.TryGetValue(agentId, out var parameterTypes))
|
||||||
|
{
|
||||||
|
parameterTypes = new();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var rule in routingRules.Where(x => x.Required))
|
foreach (var rule in routingRules.Where(x => x.Required))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(rule.FieldType)) continue;
|
if (string.IsNullOrEmpty(rule.FieldType)) continue;
|
||||||
parameterTypes.TryAdd(rule.Field, rule.FieldType);
|
parameterTypes.TryAdd(rule.Field, rule.FieldType);
|
||||||
}
|
}
|
||||||
|
|
||||||
AgentParameterTypes.TryAdd(agentId, parameterTypes);
|
AgentParameterTypes.TryAdd(agentId, parameterTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddOrUpdateFunctionsParameters(string agentId, List<FunctionDef> functions)
|
private void AddOrUpdateFunctionsParameters(string agentId, List<FunctionDef> functions)
|
||||||
{
|
{
|
||||||
if (!AgentParameterTypes.TryGetValue(agentId, out var parameterTypes)) parameterTypes = new();
|
if (!AgentParameterTypes.TryGetValue(agentId, out var parameterTypes))
|
||||||
|
{
|
||||||
|
parameterTypes = new();
|
||||||
|
}
|
||||||
|
|
||||||
var parameters = functions.Select(p => p.Parameters);
|
var parameters = functions.Select(p => p.Parameters);
|
||||||
foreach (var param in parameters)
|
foreach (var param in parameters)
|
||||||
{
|
{
|
||||||
|
|
@ -139,6 +146,7 @@ public partial class AgentService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AgentParameterTypes.TryAdd(agentId, parameterTypes);
|
AgentParameterTypes.TryAdd(agentId, parameterTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,13 @@ public partial class AgentService
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (defaultInstruction, channelInstructions) = FetchInstructionsFromFile(dir);
|
||||||
var functions = FetchFunctionsFromFile(dir);
|
var functions = FetchFunctionsFromFile(dir);
|
||||||
var instruction = FetchInstructionFromFile(dir);
|
|
||||||
var responses = FetchResponsesFromFile(dir);
|
var responses = FetchResponsesFromFile(dir);
|
||||||
var templates = FetchTemplatesFromFile(dir);
|
var templates = FetchTemplatesFromFile(dir);
|
||||||
var samples = FetchSamplesFromFile(dir);
|
var samples = FetchSamplesFromFile(dir);
|
||||||
agent.SetInstruction(instruction)
|
agent.SetInstruction(defaultInstruction)
|
||||||
|
.SetChannelInstructions(channelInstructions)
|
||||||
.SetTemplates(templates)
|
.SetTemplates(templates)
|
||||||
.SetFunctions(functions)
|
.SetFunctions(functions)
|
||||||
.SetResponses(responses)
|
.SetResponses(responses)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ public partial class AgentService
|
||||||
record.Profiles = agent.Profiles ?? new List<string>();
|
record.Profiles = agent.Profiles ?? new List<string>();
|
||||||
record.RoutingRules = agent.RoutingRules ?? new List<RoutingRule>();
|
record.RoutingRules = agent.RoutingRules ?? new List<RoutingRule>();
|
||||||
record.Instruction = agent.Instruction ?? string.Empty;
|
record.Instruction = agent.Instruction ?? string.Empty;
|
||||||
|
record.ChannelInstructions = agent.ChannelInstructions ?? new List<ChannelInstruction>();
|
||||||
record.Functions = agent.Functions ?? new List<FunctionDef>();
|
record.Functions = agent.Functions ?? new List<FunctionDef>();
|
||||||
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>();
|
||||||
|
|
@ -41,7 +42,6 @@ public partial class AgentService
|
||||||
_db.UpdateAgent(record, updateField);
|
_db.UpdateAgent(record, updateField);
|
||||||
|
|
||||||
Utilities.ClearCache();
|
Utilities.ClearCache();
|
||||||
|
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,6 +90,7 @@ public partial class AgentService
|
||||||
.SetProfiles(foundAgent.Profiles)
|
.SetProfiles(foundAgent.Profiles)
|
||||||
.SetRoutingRules(foundAgent.RoutingRules)
|
.SetRoutingRules(foundAgent.RoutingRules)
|
||||||
.SetInstruction(foundAgent.Instruction)
|
.SetInstruction(foundAgent.Instruction)
|
||||||
|
.SetChannelInstructions(foundAgent.ChannelInstructions)
|
||||||
.SetTemplates(foundAgent.Templates)
|
.SetTemplates(foundAgent.Templates)
|
||||||
.SetFunctions(foundAgent.Functions)
|
.SetFunctions(foundAgent.Functions)
|
||||||
.SetResponses(foundAgent.Responses)
|
.SetResponses(foundAgent.Responses)
|
||||||
|
|
@ -175,12 +176,13 @@ public partial class AgentService
|
||||||
var agent = JsonSerializer.Deserialize<Agent>(agentJson, _options);
|
var agent = JsonSerializer.Deserialize<Agent>(agentJson, _options);
|
||||||
if (agent != null && agent.Id == agentId)
|
if (agent != null && agent.Id == agentId)
|
||||||
{
|
{
|
||||||
|
var (defaultInstruction, channelInstructions) = FetchInstructionsFromFile(dir);
|
||||||
var functions = FetchFunctionsFromFile(dir);
|
var functions = FetchFunctionsFromFile(dir);
|
||||||
var instruction = FetchInstructionFromFile(dir);
|
|
||||||
var responses = FetchResponsesFromFile(dir);
|
var responses = FetchResponsesFromFile(dir);
|
||||||
var templates = FetchTemplatesFromFile(dir);
|
var templates = FetchTemplatesFromFile(dir);
|
||||||
var samples = FetchSamplesFromFile(dir);
|
var samples = FetchSamplesFromFile(dir);
|
||||||
return agent.SetInstruction(instruction)
|
return agent.SetInstruction(defaultInstruction)
|
||||||
|
.SetChannelInstructions(channelInstructions)
|
||||||
.SetTemplates(templates)
|
.SetTemplates(templates)
|
||||||
.SetFunctions(functions)
|
.SetFunctions(functions)
|
||||||
.SetResponses(responses)
|
.SetResponses(responses)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
using BotSharp.Abstraction.Functions.Models;
|
||||||
using BotSharp.Abstraction.Routing.Models;
|
using BotSharp.Abstraction.Routing.Models;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace BotSharp.Core.Repository
|
namespace BotSharp.Core.Repository
|
||||||
{
|
{
|
||||||
|
|
@ -37,7 +37,7 @@ namespace BotSharp.Core.Repository
|
||||||
UpdateAgentRoutingRules(agent.Id, agent.RoutingRules);
|
UpdateAgentRoutingRules(agent.Id, agent.RoutingRules);
|
||||||
break;
|
break;
|
||||||
case AgentField.Instruction:
|
case AgentField.Instruction:
|
||||||
UpdateAgentInstruction(agent.Id, agent.Instruction);
|
UpdateAgentInstructions(agent.Id, agent.Instruction, agent.ChannelInstructions);
|
||||||
break;
|
break;
|
||||||
case AgentField.Function:
|
case AgentField.Function:
|
||||||
UpdateAgentFunctions(agent.Id, agent.Functions);
|
UpdateAgentFunctions(agent.Id, agent.Functions);
|
||||||
|
|
@ -175,17 +175,30 @@ namespace BotSharp.Core.Repository
|
||||||
File.WriteAllText(agentFile, json);
|
File.WriteAllText(agentFile, json);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAgentInstruction(string agentId, string instruction)
|
private void UpdateAgentInstructions(string agentId, string instruction, List<ChannelInstruction> channelInstructions)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(instruction)) return;
|
if (string.IsNullOrWhiteSpace(instruction)) return;
|
||||||
|
|
||||||
var (agent, agentFile) = GetAgentFromFile(agentId);
|
var (agent, agentFile) = GetAgentFromFile(agentId);
|
||||||
if (agent == null) return;
|
if (agent == null) return;
|
||||||
|
|
||||||
var instructionFile = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir,
|
var instructionDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_INSTRUCTIONS_FOLDER);
|
||||||
agentId, $"{AGENT_INSTRUCTION_FILE}.{_agentSettings.TemplateFormat}");
|
DeleteBeforeCreateDirectory(instructionDir);
|
||||||
|
|
||||||
File.WriteAllText(instructionFile, instruction);
|
// Save default instructions
|
||||||
|
var instructionFile = Path.Combine(instructionDir, $"{AGENT_INSTRUCTION_FILE}.{_agentSettings.TemplateFormat}");
|
||||||
|
File.WriteAllText(instructionFile, instruction ?? string.Empty);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
|
||||||
|
// Save channel instructions
|
||||||
|
foreach (var ci in channelInstructions)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(ci.Channel)) continue;
|
||||||
|
|
||||||
|
var file = Path.Combine(instructionDir, $"{AGENT_INSTRUCTION_FILE}.{ci.Channel}.{_agentSettings.TemplateFormat}");
|
||||||
|
File.WriteAllText(file, ci.Instruction ?? string.Empty);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAgentFunctions(string agentId, List<FunctionDef> inputFunctions)
|
private void UpdateAgentFunctions(string agentId, List<FunctionDef> inputFunctions)
|
||||||
|
|
@ -195,14 +208,8 @@ namespace BotSharp.Core.Repository
|
||||||
var (agent, agentFile) = GetAgentFromFile(agentId);
|
var (agent, agentFile) = GetAgentFromFile(agentId);
|
||||||
if (agent == null) return;
|
if (agent == null) return;
|
||||||
|
|
||||||
var functionDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir,
|
var functionDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_FUNCTIONS_FOLDER);
|
||||||
agentId, AGENT_FUNCTIONS_FOLDER);
|
DeleteBeforeCreateDirectory(functionDir);
|
||||||
|
|
||||||
if (Directory.Exists(functionDir))
|
|
||||||
{
|
|
||||||
Directory.Delete(functionDir, true);
|
|
||||||
}
|
|
||||||
Directory.CreateDirectory(functionDir);
|
|
||||||
|
|
||||||
foreach (var func in inputFunctions)
|
foreach (var func in inputFunctions)
|
||||||
{
|
{
|
||||||
|
|
@ -211,7 +218,7 @@ namespace BotSharp.Core.Repository
|
||||||
var text = JsonSerializer.Serialize(func, _options);
|
var text = JsonSerializer.Serialize(func, _options);
|
||||||
var file = Path.Combine(functionDir, $"{func.Name}.json");
|
var file = Path.Combine(functionDir, $"{func.Name}.json");
|
||||||
File.WriteAllText(file, text);
|
File.WriteAllText(file, text);
|
||||||
Thread.Sleep(200);
|
Thread.Sleep(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,16 +230,7 @@ namespace BotSharp.Core.Repository
|
||||||
if (agent == null) return;
|
if (agent == null) return;
|
||||||
|
|
||||||
var templateDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_TEMPLATES_FOLDER);
|
var templateDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_TEMPLATES_FOLDER);
|
||||||
|
DeleteBeforeCreateDirectory(templateDir);
|
||||||
if (!Directory.Exists(templateDir))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(templateDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var file in Directory.GetFiles(templateDir))
|
|
||||||
{
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var template in templates)
|
foreach (var template in templates)
|
||||||
{
|
{
|
||||||
|
|
@ -249,15 +247,7 @@ namespace BotSharp.Core.Repository
|
||||||
if (agent == null) return;
|
if (agent == null) return;
|
||||||
|
|
||||||
var responseDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_RESPONSES_FOLDER);
|
var responseDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_RESPONSES_FOLDER);
|
||||||
if (!Directory.Exists(responseDir))
|
DeleteBeforeCreateDirectory(responseDir);
|
||||||
{
|
|
||||||
Directory.CreateDirectory(responseDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var file in Directory.GetFiles(responseDir))
|
|
||||||
{
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < responses.Count; i++)
|
for (int i = 0; i < responses.Count; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -308,7 +298,7 @@ namespace BotSharp.Core.Repository
|
||||||
var json = JsonSerializer.Serialize(agent, _options);
|
var json = JsonSerializer.Serialize(agent, _options);
|
||||||
File.WriteAllText(agentFile, json);
|
File.WriteAllText(agentFile, json);
|
||||||
|
|
||||||
UpdateAgentInstruction(inputAgent.Id, inputAgent.Instruction);
|
UpdateAgentInstructions(inputAgent.Id, inputAgent.Instruction, agent.ChannelInstructions);
|
||||||
UpdateAgentResponses(inputAgent.Id, inputAgent.Responses);
|
UpdateAgentResponses(inputAgent.Id, inputAgent.Responses);
|
||||||
UpdateAgentTemplates(inputAgent.Id, inputAgent.Templates);
|
UpdateAgentTemplates(inputAgent.Id, inputAgent.Templates);
|
||||||
UpdateAgentFunctions(inputAgent.Id, inputAgent.Functions);
|
UpdateAgentFunctions(inputAgent.Id, inputAgent.Functions);
|
||||||
|
|
@ -348,12 +338,13 @@ namespace BotSharp.Core.Repository
|
||||||
var record = JsonSerializer.Deserialize<Agent>(json, _options);
|
var record = JsonSerializer.Deserialize<Agent>(json, _options);
|
||||||
if (record == null) return null;
|
if (record == null) return null;
|
||||||
|
|
||||||
var instruction = FetchInstruction(dir);
|
var (defaultInstruction, channelInstructions) = FetchInstructions(dir);
|
||||||
var functions = FetchFunctions(dir);
|
var functions = FetchFunctions(dir);
|
||||||
var samples = FetchSamples(dir);
|
var samples = FetchSamples(dir);
|
||||||
var templates = FetchTemplates(dir);
|
var templates = FetchTemplates(dir);
|
||||||
var responses = FetchResponses(dir);
|
var responses = FetchResponses(dir);
|
||||||
return record.SetInstruction(instruction)
|
return record.SetInstruction(defaultInstruction)
|
||||||
|
.SetChannelInstructions(channelInstructions)
|
||||||
.SetFunctions(functions)
|
.SetFunctions(functions)
|
||||||
.SetTemplates(templates)
|
.SetTemplates(templates)
|
||||||
.SetSamples(samples)
|
.SetSamples(samples)
|
||||||
|
|
@ -451,13 +442,9 @@ namespace BotSharp.Core.Repository
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BulkInsertAgents(List<Agent> agents)
|
public void BulkInsertAgents(List<Agent> agents) { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BulkInsertUserAgents(List<UserAgent> userAgents)
|
public void BulkInsertUserAgents(List<UserAgent> userAgents) { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DeleteAgents()
|
public bool DeleteAgents()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ public partial class FileRepository : IBotSharpRepository
|
||||||
private const string AGENT_TASK_PREFIX = "#metadata";
|
private const string AGENT_TASK_PREFIX = "#metadata";
|
||||||
private const string AGENT_TASK_SUFFIX = "/metadata";
|
private const string AGENT_TASK_SUFFIX = "/metadata";
|
||||||
private const string TRANSLATION_MEMORY_FILE = "memory.json";
|
private const string TRANSLATION_MEMORY_FILE = "memory.json";
|
||||||
|
private const string AGENT_INSTRUCTIONS_FOLDER = "instructions";
|
||||||
private const string AGENT_FUNCTIONS_FOLDER = "functions";
|
private const string AGENT_FUNCTIONS_FOLDER = "functions";
|
||||||
private const string AGENT_TEMPLATES_FOLDER = "templates";
|
private const string AGENT_TEMPLATES_FOLDER = "templates";
|
||||||
private const string AGENT_RESPONSES_FOLDER = "responses";
|
private const string AGENT_RESPONSES_FOLDER = "responses";
|
||||||
|
|
@ -123,7 +124,9 @@ public partial class FileRepository : IBotSharpRepository
|
||||||
var agent = JsonSerializer.Deserialize<Agent>(json, _options);
|
var agent = JsonSerializer.Deserialize<Agent>(json, _options);
|
||||||
if (agent != null)
|
if (agent != null)
|
||||||
{
|
{
|
||||||
agent = agent.SetInstruction(FetchInstruction(d))
|
var (defaultInstruction, channelInstructions) = FetchInstructions(d);
|
||||||
|
agent = agent.SetInstruction(defaultInstruction)
|
||||||
|
.SetChannelInstructions(channelInstructions)
|
||||||
.SetFunctions(FetchFunctions(d))
|
.SetFunctions(FetchFunctions(d))
|
||||||
.SetTemplates(FetchTemplates(d))
|
.SetTemplates(FetchTemplates(d))
|
||||||
.SetResponses(FetchResponses(d))
|
.SetResponses(FetchResponses(d))
|
||||||
|
|
@ -165,6 +168,17 @@ public partial class FileRepository : IBotSharpRepository
|
||||||
|
|
||||||
|
|
||||||
#region Private methods
|
#region Private methods
|
||||||
|
private void DeleteBeforeCreateDirectory(string dir)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(dir)) return;
|
||||||
|
|
||||||
|
if (Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
Directory.Delete(dir, true);
|
||||||
|
}
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
}
|
||||||
|
|
||||||
private string GetAgentDataDir(string agentId)
|
private string GetAgentDataDir(string agentId)
|
||||||
{
|
{
|
||||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId);
|
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId);
|
||||||
|
|
@ -186,13 +200,46 @@ public partial class FileRepository : IBotSharpRepository
|
||||||
return (agent, agentFile);
|
return (agent, agentFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string? FetchInstruction(string fileDir)
|
private (string, List<ChannelInstruction>) FetchInstructions(string fileDir)
|
||||||
{
|
{
|
||||||
var file = Path.Combine(fileDir, $"{AGENT_INSTRUCTION_FILE}.{_agentSettings.TemplateFormat}");
|
var defaultInstruction = string.Empty;
|
||||||
if (!File.Exists(file)) return null;
|
var channelInstructions = new List<ChannelInstruction>();
|
||||||
|
|
||||||
var instruction = File.ReadAllText(file);
|
var instructionDir = Path.Combine(fileDir, AGENT_INSTRUCTIONS_FOLDER);
|
||||||
return instruction;
|
if (!Directory.Exists(instructionDir))
|
||||||
|
{
|
||||||
|
return (defaultInstruction, channelInstructions);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var file in Directory.GetFiles(instructionDir))
|
||||||
|
{
|
||||||
|
var extension = Path.GetExtension(file).Substring(1);
|
||||||
|
if (!extension.IsEqualTo(_agentSettings.TemplateFormat))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var segments = Path.GetFileName(file).Split(".", StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (segments.IsNullOrEmpty() || !segments[0].IsEqualTo(AGENT_INSTRUCTION_FILE))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segments.Length == 2)
|
||||||
|
{
|
||||||
|
defaultInstruction = File.ReadAllText(file);
|
||||||
|
}
|
||||||
|
else if (segments.Length == 3)
|
||||||
|
{
|
||||||
|
var item = new ChannelInstruction
|
||||||
|
{
|
||||||
|
Channel = segments[1],
|
||||||
|
Instruction = File.ReadAllText(file)
|
||||||
|
};
|
||||||
|
channelInstructions.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (defaultInstruction, channelInstructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<FunctionDef> FetchFunctions(string fileDir)
|
private List<FunctionDef> FetchFunctions(string fileDir)
|
||||||
|
|
@ -298,13 +345,14 @@ public partial class FileRepository : IBotSharpRepository
|
||||||
var agent = JsonSerializer.Deserialize<Agent>(agentJson, _options);
|
var agent = JsonSerializer.Deserialize<Agent>(agentJson, _options);
|
||||||
if (agent == null) return null;
|
if (agent == null) return null;
|
||||||
|
|
||||||
var instruction = FetchInstruction(agentDir);
|
var (defaultInstruction, channelInstructions) = FetchInstructions(agentDir);
|
||||||
var functions = FetchFunctions(agentDir);
|
var functions = FetchFunctions(agentDir);
|
||||||
var samples = FetchSamples(agentDir);
|
var samples = FetchSamples(agentDir);
|
||||||
var templates = FetchTemplates(agentDir);
|
var templates = FetchTemplates(agentDir);
|
||||||
var responses = FetchResponses(agentDir);
|
var responses = FetchResponses(agentDir);
|
||||||
|
|
||||||
return agent.SetInstruction(instruction)
|
return agent.SetInstruction(defaultInstruction)
|
||||||
|
.SetChannelInstructions(channelInstructions)
|
||||||
.SetFunctions(functions)
|
.SetFunctions(functions)
|
||||||
.SetTemplates(templates)
|
.SetTemplates(templates)
|
||||||
.SetSamples(samples)
|
.SetSamples(samples)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using BotSharp.Abstraction.Agents.Models;
|
|
||||||
using BotSharp.Abstraction.Users.Enums;
|
using BotSharp.Abstraction.Users.Enums;
|
||||||
|
|
||||||
namespace BotSharp.OpenAPI.Controllers;
|
namespace BotSharp.OpenAPI.Controllers;
|
||||||
|
|
@ -28,13 +27,18 @@ public class AgentController : ControllerBase
|
||||||
[HttpGet("/agent/{id}")]
|
[HttpGet("/agent/{id}")]
|
||||||
public async Task<AgentViewModel?> GetAgent([FromRoute] string id)
|
public async Task<AgentViewModel?> GetAgent([FromRoute] string id)
|
||||||
{
|
{
|
||||||
var agents = await GetAgents(new AgentFilter
|
var pagedAgents = await _agentService.GetAgents(new AgentFilter
|
||||||
{
|
{
|
||||||
AgentIds = new List<string> { id }
|
AgentIds = new List<string> { id }
|
||||||
}, useHook: true);
|
});
|
||||||
|
|
||||||
var targetAgent = agents.Items.FirstOrDefault();
|
var foundAgent = pagedAgents.Items.FirstOrDefault();
|
||||||
if (targetAgent == null) return null;
|
if (foundAgent == null) return null;
|
||||||
|
|
||||||
|
await _agentService.InheritAgent(foundAgent);
|
||||||
|
var targetAgent = AgentViewModel.FromAgent(foundAgent);
|
||||||
|
var agentSetting = _services.GetRequiredService<AgentSettings>();
|
||||||
|
targetAgent.IsHost = targetAgent.Id == agentSetting.HostAgentId;
|
||||||
|
|
||||||
var redirectAgentIds = targetAgent.RoutingRules
|
var redirectAgentIds = targetAgent.RoutingRules
|
||||||
.Where(x => !string.IsNullOrEmpty(x.RedirectTo))
|
.Where(x => !string.IsNullOrEmpty(x.RedirectTo))
|
||||||
|
|
@ -65,39 +69,16 @@ public class AgentController : ControllerBase
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("/agents")]
|
[HttpGet("/agents")]
|
||||||
public async Task<PagedItems<AgentViewModel>> GetAgents([FromQuery] AgentFilter filter, [FromQuery] bool useHook = false)
|
public async Task<PagedItems<AgentViewModel>> GetAgents([FromQuery] AgentFilter filter)
|
||||||
{
|
{
|
||||||
var agentSetting = _services.GetRequiredService<AgentSettings>();
|
var agentSetting = _services.GetRequiredService<AgentSettings>();
|
||||||
var pagedAgents = await _agentService.GetAgents(filter);
|
var pagedAgents = await _agentService.GetAgents(filter);
|
||||||
|
var agents = pagedAgents?.Items?.Select(x => AgentViewModel.FromAgent(x))?.ToList() ?? new List<AgentViewModel>();
|
||||||
var items = new List<Agent>();
|
|
||||||
var agents = new List<AgentViewModel>();
|
|
||||||
if (useHook)
|
|
||||||
{
|
|
||||||
// prerender agent
|
|
||||||
foreach (var agent in pagedAgents.Items)
|
|
||||||
{
|
|
||||||
var renderedAgent = await _agentService.LoadAgent(agent.Id);
|
|
||||||
items.Add(renderedAgent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set IsHost
|
|
||||||
agents = items.Select(x => AgentViewModel.FromAgent(x)).ToList();
|
|
||||||
foreach (var agent in agents)
|
|
||||||
{
|
|
||||||
agent.IsHost = agentSetting.HostAgentId == agent.Id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
items = pagedAgents.Items.ToList();
|
|
||||||
agents = items.Select(x => AgentViewModel.FromAgent(x)).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PagedItems<AgentViewModel>
|
return new PagedItems<AgentViewModel>
|
||||||
{
|
{
|
||||||
Items = agents,
|
Items = agents,
|
||||||
Count = pagedAgents.Count
|
Count = pagedAgents?.Count ?? 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using BotSharp.Abstraction.Agents.Models;
|
using BotSharp.Abstraction.Agents.Models;
|
||||||
using BotSharp.Abstraction.Functions.Models;
|
using BotSharp.Abstraction.Functions.Models;
|
||||||
using BotSharp.Abstraction.Routing.Models;
|
using BotSharp.Abstraction.Routing.Models;
|
||||||
using BotSharp.Core.Infrastructures;
|
|
||||||
|
|
||||||
namespace BotSharp.OpenAPI.ViewModels.Agents;
|
namespace BotSharp.OpenAPI.ViewModels.Agents;
|
||||||
|
|
||||||
|
|
@ -16,21 +15,26 @@ public class AgentCreationModel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Instruction { get; set; } = string.Empty;
|
public string Instruction { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public List<ChannelInstruction> ChannelInstructions { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LLM extensible Instructions in addition to the default Instructions
|
/// LLM extensible Instructions in addition to the default Instructions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<AgentTemplate> Templates { get; set; } = new List<AgentTemplate>();
|
public List<AgentTemplate> Templates { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LLM callable function definition
|
/// LLM callable function definition
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<FunctionDef> Functions { get; set; } = new List<FunctionDef>();
|
public List<FunctionDef> Functions { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Response template
|
/// Response template
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<AgentResponse> Responses { get; set; } = new List<AgentResponse>();
|
public List<AgentResponse> Responses { get; set; } = new();
|
||||||
public List<string> Samples { get; set; } = new List<string>();
|
public List<string> Samples { get; set; } = new();
|
||||||
|
|
||||||
public bool IsPublic { get; set; }
|
public bool IsPublic { get; set; }
|
||||||
|
|
||||||
|
|
@ -43,9 +47,9 @@ public class AgentCreationModel
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Combine different Agents together to form a Profile.
|
/// Combine different Agents together to form a Profile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> Profiles { get; set; } = new List<string>();
|
public List<string> Profiles { get; set; } = new();
|
||||||
public List<string> Utilities { get; set; } = new List<string>();
|
public List<string> Utilities { get; set; } = new();
|
||||||
public List<RoutingRuleUpdateModel> RoutingRules { get; set; } = new List<RoutingRuleUpdateModel>();
|
public List<RoutingRuleUpdateModel> RoutingRules { get; set; } = new();
|
||||||
public AgentLlmConfig? LlmConfig { get; set; }
|
public AgentLlmConfig? LlmConfig { get; set; }
|
||||||
|
|
||||||
public Agent ToAgent()
|
public Agent ToAgent()
|
||||||
|
|
@ -55,6 +59,7 @@ public class AgentCreationModel
|
||||||
Name = Name,
|
Name = Name,
|
||||||
Description = Description,
|
Description = Description,
|
||||||
Instruction = Instruction,
|
Instruction = Instruction,
|
||||||
|
ChannelInstructions = ChannelInstructions,
|
||||||
Templates = Templates,
|
Templates = Templates,
|
||||||
Functions = Functions,
|
Functions = Functions,
|
||||||
Responses = Responses,
|
Responses = Responses,
|
||||||
|
|
@ -64,9 +69,7 @@ public class AgentCreationModel
|
||||||
Type = Type,
|
Type = Type,
|
||||||
Disabled = Disabled,
|
Disabled = Disabled,
|
||||||
Profiles = Profiles,
|
Profiles = Profiles,
|
||||||
RoutingRules = RoutingRules?
|
RoutingRules = RoutingRules?.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?.ToList() ?? new List<RoutingRule>(),
|
||||||
.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?
|
|
||||||
.ToList() ?? new List<RoutingRule>(),
|
|
||||||
LlmConfig = LlmConfig
|
LlmConfig = LlmConfig
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,12 @@ public class AgentUpdateModel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Instruction { get; set; } = string.Empty;
|
public string Instruction { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Channel instructions
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("channel_instructions")]
|
||||||
|
public List<ChannelInstruction>? ChannelInstructions { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Templates
|
/// Templates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -39,11 +45,11 @@ public class AgentUpdateModel
|
||||||
/// Routes
|
/// Routes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<AgentResponse>? Responses { get; set; }
|
public List<AgentResponse>? Responses { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("is_public")]
|
[JsonPropertyName("is_public")]
|
||||||
|
|
||||||
public bool IsPublic { get; set; }
|
public bool IsPublic { get; set; }
|
||||||
[JsonPropertyName("allow_routing")]
|
|
||||||
|
|
||||||
|
[JsonPropertyName("allow_routing")]
|
||||||
public bool AllowRouting { get; set; }
|
public bool AllowRouting { get; set; }
|
||||||
|
|
||||||
public bool Disabled { get; set; }
|
public bool Disabled { get; set; }
|
||||||
|
|
@ -52,8 +58,8 @@ public class AgentUpdateModel
|
||||||
/// Profile by channel
|
/// Profile by channel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string>? Profiles { get; set; }
|
public List<string>? Profiles { get; set; }
|
||||||
[JsonPropertyName("routing_rules")]
|
|
||||||
|
|
||||||
|
[JsonPropertyName("routing_rules")]
|
||||||
public List<RoutingRuleUpdateModel>? RoutingRules { get; set; }
|
public List<RoutingRuleUpdateModel>? RoutingRules { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("llm_config")]
|
[JsonPropertyName("llm_config")]
|
||||||
|
|
@ -69,10 +75,9 @@ public class AgentUpdateModel
|
||||||
Disabled = Disabled,
|
Disabled = Disabled,
|
||||||
Type = Type,
|
Type = Type,
|
||||||
Profiles = Profiles ?? new List<string>(),
|
Profiles = Profiles ?? new List<string>(),
|
||||||
RoutingRules = RoutingRules?
|
RoutingRules = RoutingRules?.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?.ToList() ?? new List<RoutingRule>(),
|
||||||
.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?
|
|
||||||
.ToList() ?? new List<RoutingRule>(),
|
|
||||||
Instruction = Instruction ?? string.Empty,
|
Instruction = Instruction ?? string.Empty,
|
||||||
|
ChannelInstructions = ChannelInstructions ?? new List<ChannelInstruction>(),
|
||||||
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>(),
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ public class AgentViewModel
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string Type { get; set; } = AgentType.Task;
|
public string Type { get; set; } = AgentType.Task;
|
||||||
public string Instruction { get; set; }
|
public string Instruction { get; set; }
|
||||||
|
public List<ChannelInstruction> ChannelInstructions { get; set; }
|
||||||
public List<AgentTemplate> Templates { get; set; }
|
public List<AgentTemplate> Templates { get; set; }
|
||||||
public List<FunctionDef> Functions { get; set; }
|
public List<FunctionDef> Functions { get; set; }
|
||||||
public List<AgentResponse> Responses { get; set; }
|
public List<AgentResponse> Responses { get; set; }
|
||||||
|
|
@ -60,6 +61,7 @@ public class AgentViewModel
|
||||||
Description = agent.Description,
|
Description = agent.Description,
|
||||||
Type = agent.Type,
|
Type = agent.Type,
|
||||||
Instruction = agent.Instruction,
|
Instruction = agent.Instruction,
|
||||||
|
ChannelInstructions = agent.ChannelInstructions,
|
||||||
Templates = agent.Templates,
|
Templates = agent.Templates,
|
||||||
Functions = agent.Functions,
|
Functions = agent.Functions,
|
||||||
Responses = agent.Responses,
|
Responses = agent.Responses,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ public class AgentDocument : MongoBase
|
||||||
public string? InheritAgentId { get; set; }
|
public string? InheritAgentId { get; set; }
|
||||||
public string? IconUrl { get; set; }
|
public string? IconUrl { get; set; }
|
||||||
public string Instruction { get; set; }
|
public string Instruction { get; set; }
|
||||||
|
public List<ChannelInstructionMongoElement> ChannelInstructions { get; set; }
|
||||||
public List<AgentTemplateMongoElement> Templates { get; set; }
|
public List<AgentTemplateMongoElement> Templates { get; set; }
|
||||||
public List<FunctionDefMongoElement> Functions { get; set; }
|
public List<FunctionDefMongoElement> Functions { get; set; }
|
||||||
public List<AgentResponseMongoElement> Responses { get; set; }
|
public List<AgentResponseMongoElement> Responses { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
using BotSharp.Abstraction.Agents.Models;
|
||||||
|
|
||||||
|
namespace BotSharp.Plugin.MongoStorage.Models;
|
||||||
|
|
||||||
|
public class ChannelInstructionMongoElement
|
||||||
|
{
|
||||||
|
public string Channel { get; set; }
|
||||||
|
public string Instruction { get; set; }
|
||||||
|
|
||||||
|
public static ChannelInstructionMongoElement ToMongoElement(ChannelInstruction instruction)
|
||||||
|
{
|
||||||
|
return new ChannelInstructionMongoElement
|
||||||
|
{
|
||||||
|
Channel = instruction.Channel,
|
||||||
|
Instruction = instruction.Instruction
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChannelInstruction ToDomainElement(ChannelInstructionMongoElement instruction)
|
||||||
|
{
|
||||||
|
return new ChannelInstruction
|
||||||
|
{
|
||||||
|
Channel = instruction.Channel,
|
||||||
|
Instruction = instruction.Instruction
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ public partial class MongoRepository
|
||||||
UpdateAgentRoutingRules(agent.Id, agent.RoutingRules);
|
UpdateAgentRoutingRules(agent.Id, agent.RoutingRules);
|
||||||
break;
|
break;
|
||||||
case AgentField.Instruction:
|
case AgentField.Instruction:
|
||||||
UpdateAgentInstruction(agent.Id, agent.Instruction);
|
UpdateAgentInstructions(agent.Id, agent.Instruction, agent.ChannelInstructions);
|
||||||
break;
|
break;
|
||||||
case AgentField.Function:
|
case AgentField.Function:
|
||||||
UpdateAgentFunctions(agent.Id, agent.Functions);
|
UpdateAgentFunctions(agent.Id, agent.Functions);
|
||||||
|
|
@ -156,13 +156,17 @@ public partial class MongoRepository
|
||||||
_dc.Agents.UpdateOne(filter, update);
|
_dc.Agents.UpdateOne(filter, update);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAgentInstruction(string agentId, string instruction)
|
private void UpdateAgentInstructions(string agentId, string instruction, List<ChannelInstruction>? channelInstructions)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(instruction)) return;
|
if (string.IsNullOrWhiteSpace(agentId)) return;
|
||||||
|
|
||||||
|
var instructionElements = channelInstructions?.Select(x => ChannelInstructionMongoElement.ToMongoElement(x))?
|
||||||
|
.ToList() ?? new List<ChannelInstructionMongoElement>();
|
||||||
|
|
||||||
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agentId);
|
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agentId);
|
||||||
var update = Builders<AgentDocument>.Update
|
var update = Builders<AgentDocument>.Update
|
||||||
.Set(x => x.Instruction, instruction)
|
.Set(x => x.Instruction, instruction)
|
||||||
|
.Set(x => x.ChannelInstructions, instructionElements)
|
||||||
.Set(x => x.UpdatedTime, DateTime.UtcNow);
|
.Set(x => x.UpdatedTime, DateTime.UtcNow);
|
||||||
|
|
||||||
_dc.Agents.UpdateOne(filter, update);
|
_dc.Agents.UpdateOne(filter, update);
|
||||||
|
|
@ -253,6 +257,7 @@ public partial class MongoRepository
|
||||||
.Set(x => x.Profiles, agent.Profiles)
|
.Set(x => x.Profiles, agent.Profiles)
|
||||||
.Set(x => x.RoutingRules, agent.RoutingRules.Select(r => RoutingRuleMongoElement.ToMongoElement(r)).ToList())
|
.Set(x => x.RoutingRules, agent.RoutingRules.Select(r => RoutingRuleMongoElement.ToMongoElement(r)).ToList())
|
||||||
.Set(x => x.Instruction, agent.Instruction)
|
.Set(x => x.Instruction, agent.Instruction)
|
||||||
|
.Set(x => x.ChannelInstructions, agent.ChannelInstructions.Select(i => ChannelInstructionMongoElement.ToMongoElement(i)).ToList())
|
||||||
.Set(x => x.Templates, agent.Templates.Select(t => AgentTemplateMongoElement.ToMongoElement(t)).ToList())
|
.Set(x => x.Templates, agent.Templates.Select(t => AgentTemplateMongoElement.ToMongoElement(t)).ToList())
|
||||||
.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())
|
||||||
|
|
@ -373,6 +378,9 @@ public partial class MongoRepository
|
||||||
IconUrl = x.IconUrl,
|
IconUrl = x.IconUrl,
|
||||||
Description = x.Description,
|
Description = x.Description,
|
||||||
Instruction = x.Instruction,
|
Instruction = x.Instruction,
|
||||||
|
ChannelInstructions = x.ChannelInstructions?
|
||||||
|
.Select(i => ChannelInstructionMongoElement.ToMongoElement(i))?
|
||||||
|
.ToList() ?? new List<ChannelInstructionMongoElement>(),
|
||||||
Templates = x.Templates?
|
Templates = x.Templates?
|
||||||
.Select(t => AgentTemplateMongoElement.ToMongoElement(t))?
|
.Select(t => AgentTemplateMongoElement.ToMongoElement(t))?
|
||||||
.ToList() ?? new List<AgentTemplateMongoElement>(),
|
.ToList() ?? new List<AgentTemplateMongoElement>(),
|
||||||
|
|
@ -463,6 +471,9 @@ public partial class MongoRepository
|
||||||
IconUrl = agentDoc.IconUrl,
|
IconUrl = agentDoc.IconUrl,
|
||||||
Description = agentDoc.Description,
|
Description = agentDoc.Description,
|
||||||
Instruction = agentDoc.Instruction,
|
Instruction = agentDoc.Instruction,
|
||||||
|
ChannelInstructions = !agentDoc.ChannelInstructions.IsNullOrEmpty() ? agentDoc.ChannelInstructions
|
||||||
|
.Select(i => ChannelInstructionMongoElement.ToDomainElement(i))
|
||||||
|
.ToList() : new List<ChannelInstruction>(),
|
||||||
Templates = !agentDoc.Templates.IsNullOrEmpty() ? agentDoc.Templates
|
Templates = !agentDoc.Templates.IsNullOrEmpty() ? agentDoc.Templates
|
||||||
.Select(t => AgentTemplateMongoElement.ToDomainElement(t))
|
.Select(t => AgentTemplateMongoElement.ToDomainElement(t))
|
||||||
.ToList() : new List<AgentTemplate>(),
|
.ToList() : new List<AgentTemplate>(),
|
||||||
|
|
@ -472,6 +483,10 @@ public partial class MongoRepository
|
||||||
Responses = !agentDoc.Responses.IsNullOrEmpty() ? agentDoc.Responses
|
Responses = !agentDoc.Responses.IsNullOrEmpty() ? agentDoc.Responses
|
||||||
.Select(r => AgentResponseMongoElement.ToDomainElement(r))
|
.Select(r => AgentResponseMongoElement.ToDomainElement(r))
|
||||||
.ToList() : new List<AgentResponse>(),
|
.ToList() : new List<AgentResponse>(),
|
||||||
|
RoutingRules = !agentDoc.RoutingRules.IsNullOrEmpty() ? agentDoc.RoutingRules
|
||||||
|
.Select(r => RoutingRuleMongoElement.ToDomainElement(agentDoc.Id, agentDoc.Name, r))
|
||||||
|
.ToList() : new List<RoutingRule>(),
|
||||||
|
LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(agentDoc.LlmConfig),
|
||||||
Samples = agentDoc.Samples ?? new List<string>(),
|
Samples = agentDoc.Samples ?? new List<string>(),
|
||||||
Utilities = agentDoc.Utilities ?? new List<string>(),
|
Utilities = agentDoc.Utilities ?? new List<string>(),
|
||||||
IsPublic = agentDoc.IsPublic,
|
IsPublic = agentDoc.IsPublic,
|
||||||
|
|
@ -479,10 +494,6 @@ public partial class MongoRepository
|
||||||
Type = agentDoc.Type,
|
Type = agentDoc.Type,
|
||||||
InheritAgentId = agentDoc.InheritAgentId,
|
InheritAgentId = agentDoc.InheritAgentId,
|
||||||
Profiles = agentDoc.Profiles,
|
Profiles = agentDoc.Profiles,
|
||||||
RoutingRules = !agentDoc.RoutingRules.IsNullOrEmpty() ? agentDoc.RoutingRules
|
|
||||||
.Select(r => RoutingRuleMongoElement.ToDomainElement(agentDoc.Id, agentDoc.Name, r))
|
|
||||||
.ToList() : new List<RoutingRule>(),
|
|
||||||
LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(agentDoc.LlmConfig)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,12 @@ public partial class MongoRepository
|
||||||
{
|
{
|
||||||
Id = !string.IsNullOrEmpty(x.Id) ? x.Id : Guid.NewGuid().ToString(),
|
Id = !string.IsNullOrEmpty(x.Id) ? x.Id : Guid.NewGuid().ToString(),
|
||||||
Name = x.Name,
|
Name = x.Name,
|
||||||
|
IconUrl = x.IconUrl,
|
||||||
Description = x.Description,
|
Description = x.Description,
|
||||||
Instruction = x.Instruction,
|
Instruction = x.Instruction,
|
||||||
IconUrl = x.IconUrl,
|
ChannelInstructions = x.ChannelInstructions?
|
||||||
|
.Select(i => ChannelInstructionMongoElement.ToMongoElement(i))?
|
||||||
|
.ToList() ?? new List<ChannelInstructionMongoElement>(),
|
||||||
Templates = x.Templates?
|
Templates = x.Templates?
|
||||||
.Select(t => AgentTemplateMongoElement.ToMongoElement(t))?
|
.Select(t => AgentTemplateMongoElement.ToMongoElement(t))?
|
||||||
.ToList() ?? new List<AgentTemplateMongoElement>(),
|
.ToList() ?? new List<AgentTemplateMongoElement>(),
|
||||||
|
|
@ -71,6 +74,7 @@ public partial class MongoRepository
|
||||||
.Set(x => x.Name, agent.Name)
|
.Set(x => x.Name, agent.Name)
|
||||||
.Set(x => x.Description, agent.Description)
|
.Set(x => x.Description, agent.Description)
|
||||||
.Set(x => x.Instruction, agent.Instruction)
|
.Set(x => x.Instruction, agent.Instruction)
|
||||||
|
.Set(x => x.ChannelInstructions, agent.ChannelInstructions)
|
||||||
.Set(x => x.Templates, agent.Templates)
|
.Set(x => x.Templates, agent.Templates)
|
||||||
.Set(x => x.Functions, agent.Functions)
|
.Set(x => x.Functions, agent.Functions)
|
||||||
.Set(x => x.Responses, agent.Responses)
|
.Set(x => x.Responses, agent.Responses)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue