2023-09-27 12:51:15 +00:00
|
|
|
using BotSharp.Abstraction.Functions.Models;
|
2023-10-16 20:07:07 +00:00
|
|
|
using BotSharp.Abstraction.Repositories;
|
2023-09-27 12:51:15 +00:00
|
|
|
using BotSharp.Abstraction.Routing.Models;
|
2023-10-13 23:36:57 +00:00
|
|
|
using BotSharp.Abstraction.Templating;
|
2023-09-27 12:51:15 +00:00
|
|
|
using System.Drawing;
|
2023-10-13 23:36:57 +00:00
|
|
|
using System.IO;
|
2023-09-27 12:51:15 +00:00
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
|
|
|
|
namespace BotSharp.Core.Routing;
|
|
|
|
|
|
|
|
|
|
public partial class RoutingService
|
|
|
|
|
{
|
2023-10-12 21:42:39 +00:00
|
|
|
public async Task<FunctionCallFromLlm> GetNextInstruction()
|
2023-09-27 12:51:15 +00:00
|
|
|
{
|
2023-10-13 23:36:57 +00:00
|
|
|
var content = GetNextStepPrompt();
|
2023-09-27 12:51:15 +00:00
|
|
|
|
2023-10-09 22:28:17 +00:00
|
|
|
RoleDialogModel response = default;
|
2023-10-10 21:53:04 +00:00
|
|
|
var args = new FunctionCallFromLlm();
|
|
|
|
|
|
2023-10-09 22:28:17 +00:00
|
|
|
if (_settings.UseTextCompletion)
|
|
|
|
|
{
|
|
|
|
|
var completion = CompletionProvider.GetTextCompletion(_services,
|
|
|
|
|
provider: _settings.Provider,
|
|
|
|
|
model: _settings.Model);
|
|
|
|
|
|
|
|
|
|
content = _routerInstance.Router.Instruction + "\r\n\r\n" + content + "\r\nResponse: ";
|
2023-10-12 00:59:09 +00:00
|
|
|
|
|
|
|
|
int retryCount = 0;
|
|
|
|
|
|
|
|
|
|
while (retryCount < 3)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var text = await completion.GetCompletion(content);
|
|
|
|
|
response = new RoleDialogModel(AgentRole.Assistant, text);
|
|
|
|
|
|
|
|
|
|
var pattern = @"\{(?:[^{}]|(?<open>\{)|(?<-open>\}))+(?(open)(?!))\}";
|
|
|
|
|
response.Content = Regex.Match(response.Content, pattern).Value;
|
|
|
|
|
args = JsonSerializer.Deserialize<FunctionCallFromLlm>(response.Content);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError($"{ex.Message}: {response.Content}");
|
|
|
|
|
args.Function = "response_to_user";
|
2023-10-13 23:36:57 +00:00
|
|
|
args.Response = ex.Message;
|
2023-10-12 11:30:13 +00:00
|
|
|
args.AgentName = "Router";
|
2023-10-12 00:59:09 +00:00
|
|
|
content += "\r\nPlease response in JSON format.";
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
retryCount++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-09 22:28:17 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var completion = CompletionProvider.GetChatCompletion(_services,
|
|
|
|
|
provider: _settings.Provider,
|
|
|
|
|
model: _settings.Model);
|
|
|
|
|
|
2023-10-10 21:53:04 +00:00
|
|
|
int retryCount = 0;
|
|
|
|
|
|
|
|
|
|
while (retryCount < 3)
|
2023-09-27 12:51:15 +00:00
|
|
|
{
|
2023-10-10 21:53:04 +00:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
response = completion.GetChatCompletions(_routerInstance.Router, new List<RoleDialogModel>
|
|
|
|
|
{
|
|
|
|
|
new RoleDialogModel(AgentRole.User, content)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var pattern = @"\{(?:[^{}]|(?<open>\{)|(?<-open>\}))+(?(open)(?!))\}";
|
|
|
|
|
response.Content = Regex.Match(response.Content, pattern).Value;
|
|
|
|
|
args = JsonSerializer.Deserialize<FunctionCallFromLlm>(response.Content);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError($"{ex.Message}: {response.Content}");
|
|
|
|
|
args.Function = "response_to_user";
|
2023-10-13 23:36:57 +00:00
|
|
|
args.Response = ex.Message;
|
2023-10-12 11:30:13 +00:00
|
|
|
args.AgentName = "Router";
|
2023-10-10 21:53:04 +00:00
|
|
|
content += "\r\nPlease response in JSON format.";
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
retryCount++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-09 22:28:17 +00:00
|
|
|
}
|
2023-09-27 12:51:15 +00:00
|
|
|
|
|
|
|
|
#if DEBUG
|
2023-10-10 21:53:04 +00:00
|
|
|
Console.WriteLine(response.Content, Color.Gray);
|
2023-09-27 12:51:15 +00:00
|
|
|
#else
|
2023-10-10 21:53:04 +00:00
|
|
|
_logger.LogInformation(response.Content);
|
2023-09-27 12:51:15 +00:00
|
|
|
#endif
|
|
|
|
|
|
2023-10-10 21:53:04 +00:00
|
|
|
// Sometimes it populate malformed Function in Agent name
|
|
|
|
|
if (!string.IsNullOrEmpty(args.Function) && args.Function == args.AgentName)
|
|
|
|
|
{
|
|
|
|
|
args.Function = "route_to_agent";
|
|
|
|
|
_logger.LogWarning($"Captured LLM malformed response");
|
2023-09-27 12:51:15 +00:00
|
|
|
}
|
2023-10-10 21:53:04 +00:00
|
|
|
|
|
|
|
|
// Another case of malformed response
|
|
|
|
|
var agentService = _services.GetRequiredService<IAgentService>();
|
|
|
|
|
var agents = await agentService.GetAgents();
|
|
|
|
|
if (string.IsNullOrEmpty(args.AgentName) && agents.Select(x => x.Name).Contains(args.Function))
|
2023-09-27 12:51:15 +00:00
|
|
|
{
|
2023-10-10 21:53:04 +00:00
|
|
|
args.AgentName = args.Function;
|
|
|
|
|
args.Function = "route_to_agent";
|
|
|
|
|
_logger.LogWarning($"Captured LLM malformed response");
|
2023-09-27 12:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (args.Arguments != null)
|
|
|
|
|
{
|
|
|
|
|
SaveStateByArgs(args.Arguments);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
args.Function = args.Function.Split('.').Last();
|
|
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
Console.WriteLine($"*** Next Instruction *** {args}", Color.Green);
|
|
|
|
|
#else
|
|
|
|
|
_logger.LogInformation($"*** Next Instruction *** {args}");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return args;
|
|
|
|
|
}
|
2023-10-13 23:36:57 +00:00
|
|
|
|
|
|
|
|
#if !DEBUG
|
|
|
|
|
[MemoryCache(60 * 60)]
|
|
|
|
|
#endif
|
|
|
|
|
private string GetNextStepPrompt()
|
|
|
|
|
{
|
2023-10-16 20:07:07 +00:00
|
|
|
var db = _services.GetRequiredService<IBotSharpRepository>();
|
|
|
|
|
// _routerInstance.Router.Templates.First(x => x.Name == "next_step_prompt").Content;
|
|
|
|
|
var template = db.GetAgentTemplate(_routerInstance.AgentId, "next_step_prompt");
|
2023-10-13 23:36:57 +00:00
|
|
|
|
|
|
|
|
// If enabled reasoning
|
|
|
|
|
// JsonSerializer.Serialize(new FunctionCallFromLlm());
|
|
|
|
|
|
|
|
|
|
var render = _services.GetRequiredService<ITemplateRender>();
|
|
|
|
|
return render.Render(template, new Dictionary<string, object>
|
|
|
|
|
{
|
2023-10-16 20:07:07 +00:00
|
|
|
{ "enabled_reasoning", _settings.EnableReasoning }
|
2023-10-13 23:36:57 +00:00
|
|
|
});
|
|
|
|
|
}
|
2023-09-27 12:51:15 +00:00
|
|
|
}
|