2023-09-19 12:17:50 +00:00
|
|
|
using BotSharp.Abstraction.Agents.Models;
|
2023-09-23 21:33:05 +00:00
|
|
|
using BotSharp.Abstraction.Functions.Models;
|
2023-09-19 12:17:50 +00:00
|
|
|
using BotSharp.Abstraction.Repositories;
|
|
|
|
|
using BotSharp.Abstraction.Routing;
|
|
|
|
|
using BotSharp.Abstraction.Routing.Models;
|
2023-09-20 10:31:50 +00:00
|
|
|
using BotSharp.Abstraction.Routing.Settings;
|
2023-09-19 12:17:50 +00:00
|
|
|
namespace BotSharp.Core.Routing;
|
|
|
|
|
|
|
|
|
|
public class RoutingService : IRoutingService
|
|
|
|
|
{
|
|
|
|
|
private readonly IServiceProvider _services;
|
2023-09-20 10:31:50 +00:00
|
|
|
private readonly RoutingSettings _settings;
|
2023-09-19 12:17:50 +00:00
|
|
|
private readonly ILogger _logger;
|
|
|
|
|
private List<RoleDialogModel> _dialogs;
|
2023-09-25 22:46:00 +00:00
|
|
|
public List<RoleDialogModel> Dialogs {
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_dialogs == null)
|
|
|
|
|
{
|
|
|
|
|
var conv = _services.GetRequiredService<IConversationService>();
|
|
|
|
|
_dialogs = conv.GetDialogHistory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _dialogs;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-09-19 12:17:50 +00:00
|
|
|
|
2023-09-20 10:31:50 +00:00
|
|
|
public RoutingService(IServiceProvider services,
|
|
|
|
|
RoutingSettings settings,
|
|
|
|
|
ILogger<RoutingService> logger)
|
2023-09-19 12:17:50 +00:00
|
|
|
{
|
|
|
|
|
_services = services;
|
2023-09-20 10:31:50 +00:00
|
|
|
_settings = settings;
|
2023-09-19 12:17:50 +00:00
|
|
|
_logger = logger;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-23 21:33:05 +00:00
|
|
|
|
|
|
|
|
public async Task<RoleDialogModel> ExecuteOnce(Agent agent)
|
|
|
|
|
{
|
2023-09-25 22:46:00 +00:00
|
|
|
var message = Dialogs.Last().Content;
|
2023-09-23 21:33:05 +00:00
|
|
|
|
|
|
|
|
var handlers = _services.GetServices<IRoutingHandler>();
|
|
|
|
|
|
|
|
|
|
var handler = handlers.FirstOrDefault(x => x.Name == "route_to_agent");
|
2023-09-25 22:46:00 +00:00
|
|
|
handler.SetDialogs(Dialogs);
|
2023-09-23 21:33:05 +00:00
|
|
|
var result = await handler.Handle(new FunctionCallFromLlm
|
|
|
|
|
{
|
2023-09-25 22:46:00 +00:00
|
|
|
Function = "route_to_agent",
|
|
|
|
|
Question = message,
|
|
|
|
|
Reason = message,
|
|
|
|
|
AgentName = agent.Name
|
2023-09-23 21:33:05 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-25 22:46:00 +00:00
|
|
|
public async Task<RoleDialogModel> InstructLoop()
|
2023-09-19 12:17:50 +00:00
|
|
|
{
|
2023-09-25 22:46:00 +00:00
|
|
|
var router = LoadRouter();
|
2023-09-22 20:38:58 +00:00
|
|
|
var result = new RoleDialogModel(AgentRole.Assistant, "Can you repeat your request again?")
|
|
|
|
|
{
|
|
|
|
|
CurrentAgentId = router.Id
|
|
|
|
|
};
|
2023-09-19 12:17:50 +00:00
|
|
|
|
2023-09-25 22:46:00 +00:00
|
|
|
var message = Dialogs.Last().Content;
|
|
|
|
|
foreach (var dialog in Dialogs.TakeLast(20))
|
2023-09-19 12:17:50 +00:00
|
|
|
{
|
2023-09-21 13:08:27 +00:00
|
|
|
router.Instruction += $"\r\n{dialog.Role}: {dialog.Content}";
|
2023-09-19 12:17:50 +00:00
|
|
|
}
|
|
|
|
|
|
2023-09-22 20:38:58 +00:00
|
|
|
var handlers = _services.GetServices<IRoutingHandler>();
|
|
|
|
|
|
|
|
|
|
var handler = handlers.FirstOrDefault(x => x.Name == "get_next_instruction");
|
|
|
|
|
handler.SetRouter(router);
|
2023-09-25 22:46:00 +00:00
|
|
|
handler.SetDialogs(Dialogs);
|
2023-09-22 20:38:58 +00:00
|
|
|
|
2023-09-19 12:17:50 +00:00
|
|
|
int loopCount = 0;
|
2023-09-23 21:33:05 +00:00
|
|
|
var stop = false;
|
|
|
|
|
while (!stop && loopCount < 5)
|
2023-09-19 12:17:50 +00:00
|
|
|
{
|
|
|
|
|
loopCount++;
|
|
|
|
|
|
2023-09-23 21:33:05 +00:00
|
|
|
var inst = await handler.GetNextInstructionFromReasoner($"You are the Router, tell me the next step?");
|
2023-09-22 20:38:58 +00:00
|
|
|
inst.Question = inst.Question ?? message;
|
2023-09-19 12:17:50 +00:00
|
|
|
|
2023-09-22 20:38:58 +00:00
|
|
|
handler = handlers.FirstOrDefault(x => x.Name == inst.Function);
|
|
|
|
|
if (handler == null)
|
|
|
|
|
{
|
|
|
|
|
handler = handlers.FirstOrDefault(x => x.Name == "get_next_instruction");
|
2023-09-23 21:33:05 +00:00
|
|
|
router.Instruction += $"\r\n{AgentRole.System}: the function must be one of {string.Join(",", GetHandlers().Select(x => x.Name))}.";
|
2023-09-22 20:38:58 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
handler.SetRouter(router);
|
2023-09-25 22:46:00 +00:00
|
|
|
handler.SetDialogs(Dialogs);
|
2023-09-19 12:17:50 +00:00
|
|
|
|
2023-09-22 20:38:58 +00:00
|
|
|
result = await handler.Handle(inst);
|
2023-09-19 12:17:50 +00:00
|
|
|
|
2023-09-22 20:38:58 +00:00
|
|
|
message = result.Content.Replace("\r\n", " ");
|
|
|
|
|
router.Instruction += $"\r\n{result.Role}: {message}";
|
2023-09-19 12:17:50 +00:00
|
|
|
|
2023-09-23 21:33:05 +00:00
|
|
|
stop = !_settings.EnableReasoning;
|
2023-09-19 12:17:50 +00:00
|
|
|
}
|
|
|
|
|
|
2023-09-22 20:38:58 +00:00
|
|
|
return result;
|
2023-09-19 12:17:50 +00:00
|
|
|
}
|
|
|
|
|
|
2023-09-20 10:31:50 +00:00
|
|
|
public Agent LoadRouter()
|
|
|
|
|
{
|
|
|
|
|
var db = _services.GetRequiredService<IBotSharpRepository>();
|
|
|
|
|
|
|
|
|
|
var router = new Agent()
|
|
|
|
|
{
|
|
|
|
|
Id = _settings.RouterId,
|
2023-09-21 16:40:54 +00:00
|
|
|
Name = _settings.RouterName,
|
|
|
|
|
Description = _settings.Description
|
2023-09-20 10:31:50 +00:00
|
|
|
};
|
|
|
|
|
var agents = db.Agents.Where(x => !x.Disabled && x.AllowRouting).ToArray();
|
|
|
|
|
|
2023-09-24 16:20:02 +00:00
|
|
|
// Assemble prompt
|
|
|
|
|
var prompt = @"You're a Router with reasoning. Follow these steps to handle user's request:
|
|
|
|
|
1. Read the CONVERSATION context.
|
|
|
|
|
2. Select a appropriate function from FUNCTIONS.
|
2023-09-25 22:46:00 +00:00
|
|
|
3. Determine which agent is suitable according to conversation context.
|
2023-09-24 21:32:58 +00:00
|
|
|
4. Re-think about selected function is from FUNCTIONS to handle the request.";
|
2023-09-24 16:20:02 +00:00
|
|
|
|
|
|
|
|
// Append function
|
|
|
|
|
prompt += "\r\n";
|
|
|
|
|
prompt += "\r\nFUNCTIONS";
|
|
|
|
|
GetHandlers().Select((handler, i) =>
|
|
|
|
|
{
|
|
|
|
|
prompt += "\r\n";
|
|
|
|
|
prompt += $"\r\n{i + 1}. {handler.Name}";
|
|
|
|
|
prompt += $"\r\n{handler.Description}";
|
|
|
|
|
|
|
|
|
|
// Append parameters
|
|
|
|
|
if (handler.Parameters.Any())
|
|
|
|
|
{
|
|
|
|
|
prompt += "\r\nParameters:";
|
|
|
|
|
handler.Parameters.Select((p, i) =>
|
|
|
|
|
{
|
2023-09-25 22:46:00 +00:00
|
|
|
prompt += $"\r\n - {p.Name}: {p.Description}";
|
2023-09-24 16:20:02 +00:00
|
|
|
return p;
|
|
|
|
|
}).ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return handler;
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
prompt += "\r\n";
|
|
|
|
|
prompt += "\r\nAGENTS";
|
|
|
|
|
agents.Select(x => new RoutingItem
|
2023-09-20 10:31:50 +00:00
|
|
|
{
|
|
|
|
|
AgentId = x.Id,
|
|
|
|
|
Description = x.Description,
|
|
|
|
|
Name = x.Name,
|
|
|
|
|
RequiredFields = x.RoutingRules.Where(x => x.Required)
|
|
|
|
|
.Select(x => x.Field)
|
|
|
|
|
.ToArray()
|
2023-09-24 16:20:02 +00:00
|
|
|
}).Select((agent, i) =>
|
|
|
|
|
{
|
|
|
|
|
prompt += "\r\n";
|
|
|
|
|
prompt += $"\r\n{i + 1}. {agent.Name}";
|
|
|
|
|
prompt += $"\r\n{agent.Description}";
|
2023-09-20 10:31:50 +00:00
|
|
|
|
2023-09-24 16:20:02 +00:00
|
|
|
// Append parameters
|
|
|
|
|
if (agent.RequiredFields.Any())
|
|
|
|
|
{
|
2023-09-24 21:32:58 +00:00
|
|
|
prompt += $"\r\nRequired: {string.Join(", ", agent.RequiredFields)}.";
|
2023-09-24 16:20:02 +00:00
|
|
|
}
|
|
|
|
|
return agent;
|
|
|
|
|
}).ToList();
|
2023-09-20 10:31:50 +00:00
|
|
|
|
2023-09-24 16:20:02 +00:00
|
|
|
prompt += "\r\n";
|
|
|
|
|
prompt += "\r\nCONVERSATION";
|
|
|
|
|
router.Instruction = prompt;
|
2023-09-20 10:31:50 +00:00
|
|
|
|
|
|
|
|
return router;
|
|
|
|
|
}
|
2023-09-22 20:38:58 +00:00
|
|
|
|
|
|
|
|
private List<RoutingHandlerDef> GetHandlers()
|
|
|
|
|
{
|
|
|
|
|
return _services.GetServices<IRoutingHandler>()
|
|
|
|
|
.Where(x => x.IsReasoning == _settings.EnableReasoning)
|
|
|
|
|
.Where(x => !string.IsNullOrEmpty(x.Description))
|
|
|
|
|
.Select(x => new RoutingHandlerDef
|
|
|
|
|
{
|
|
|
|
|
Name = x.Name,
|
|
|
|
|
Description = x.Description,
|
|
|
|
|
Parameters = x.Parameters
|
|
|
|
|
}).ToList();
|
|
|
|
|
}
|
2023-09-19 12:17:50 +00:00
|
|
|
}
|