using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Instructs; using BotSharp.Abstraction.MLTasks; using BotSharp.Abstraction.Templating; namespace BotSharp.Core.Instructs; public partial class InstructService : IInstructService { private readonly IServiceProvider _services; private readonly ILogger _logger; public InstructService(IServiceProvider services, ILogger logger) { _services = services; _logger = logger; } public async Task ExecuteInstructionRecursively(Agent agent, List wholeDialogs, Func onMessageReceived, Func onFunctionExecuting, Func onFunctionExecuted) { var chatCompletion = GetChatCompletion(); var result = await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs, async msg => { await onMessageReceived(msg); }, async fn => { var preAgentId = agent.Id; await HandleFunctionMessage(fn, onFunctionExecuting, onFunctionExecuted); // Function executed has exception if (fn.ExecutionResult == null || fn.StopCompletion) { await onMessageReceived(new RoleDialogModel(AgentRole.Assistant, fn.Content)); return; } fn.Content = fn.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim() + " => " + fn.ExecutionResult; // Find response template var templateService = _services.GetRequiredService(); var response = await templateService.RenderFunctionResponse(agent.Id, fn); if (!string.IsNullOrEmpty(response)) { await onMessageReceived(new RoleDialogModel(AgentRole.Assistant, response)); return; } // After function is executed, pass the result to LLM to get a natural response wholeDialogs.Add(fn); await ExecuteInstructionRecursively(agent, wholeDialogs, onMessageReceived, onFunctionExecuting, onFunctionExecuted); }); return result; } private async Task HandleFunctionMessage(RoleDialogModel msg, Func onFunctionExecuting, Func onFunctionExecuted) { // Call functions await onFunctionExecuting(msg); await CallFunctions(msg); await onFunctionExecuted(msg); } public IChatCompletion GetChatCompletion() { var completions = _services.GetServices(); var settings = _services.GetRequiredService(); return completions.FirstOrDefault(x => x.GetType().FullName.EndsWith(settings.ChatCompletion)); } }