Merge branch 'SciSharp:master' into master
This commit is contained in:
commit
db709b26f5
|
|
@ -2,8 +2,8 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<BotSharpVersion>1.2.1</BotSharpVersion>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<BotSharpVersion>1.3.1</BotSharpVersion>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>false</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -10,7 +10,7 @@ namespace BotSharp.Abstraction.Agents;
|
|||
public interface IAgentService
|
||||
{
|
||||
Task<Agent> CreateAgent(Agent agent);
|
||||
Task RefreshAgents();
|
||||
Task<string> RefreshAgents();
|
||||
Task<PagedItems<Agent>> GetAgents(AgentFilter filter);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -26,6 +26,8 @@ public interface IAgentService
|
|||
|
||||
bool RenderFunction(Agent agent, FunctionDef def);
|
||||
|
||||
FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def);
|
||||
|
||||
/// <summary>
|
||||
/// Get agent detail without trigger any hook.
|
||||
/// </summary>
|
||||
|
|
@ -35,7 +37,7 @@ public interface IAgentService
|
|||
|
||||
Task<bool> DeleteAgent(string id);
|
||||
Task UpdateAgent(Agent agent, AgentField updateField);
|
||||
Task UpdateAgentFromFile(string id);
|
||||
Task<string> UpdateAgentFromFile(string id);
|
||||
string GetDataDir();
|
||||
string GetAgentDataDir(string agentId);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace BotSharp.Abstraction.Conversations;
|
|||
public interface IConversationStateService
|
||||
{
|
||||
string GetConversationId();
|
||||
Dictionary<string, string> Load(string conversationId);
|
||||
Dictionary<string, string> Load(string conversationId, bool isReadOnly = false);
|
||||
string GetState(string name, string defaultValue = "");
|
||||
bool ContainsState(string name);
|
||||
Dictionary<string, string> GetStates();
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ public static class EditorTypeEnum
|
|||
public const string DateTimePicker = "datetime-picker";
|
||||
public const string DateTimeRangePicker = "datetime-range-picker";
|
||||
public const string Email = "email";
|
||||
public const string File = "file";
|
||||
|
||||
/// <summary>
|
||||
/// Regex, set the expression in editor_attributes
|
||||
|
|
|
|||
|
|
@ -20,4 +20,7 @@ public class ElementButton
|
|||
|
||||
[JsonPropertyName("is_secondary")]
|
||||
public bool IsSecondary { get; set; }
|
||||
|
||||
[JsonPropertyName("post_action_disclaimer")]
|
||||
public string? PostActionDisclaimer { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ public class GenericTemplateMessage<T> : IRichMessage, ITemplateMessage
|
|||
[JsonPropertyName("is_horizontal")]
|
||||
public bool IsHorizontal { get; set; }
|
||||
|
||||
[JsonPropertyName("is_popup")]
|
||||
public bool IsPopup { get; set; }
|
||||
|
||||
[JsonPropertyName("element_type")]
|
||||
public string ElementType => typeof(T).Name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
namespace BotSharp.Abstraction.Repositories.Enums;
|
||||
|
||||
public static class RepositoryEnum
|
||||
{
|
||||
public const string FileRepository = nameof(FileRepository);
|
||||
public const string MongoRepository = nameof(MongoRepository);
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ public interface IBotSharpRepository
|
|||
void BulkInsertAgents(List<Agent> agents);
|
||||
void BulkInsertUserAgents(List<UserAgent> userAgents);
|
||||
bool DeleteAgents();
|
||||
bool DeleteAgent(string agentId);
|
||||
List<string> GetAgentResponses(string agentId, string prefix, string intent);
|
||||
string GetAgentTemplate(string agentId, string templateName);
|
||||
#endregion
|
||||
|
|
@ -42,7 +43,7 @@ public interface IBotSharpRepository
|
|||
void InsertAgentTask(AgentTask task);
|
||||
void BulkInsertAgentTasks(List<AgentTask> tasks);
|
||||
void UpdateAgentTask(AgentTask task, AgentTaskField field);
|
||||
bool DeleteAgentTask(string agentId, string taskId);
|
||||
bool DeleteAgentTask(string agentId, List<string> taskIds);
|
||||
bool DeleteAgentTasks();
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -1,55 +1,89 @@
|
|||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using BotSharp.Abstraction.Repositories.Enums;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
public partial class AgentService
|
||||
{
|
||||
public async Task RefreshAgents()
|
||||
public async Task<string> RefreshAgents()
|
||||
{
|
||||
var isAgentDeleted = _db.DeleteAgents();
|
||||
var isTaskDeleted = _db.DeleteAgentTasks();
|
||||
if (!isAgentDeleted) return;
|
||||
|
||||
string refreshResult;
|
||||
var dbSettings = _services.GetRequiredService<BotSharpDatabaseSettings>();
|
||||
if (dbSettings.Default == RepositoryEnum.FileRepository)
|
||||
{
|
||||
refreshResult = $"Invalid database repository setting: {dbSettings.Default}";
|
||||
_logger.LogWarning(refreshResult);
|
||||
return refreshResult;
|
||||
}
|
||||
|
||||
var agentDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
|
||||
dbSettings.FileRepository,
|
||||
_agentSettings.DataDir);
|
||||
|
||||
if (!Directory.Exists(agentDir))
|
||||
{
|
||||
refreshResult = $"Cannot find the directory: {agentDir}";
|
||||
return refreshResult;
|
||||
}
|
||||
|
||||
var user = _db.GetUserById(_user.Id);
|
||||
var agents = new List<Agent>();
|
||||
var userAgents = new List<UserAgent>();
|
||||
var agentTasks = new List<AgentTask>();
|
||||
var refreshedAgents = new List<string>();
|
||||
|
||||
foreach (var dir in Directory.GetDirectories(agentDir))
|
||||
{
|
||||
var agentJson = File.ReadAllText(Path.Combine(dir, "agent.json"));
|
||||
var agent = JsonSerializer.Deserialize<Agent>(agentJson, _options);
|
||||
if (agent == null) continue;
|
||||
try
|
||||
{
|
||||
var agentJson = File.ReadAllText(Path.Combine(dir, "agent.json"));
|
||||
var agent = JsonSerializer.Deserialize<Agent>(agentJson, _options);
|
||||
|
||||
if (agent == null)
|
||||
{
|
||||
_logger.LogError($"Cannot find agent in file directory: {dir}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var functions = FetchFunctionsFromFile(dir);
|
||||
var instruction = FetchInstructionFromFile(dir);
|
||||
var responses = FetchResponsesFromFile(dir);
|
||||
var templates = FetchTemplatesFromFile(dir);
|
||||
var samples = FetchSamplesFromFile(dir);
|
||||
agent.SetInstruction(instruction)
|
||||
.SetTemplates(templates)
|
||||
.SetFunctions(functions)
|
||||
.SetResponses(responses)
|
||||
.SetSamples(samples);
|
||||
agents.Add(agent);
|
||||
var functions = FetchFunctionsFromFile(dir);
|
||||
var instruction = FetchInstructionFromFile(dir);
|
||||
var responses = FetchResponsesFromFile(dir);
|
||||
var templates = FetchTemplatesFromFile(dir);
|
||||
var samples = FetchSamplesFromFile(dir);
|
||||
agent.SetInstruction(instruction)
|
||||
.SetTemplates(templates)
|
||||
.SetFunctions(functions)
|
||||
.SetResponses(responses)
|
||||
.SetSamples(samples);
|
||||
|
||||
var userAgent = BuildUserAgent(agent.Id, user.Id);
|
||||
userAgents.Add(userAgent);
|
||||
var userAgent = BuildUserAgent(agent.Id, user.Id);
|
||||
var tasks = FetchTasksFromFile(dir);
|
||||
|
||||
var tasks = FetchTasksFromFile(dir);
|
||||
agentTasks.AddRange(tasks);
|
||||
var isAgentDeleted = _db.DeleteAgent(agent.Id);
|
||||
if (isAgentDeleted)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
_db.BulkInsertAgents(new List<Agent> { agent });
|
||||
_db.BulkInsertUserAgents(new List<UserAgent> { userAgent });
|
||||
_db.BulkInsertAgentTasks(tasks);
|
||||
refreshedAgents.Add(agent.Name);
|
||||
_logger.LogInformation($"Agent {agent.Name} has been migrated.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"Failed to migrate agent in file directory: {dir}\r\nError: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
_db.BulkInsertAgents(agents);
|
||||
_db.BulkInsertUserAgents(userAgents);
|
||||
_db.BulkInsertAgentTasks(agentTasks);
|
||||
if (!refreshedAgents.IsNullOrEmpty())
|
||||
{
|
||||
Utilities.ClearCache();
|
||||
refreshResult = $"Agents are migrated!\r\n{string.Join("\r\n", refreshedAgents)}";
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshResult = "No agent gets refreshed!";
|
||||
}
|
||||
|
||||
Utilities.ClearCache();
|
||||
_logger.LogInformation(refreshResult);
|
||||
return refreshResult;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using BotSharp.Abstraction.Loggers;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
|
|
@ -32,6 +33,64 @@ public partial class AgentService
|
|||
return true;
|
||||
}
|
||||
|
||||
public FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def)
|
||||
{
|
||||
var parameterDef = def?.Parameters;
|
||||
var propertyDef = parameterDef?.Properties;
|
||||
if (propertyDef == null) return null;
|
||||
|
||||
var visibleExpress = "visibility_expression";
|
||||
var root = propertyDef.RootElement;
|
||||
var iterator = root.EnumerateObject();
|
||||
var visibleProps = new List<string>();
|
||||
while (iterator.MoveNext())
|
||||
{
|
||||
var prop = iterator.Current;
|
||||
var name = prop.Name;
|
||||
var node = prop.Value;
|
||||
var matched = true;
|
||||
if (node.TryGetProperty(visibleExpress, out var element))
|
||||
{
|
||||
var expression = element.GetString();
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
var result = render.Render(expression, new Dictionary<string, object>
|
||||
{
|
||||
{ "states", agent.TemplateDict }
|
||||
});
|
||||
matched = result == "visible";
|
||||
}
|
||||
|
||||
if (matched)
|
||||
{
|
||||
visibleProps.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
var rootObject = JObject.Parse(root.GetRawText());
|
||||
var clonedRoot = rootObject.DeepClone() as JObject;
|
||||
var required = parameterDef?.Required ?? new List<string>();
|
||||
foreach (var property in rootObject.Properties())
|
||||
{
|
||||
if (visibleProps.Contains(property.Name))
|
||||
{
|
||||
var value = clonedRoot.GetValue(property.Name) as JObject;
|
||||
if (value != null && value.ContainsKey(visibleExpress))
|
||||
{
|
||||
value.Remove(visibleExpress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clonedRoot.Remove(property.Name);
|
||||
required.Remove(property.Name);
|
||||
}
|
||||
}
|
||||
|
||||
parameterDef.Properties = JsonSerializer.Deserialize<JsonDocument>(clonedRoot.ToString());
|
||||
parameterDef.Required = required;
|
||||
return parameterDef; ;
|
||||
}
|
||||
|
||||
public string RenderedTemplate(Agent agent, string templateName)
|
||||
{
|
||||
// render liquid template
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Abstraction.Repositories.Enums;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using System.IO;
|
||||
|
||||
|
|
@ -39,21 +40,41 @@ public partial class AgentService
|
|||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task UpdateAgentFromFile(string id)
|
||||
public async Task<string> UpdateAgentFromFile(string id)
|
||||
{
|
||||
var agent = _db.GetAgent(id);
|
||||
|
||||
if (agent == null) return;
|
||||
|
||||
string updateResult;
|
||||
var dbSettings = _services.GetRequiredService<BotSharpDatabaseSettings>();
|
||||
var agentSettings = _services.GetRequiredService<AgentSettings>();
|
||||
|
||||
if (dbSettings.Default == RepositoryEnum.FileRepository)
|
||||
{
|
||||
updateResult = $"Invalid database repository setting: {dbSettings.Default}";
|
||||
_logger.LogWarning(updateResult);
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
var agent = _db.GetAgent(id);
|
||||
if (agent == null)
|
||||
{
|
||||
updateResult = $"Cannot find agent ${id}";
|
||||
_logger.LogError(updateResult);
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
|
||||
dbSettings.FileRepository,
|
||||
agentSettings.DataDir);
|
||||
|
||||
var clonedAgent = Agent.Clone(agent);
|
||||
var foundAgent = FetchAgentFileById(agent.Id, filePath);
|
||||
if (foundAgent != null)
|
||||
if (foundAgent == null)
|
||||
{
|
||||
updateResult = $"Cannot find agent {agent.Name} in file directory: {filePath}";
|
||||
_logger.LogError(updateResult);
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
clonedAgent.SetId(foundAgent.Id)
|
||||
.SetName(foundAgent.Name)
|
||||
|
|
@ -71,15 +92,24 @@ public partial class AgentService
|
|||
.SetLlmConfig(foundAgent.LlmConfig);
|
||||
|
||||
_db.UpdateAgent(clonedAgent, AgentField.All);
|
||||
|
||||
Utilities.ClearCache();
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
updateResult = $"Agent {agent.Name} has been migrated!";
|
||||
_logger.LogInformation(updateResult);
|
||||
return updateResult;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
updateResult = $"Failed to migrate agent {agent.Name} in file directory {filePath}.\r\nError: {ex.Message}";
|
||||
_logger.LogError(updateResult);
|
||||
return updateResult;
|
||||
}
|
||||
}
|
||||
|
||||
private Agent FetchAgentFileById(string agentId, string filePath)
|
||||
private Agent? FetchAgentFileById(string agentId, string filePath)
|
||||
{
|
||||
if (!Directory.Exists(filePath)) return null;
|
||||
|
||||
foreach (var dir in Directory.GetDirectories(filePath))
|
||||
{
|
||||
var agentJson = File.ReadAllText(Path.Combine(dir, "agent.json"));
|
||||
|
|
|
|||
|
|
@ -117,15 +117,15 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
return this;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> Load(string conversationId)
|
||||
public Dictionary<string, string> Load(string conversationId, bool isReadOnly = false)
|
||||
{
|
||||
_conversationId = conversationId;
|
||||
_conversationId = !isReadOnly ? conversationId : null;
|
||||
|
||||
var routingCtx = _services.GetRequiredService<IRoutingContext>();
|
||||
var curMsgId = routingCtx.MessageId;
|
||||
|
||||
_historyStates = _db.GetConversationStates(_conversationId);
|
||||
var dialogs = _db.GetConversationDialogs(_conversationId);
|
||||
_historyStates = _db.GetConversationStates(conversationId);
|
||||
var dialogs = _db.GetConversationDialogs(conversationId);
|
||||
var userDialogs = dialogs.Where(x => x.MetaData?.Role == AgentRole.User || x.MetaData?.Role == UserRole.Client)
|
||||
.OrderBy(x => x.MetaData?.CreateTime)
|
||||
.ToList();
|
||||
|
|
@ -177,7 +177,7 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
_logger.LogInformation($"[STATE] {key} : {data}");
|
||||
}
|
||||
|
||||
_logger.LogInformation($"Loaded conversation states: {_conversationId}");
|
||||
_logger.LogInformation($"Loaded conversation states: {conversationId}");
|
||||
var hooks = _services.GetServices<IConversationHook>();
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -73,86 +73,57 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
|
||||
#region Agent
|
||||
public Agent GetAgent(string agentId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public List<Agent> GetAgents(AgentFilter filter)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public List<Agent> GetAgentsByUser(string userId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void UpdateAgent(Agent agent, AgentField field)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public string GetAgentTemplate(string agentId, string templateName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public List<string> GetAgentResponses(string agentId, string prefix, string intent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void BulkInsertAgents(List<Agent> agents)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void BulkInsertUserAgents(List<UserAgent> userAgents)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public bool DeleteAgents()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public bool DeleteAgent(string agentId)
|
||||
=> throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
#region Agent Task
|
||||
public PagedItems<AgentTask> GetAgentTasks(AgentTaskFilter filter)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public AgentTask? GetAgentTask(string agentId, string taskId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void InsertAgentTask(AgentTask task)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void BulkInsertAgentTasks(List<AgentTask> tasks)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void UpdateAgentTask(AgentTask task, AgentTaskField field)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public bool DeleteAgentTask(string agentId, string taskId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public bool DeleteAgentTask(string agentId, List<string> taskIds)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public bool DeleteAgentTasks()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
#region Conversation
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Repository
|
||||
|
|
@ -419,5 +414,10 @@ namespace BotSharp.Core.Repository
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool DeleteAgent(string agentId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Core.Repository;
|
||||
|
||||
|
|
@ -192,19 +190,25 @@ public partial class FileRepository
|
|||
File.WriteAllText(taskFile, fileContent);
|
||||
}
|
||||
|
||||
public bool DeleteAgentTask(string agentId, string taskId)
|
||||
public bool DeleteAgentTask(string agentId, List<string> taskIds)
|
||||
{
|
||||
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId);
|
||||
if (!Directory.Exists(agentDir)) return false;
|
||||
if (!Directory.Exists(agentDir) || taskIds.IsNullOrEmpty()) return false;
|
||||
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
if (!Directory.Exists(taskDir)) return false;
|
||||
|
||||
var taskFile = FindTaskFileById(taskDir, taskId);
|
||||
if (string.IsNullOrWhiteSpace(taskFile)) return false;
|
||||
var deletedTasks = new List<string>();
|
||||
foreach (var taskId in taskIds)
|
||||
{
|
||||
var taskFile = FindTaskFileById(taskDir, taskId);
|
||||
if (string.IsNullOrWhiteSpace(taskFile)) continue;
|
||||
|
||||
File.Delete(taskFile);
|
||||
return true;
|
||||
File.Delete(taskFile);
|
||||
deletedTasks.Add(taskId);
|
||||
}
|
||||
|
||||
return deletedTasks.Any();
|
||||
}
|
||||
|
||||
public bool DeleteAgentTasks()
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Repositories.Enums;
|
||||
using BotSharp.Abstraction.Settings;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ public class RepositoryPlugin : IBotSharpPlugin
|
|||
|
||||
var myDatabaseSettings = new BotSharpDatabaseSettings();
|
||||
config.Bind("Database", myDatabaseSettings);
|
||||
if (myDatabaseSettings.Default == "FileRepository")
|
||||
if (myDatabaseSettings.Default == RepositoryEnum.FileRepository)
|
||||
{
|
||||
services.AddScoped<IBotSharpRepository, FileRepository>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ public class HumanInterventionNeededHandler : RoutingHandlerBase, IRoutingHandle
|
|||
{
|
||||
public string Name => "human_intervention_needed";
|
||||
|
||||
public string Description => "Reach out to human being, customer service or customer representative.";
|
||||
public string Description => "Reach out to human customer service.";
|
||||
|
||||
public List<ParameterPropertyDef> Parameters => new List<ParameterPropertyDef>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -165,6 +165,22 @@ public class NaivePlanner : IPlaner
|
|||
malformed = true;
|
||||
}
|
||||
|
||||
// Agent Name is contaminated.
|
||||
if (args.Function == "route_to_agent")
|
||||
{
|
||||
// Action agent name
|
||||
if (!agents.Any(x => x.Name == args.AgentName))
|
||||
{
|
||||
args.AgentName = agents.FirstOrDefault(x => args.AgentName.Contains(x.Name))?.Name ?? args.AgentName;
|
||||
}
|
||||
|
||||
// Goal agent name
|
||||
if (!agents.Any(x => x.Name == args.OriginalAgent))
|
||||
{
|
||||
args.OriginalAgent = agents.FirstOrDefault(x => args.OriginalAgent.Contains(x.Name))?.Name ?? args.OriginalAgent;
|
||||
}
|
||||
}
|
||||
|
||||
if (malformed)
|
||||
{
|
||||
_logger.LogWarning($"Captured LLM malformed response");
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public class AgentTaskService : IAgentTaskService
|
|||
public async Task<bool> DeleteTask(string agentId, string taskId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var isDeleted = db.DeleteAgentTask(agentId, taskId);
|
||||
var isDeleted = db.DeleteAgentTask(agentId, new List<string> { taskId });
|
||||
return await Task.FromResult(isDeleted);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ You're {{router.name}} ({{router.description}}). Follow these steps to handle us
|
|||
3. Determine which agent is suitable to handle this conversation.
|
||||
4. Re-think on whether the function you chose matches the reason.
|
||||
5. For agent required arguments, think carefully, leave it as blank object if user doesn't provide specific arguments.
|
||||
6. Please do not make up any parameters when there is no exact value provided, you must set the parameter value as null.
|
||||
6. You must include all required args when using selected FUNCTIONS, but you must not make up any parameters when there is no exact value provided, those parameters must set value as null if not declared.
|
||||
7. Response must be in JSON format.
|
||||
|
||||
{% if routing_requirements and routing_requirements != empty %}
|
||||
|
|
|
|||
|
|
@ -10,5 +10,5 @@ Expected user goal agent is {{ expected_user_goal_agent }}.
|
|||
{%- else -%}
|
||||
User goal agent is inferred based on user initial request.
|
||||
{%- endif %}
|
||||
If user wants to speak to customer service, use function human_intervention_needed.
|
||||
If user wants to or is processing with a specific task that can be handled by agents, respond in appropriate output format defined to let proper agent to handle the task.
|
||||
If user wants to speak to human customer service, use function human_intervention_needed.
|
||||
If user wants to or is processing with a specific task that can be handled by agents, respond in appropriate output format defined to let proper agent to handle the task.
|
||||
|
|
|
|||
|
|
@ -84,15 +84,15 @@ public class AgentController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("/refresh-agents")]
|
||||
public async Task RefreshAgents()
|
||||
public async Task<string> RefreshAgents()
|
||||
{
|
||||
await _agentService.RefreshAgents();
|
||||
return await _agentService.RefreshAgents();
|
||||
}
|
||||
|
||||
[HttpPut("/agent/file/{agentId}")]
|
||||
public async Task UpdateAgentFromFile([FromRoute] string agentId)
|
||||
public async Task<string> UpdateAgentFromFile([FromRoute] string agentId)
|
||||
{
|
||||
await _agentService.UpdateAgentFromFile(agentId);
|
||||
return await _agentService.UpdateAgentFromFile(agentId);
|
||||
}
|
||||
|
||||
[HttpPut("/agent/{agentId}")]
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ public class ConversationController : ControllerBase
|
|||
var result = ConversationViewModel.FromSession(conversations.Items.First());
|
||||
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
result.States = state.Load(conversationId);
|
||||
result.States = state.Load(conversationId, isReadOnly: true);
|
||||
|
||||
var user = await userService.GetUser(result.User.Id);
|
||||
result.User = UserViewModel.FromUser(user);
|
||||
|
|
|
|||
|
|
@ -221,11 +221,12 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
{
|
||||
if (agentService.RenderFunction(agent, function))
|
||||
{
|
||||
var property = agentService.RenderFunctionProperty(agent, function);
|
||||
chatCompletionsOptions.Functions.Add(new FunctionDefinition
|
||||
{
|
||||
Name = function.Name,
|
||||
Description = function.Description,
|
||||
Parameters = BinaryData.FromObjectAsJson(function.Parameters)
|
||||
Parameters = BinaryData.FromObjectAsJson(property)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Repositories.Enums;
|
||||
using BotSharp.Plugin.MongoStorage.Repository;
|
||||
|
||||
namespace BotSharp.Plugin.MongoStorage;
|
||||
|
|
@ -18,7 +19,7 @@ public class MongoStoragePlugin : IBotSharpPlugin
|
|||
var dbSettings = new BotSharpDatabaseSettings();
|
||||
config.Bind("Database", dbSettings);
|
||||
|
||||
if (dbSettings.Default == "MongoRepository")
|
||||
if (dbSettings.Default == RepositoryEnum.MongoRepository)
|
||||
{
|
||||
services.AddScoped((IServiceProvider x) =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -398,7 +398,27 @@ public partial class MongoRepository
|
|||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool DeleteAgent(string agentId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(agentId)) return false;
|
||||
|
||||
var agentFilter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agentId);
|
||||
var agentUserFilter = Builders<UserAgentDocument>.Filter.Eq(x => x.AgentId, agentId);
|
||||
var agentTaskFilter = Builders<AgentTaskDocument>.Filter.Eq(x => x.AgentId, agentId);
|
||||
|
||||
_dc.Agents.DeleteOne(agentFilter);
|
||||
_dc.UserAgents.DeleteMany(agentUserFilter);
|
||||
_dc.AgentTasks.DeleteMany(agentTaskFilter);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Agent TransformAgentDocument(AgentDocument? agentDoc)
|
||||
|
|
|
|||
|
|
@ -155,12 +155,16 @@ public partial class MongoRepository
|
|||
_dc.AgentTasks.ReplaceOne(filter, taskDoc);
|
||||
}
|
||||
|
||||
public bool DeleteAgentTask(string agentId, string taskId)
|
||||
public bool DeleteAgentTask(string agentId, List<string> taskIds)
|
||||
{
|
||||
if (string.IsNullOrEmpty(taskId)) return false;
|
||||
if (taskIds.IsNullOrEmpty()) return false;
|
||||
|
||||
var filter = Builders<AgentTaskDocument>.Filter.Eq(x => x.Id, taskId);
|
||||
var taskDeleted = _dc.AgentTasks.DeleteOne(filter);
|
||||
var builder = Builders<AgentTaskDocument>.Filter;
|
||||
var filters = new List<FilterDefinition<AgentTaskDocument>>
|
||||
{
|
||||
builder.In(x => x.Id, taskIds)
|
||||
};
|
||||
var taskDeleted = _dc.AgentTasks.DeleteMany(builder.And(filters));
|
||||
return taskDeleted.DeletedCount > 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -191,14 +191,11 @@ public partial class MongoRepository
|
|||
{
|
||||
if (string.IsNullOrEmpty(conversationId) || states == null) return;
|
||||
|
||||
var filterConv = Builders<ConversationDocument>.Filter.Eq(x => x.Id, conversationId);
|
||||
var filterStates = Builders<ConversationStateDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var saveStates = states.Select(x => StateMongoElement.ToMongoElement(x)).ToList();
|
||||
var updateStates = Builders<ConversationStateDocument>.Update.Set(x => x.States, saveStates);
|
||||
var updateConv = Builders<ConversationDocument>.Update.Set(x => x.UpdatedTime, DateTime.UtcNow);
|
||||
|
||||
_dc.ConversationStates.UpdateOne(filterStates, updateStates);
|
||||
_dc.Conversations.UpdateOne(filterConv, updateConv);
|
||||
}
|
||||
|
||||
public void UpdateConversationStatus(string conversationId, string status)
|
||||
|
|
@ -391,7 +388,7 @@ public partial class MongoRepository
|
|||
{
|
||||
var skip = (page - 1) * batchSize;
|
||||
var candidates = _dc.Conversations.AsQueryable()
|
||||
.Where(x => (x.DialogCount <= messageLimit) && x.UpdatedTime <= utcNow.AddHours(-bufferHours))
|
||||
.Where(x => x.DialogCount <= messageLimit && x.UpdatedTime <= utcNow.AddHours(-bufferHours))
|
||||
.Skip(skip)
|
||||
.Take(batchSize)
|
||||
.Select(x => x.Id)
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
return (prompt, messages.ToArray(), functions.ToArray());
|
||||
}
|
||||
|
||||
private string GetPrompt(List<ChatMessage> messages,List<FunctionDef> functions)
|
||||
private string GetPrompt(List<ChatMessage> messages, List<FunctionDef> functions)
|
||||
{
|
||||
var prompt = string.Empty;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue