Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,19 @@ public async Task<List<CrontabItem>> GetCrontable()
var crontable = await repo.GetCrontabItems(CrontabItemFilter.Empty());

// Add fixed crontab items from cronsources
var fixedCrantabItems = crontable.Items.ToList();
var cronsources = _services.GetServices<ICrontabSource>();
foreach (var source in cronsources)
var fixedCrontabItems = crontable.Items.ToList();
var cronSources = _services.GetServices<ICrontabSource>();
foreach (var source in cronSources)
{
if (source.IsRealTime)
{
continue;
}
var item = source.GetCrontabItem();
fixedCrantabItems.Add(item);
fixedCrontabItems.Add(item);
}

return fixedCrantabItems;
return fixedCrontabItems;
}

public async Task<List<AgentTask>> GetTasks()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using BotSharp.Abstraction.Coding;
using BotSharp.Abstraction.Coding.Enums;
using BotSharp.Abstraction.Coding.Contexts;
using BotSharp.Abstraction.Coding.Enums;
using BotSharp.Abstraction.Files.Options;
using BotSharp.Abstraction.Files.Proccessors;
using BotSharp.Abstraction.Instructs;
Expand All @@ -23,7 +23,6 @@ public async Task<InstructResult> Execute(
FileInstructOptions? fileOptions = null)
{
var agentService = _services.GetRequiredService<IAgentService>();
var state = _services.GetRequiredService<IConversationStateService>();
var agent = await agentService.LoadAgent(agentId);

var response = new InstructResult
Expand All @@ -32,7 +31,6 @@ public async Task<InstructResult> Execute(
Template = templateName
};


if (agent == null)
{
response.Text = $"Agent (id: {agentId}) does not exist!";
Expand All @@ -46,112 +44,14 @@ public async Task<InstructResult> Execute(
return response;
}


// Run code template
var codeResponse = await RunCode(agent, message, templateName, codeOptions);
if (!string.IsNullOrWhiteSpace(codeResponse?.Text))
if (codeResponse != null)
{
return codeResponse;
}


// Before completion hooks
var hooks = _services.GetHooks<IInstructHook>(agentId);
foreach (var hook in hooks)
{
await hook.BeforeCompletion(agent, message);

// Interrupted by hook
if (message.StopCompletion)
{
return new InstructResult
{
MessageId = message.MessageId,
Text = message.Content
};
}
}


var provider = string.Empty;
var model = string.Empty;
var result = string.Empty;

// Render prompt
var prompt = string.IsNullOrEmpty(templateName) ?
agentService.RenderInstruction(agent) :
agentService.RenderTemplate(agent, templateName);

var completer = CompletionProvider.GetCompletion(_services,
agentConfig: agent.LlmConfig);

if (completer is ITextCompletion textCompleter)
{
instruction = null;
provider = textCompleter.Provider;
model = textCompleter.Model;

result = await GetTextCompletion(textCompleter, agent, prompt, message.MessageId);
response.Text = result;
}
else if (completer is IChatCompletion chatCompleter)
{
provider = chatCompleter.Provider;
model = chatCompleter.Model;


if (instruction == "#TEMPLATE#")
{
instruction = prompt;
prompt = message.Content;
}

IFileProcessor? fileProcessor = null;
if (!files.IsNullOrEmpty() && fileOptions != null)
{
fileProcessor = _services.GetServices<IFileProcessor>()
.FirstOrDefault(x => x.Provider.IsEqualTo(fileOptions.Processor));
}

if (fileProcessor != null)
{
var fileResponse = await fileProcessor.HandleFilesAsync(agent, prompt, files, new FileHandleOptions
{
Provider = provider,
Model = model,
Instruction = instruction,
UserMessage = message.Content,
TemplateName = templateName,
InvokeFrom = $"{nameof(InstructService)}.{nameof(Execute)}",
Data = state.GetStates().ToDictionary(x => x.Key, x => (object)x.Value)
});
result = fileResponse.Result.IfNullOrEmptyAs(string.Empty);
}
else
{
result = await GetChatCompletion(chatCompleter, agent, instruction, prompt, message.MessageId, files);
}
response.Text = result;
}

response.LogId = Guid.NewGuid().ToString();
// After completion hooks
foreach (var hook in hooks)
{
await hook.AfterCompletion(agent, response);
await hook.OnResponseGenerated(new InstructResponseModel
{
LogId = response.LogId,
AgentId = agentId,
Provider = provider,
Model = model,
TemplateName = templateName,
UserMessage = prompt,
SystemInstruction = instruction,
CompletionText = response.Text
});
}

response = await RunLlm(agent, message, instruction, templateName, files, fileOptions);
return response;
}

Expand All @@ -166,7 +66,7 @@ await hook.OnResponseGenerated(new InstructResponseModel
private async Task<InstructResult?> RunCode(
Agent agent,
RoleDialogModel message,
string templateName,
string? templateName,
CodeInstructOptions? codeOptions)
{
InstructResult? instructResult = null;
Expand Down Expand Up @@ -266,11 +166,16 @@ await hook.OnResponseGenerated(new InstructResponseModel
UseProcess = useProcess
}, cancellationToken: cts.Token);

if (codeResponse == null || !codeResponse.Success)
{
return instructResult;
}

instructResult = new InstructResult
{
MessageId = message.MessageId,
Template = context.CodeScript?.Name,
Text = codeResponse?.Result ?? string.Empty
Text = codeResponse.Result
};

var codeExecution = new CodeExecutionResponseModel
Expand All @@ -292,6 +197,123 @@ await hook.OnResponseGenerated(new InstructResponseModel
return instructResult;
}


private async Task<InstructResult> RunLlm(
Agent agent,
RoleDialogModel message,
string? instruction,
string? templateName,
IEnumerable<InstructFileModel>? files = null,
FileInstructOptions? fileOptions = null)
{
var agentService = _services.GetRequiredService<IAgentService>();
var state = _services.GetRequiredService<IConversationStateService>();

var response = new InstructResult
{
MessageId = message.MessageId,
Template = templateName
};

// Before completion hooks
var hooks = _services.GetHooks<IInstructHook>(agent.Id);
foreach (var hook in hooks)
{
await hook.BeforeCompletion(agent, message);

// Interrupted by hook
if (message.StopCompletion)
{
return new InstructResult
{
MessageId = message.MessageId,
Text = message.Content
};
}
}

var provider = string.Empty;
var model = string.Empty;
var result = string.Empty;

// Render prompt
var prompt = string.IsNullOrEmpty(templateName) ?
agentService.RenderInstruction(agent) :
agentService.RenderTemplate(agent, templateName);

var completer = CompletionProvider.GetCompletion(_services,
agentConfig: agent.LlmConfig);

if (completer is ITextCompletion textCompleter)
{
instruction = null;
provider = textCompleter.Provider;
model = textCompleter.Model;

result = await GetTextCompletion(textCompleter, agent, prompt, message.MessageId);
response.Text = result;
}
else if (completer is IChatCompletion chatCompleter)
{
provider = chatCompleter.Provider;
model = chatCompleter.Model;

if (instruction == "#TEMPLATE#")
{
instruction = prompt;
prompt = message.Content;
}

IFileProcessor? fileProcessor = null;
if (!files.IsNullOrEmpty() && fileOptions != null)
{
fileProcessor = _services.GetServices<IFileProcessor>()
.FirstOrDefault(x => x.Provider.IsEqualTo(fileOptions.Processor));
}

if (fileProcessor != null)
{
var fileResponse = await fileProcessor.HandleFilesAsync(agent, prompt, files, new FileHandleOptions
{
Provider = provider,
Model = model,
Instruction = instruction,
UserMessage = message.Content,
TemplateName = templateName,
InvokeFrom = $"{nameof(InstructService)}.{nameof(Execute)}",
Data = state.GetStates().ToDictionary(x => x.Key, x => (object)x.Value)
});
result = fileResponse.Result.IfNullOrEmptyAs(string.Empty);
}
else
{
result = await GetChatCompletion(chatCompleter, agent, instruction, prompt, message.MessageId, files);
}
response.Text = result;
}

response.LogId = Guid.NewGuid().ToString();
// After completion hooks
foreach (var hook in hooks)
{
await hook.AfterCompletion(agent, response);
await hook.OnResponseGenerated(new InstructResponseModel
{
LogId = response.LogId,
AgentId = agent.Id,
Provider = provider,
Model = model,
TemplateName = templateName,
UserMessage = prompt,
SystemInstruction = instruction,
CompletionText = response.Text
});
}

return response;
}


private async Task<string> GetTextCompletion(
ITextCompletion textCompleter,
Agent agent,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using BotSharp.Abstraction.Crontab;

namespace BotSharp.OpenAPI.Controllers;

[Authorize]
[ApiController]
public class CrontabController : ControllerBase
{
private readonly IServiceProvider _services;
private readonly ILogger<CrontabController> _logger;

public CrontabController(
IServiceProvider services,
ILogger<CrontabController> logger)
{
_services = services;
_logger = logger;
}

[HttpPost("/crontab/{name}")]
public async Task<bool> RunCrontab(string name)
{
var cron = _services.GetRequiredService<ICrontabService>();
var crons = await cron.GetCrontable();
var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
if (found == null)
{
_logger.LogWarning($"Cannnot find crontab {name}");
return false;
}

try
{
_logger.LogWarning($"Start running crontab {name}");
await cron.ScheduledTimeArrived(found);
_logger.LogWarning($"Complete running crontab {name}");
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error when running crontab {name}");
return false;
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace BotSharp.Plugin.OpenAI.Models;
namespace BotSharp.Plugin.OpenAI.Models.Text;

public class TextCompletionRequest
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace BotSharp.Plugin.OpenAI.Models;
namespace BotSharp.Plugin.OpenAI.Models.Text;

public class TextCompletionResponse
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Realtime.Options;
using BotSharp.Abstraction.Realtime.Sessions;
using BotSharp.Abstraction.Realtime.Settings;
using BotSharp.Plugin.OpenAI.Models.Realtime;
using OpenAI.Chat;

namespace BotSharp.Plugin.OpenAI.Providers.Realtime;
Expand Down
Loading
Loading