Merge branch 'SciSharp:master' into master

This commit is contained in:
Haiping 2024-12-11 05:30:51 +00:00 committed by GitHub
commit 31bcced8d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 608 additions and 182 deletions

View file

@ -121,6 +121,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Core.SideCar", "sr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.VertexAI", "src\Plugins\BotSharp.Plugin.LangChain\BotSharp.Plugin.VertexAI.csproj", "{7DA2DCD0-551B-432E-AA5C-22DDD3ED459B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Core.Crontab", "src\Infrastructure\BotSharp.Core.Crontab\BotSharp.Core.Crontab.csproj", "{F812BAAE-5A7D-4DF7-8E71-70696B51C61F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -489,6 +491,14 @@ Global
{7DA2DCD0-551B-432E-AA5C-22DDD3ED459B}.Release|Any CPU.Build.0 = Release|Any CPU
{7DA2DCD0-551B-432E-AA5C-22DDD3ED459B}.Release|x64.ActiveCfg = Release|Any CPU
{7DA2DCD0-551B-432E-AA5C-22DDD3ED459B}.Release|x64.Build.0 = Release|Any CPU
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F}.Debug|x64.ActiveCfg = Debug|Any CPU
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F}.Debug|x64.Build.0 = Debug|Any CPU
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F}.Release|Any CPU.Build.0 = Release|Any CPU
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F}.Release|x64.ActiveCfg = Release|Any CPU
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -547,6 +557,7 @@ Global
{F57F4862-F8D4-44A1-AC12-5C131B5C9785} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
{6D3A54F9-4792-41DB-BE7D-4F7B1D918EAE} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
{7DA2DCD0-551B-432E-AA5C-22DDD3ED459B} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19}

View file

@ -10,7 +10,7 @@ public class AgentType
/// <summary>
/// Planning agent
/// </summary>
public const string Planning = "plan";
public const string Planning = "planning";
public const string Evaluating = "evaluation";

View file

@ -32,11 +32,6 @@ public class BuiltInAgentId
/// </summary>
public const string Learner = "01acc3e5-0af7-49e6-ad7a-a760bd12dc40";
/// <summary>
/// Plan feasible implementation steps for complex problems
/// </summary>
public const string Planner = "282a7128-69a1-44b0-878c-a9159b88f3b9";
/// <summary>
/// SQL statement generation
/// </summary>

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(TargetFramework)</TargetFramework>

View file

@ -0,0 +1,24 @@
namespace BotSharp.Abstraction.Crontab.Models;
public class CrontabItem : ScheduleTaskArgs
{
[JsonPropertyName("user_id")]
public string UserId { get; set; } = null!;
[JsonPropertyName("agent_id")]
public string AgentId { get; set; } = null!;
[JsonPropertyName("conversation_id")]
public string ConversationId { get; set; } = null!;
[JsonPropertyName("execution_result")]
public string ExecutionResult { get; set; } = null!;
[JsonPropertyName("created_time")]
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
public override string ToString()
{
return $"{Title}: {Description} [AgentId: {AgentId}, UserId: {UserId}]";
}
}

View file

@ -0,0 +1,23 @@
namespace BotSharp.Abstraction.Crontab.Models;
public class CrontabItemFilter : Pagination
{
[JsonPropertyName("user_ids")]
public IEnumerable<string>? UserIds { get; set; }
[JsonPropertyName("agent_ids")]
public IEnumerable<string>? AgentIds { get; set; }
[JsonPropertyName("conversation_ids")]
public IEnumerable<string>? ConversationIds { get; set; }
public CrontabItemFilter()
{
}
public static CrontabItemFilter Empty()
{
return new CrontabItemFilter();
}
}

View file

@ -1,18 +1,25 @@
using System.Text.Json.Serialization;
namespace BotSharp.Core.Crontab.Models;
namespace BotSharp.Abstraction.Crontab.Models;
public class ScheduleTaskArgs
{
[JsonPropertyName("cron_expression")]
public string Cron { get; set; } = null!;
[JsonPropertyName("topic")]
public string Topic { get; set; } = null!;
[JsonPropertyName("title")]
public string Title { get; set; } = null!;
[JsonPropertyName("description")]
public string Description { get; set; } = null!;
[JsonPropertyName("to_do_list")]
public ScheduleTaskItemArgs[] Tasks { get; set; } = [];
}
public class ScheduleTaskItemArgs
{
[JsonPropertyName("topic")]
public string Topic { get; set; } = null!;
[JsonPropertyName("script")]
public string Script { get; set; } = null!;

View file

@ -8,6 +8,7 @@ namespace BotSharp.Abstraction.Planning;
/// </summary>
public interface ITaskPlanner
{
string Name => "Unamed Task Planner";
Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs);
Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs);
Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs);

View file

@ -145,4 +145,10 @@ public interface IBotSharpRepository : IHaveServiceProvider
bool DeleteKnolwedgeBaseFileMeta(string collectionName, string vectorStoreProvider, Guid? fileId = null);
PagedItems<KnowledgeDocMetaData> GetKnowledgeBaseFileMeta(string collectionName, string vectorStoreProvider, KnowledgeFileFilter filter);
#endregion
#region Crontab
bool UpsertCrontabItem(CrontabItem cron) => throw new NotImplementedException();
bool DeleteCrontabItem(string conversationId) => throw new NotImplementedException();
PagedItems<CrontabItem> GetCrontabItems(CrontabItemFilter filter) => throw new NotImplementedException();
#endregion
}

View file

@ -13,6 +13,9 @@ public class RoutableAgent
[JsonPropertyName("description")]
public string Description { get; set; } = string.Empty;
[JsonPropertyName("type")]
public string Type { get; set; } = AgentType.Task;
[JsonPropertyName("profiles")]
public List<string> Profiles { get; set; }
= new List<string>();

View file

@ -9,5 +9,6 @@ public interface IConversationSideCar
List<DialogElement> GetConversationDialogs(string conversationId);
void UpdateConversationBreakpoint(string conversationId, ConversationBreakpoint breakpoint);
ConversationBreakpoint? GetConversationBreakpoint(string conversationId);
Task<RoleDialogModel> SendMessage(string agentId, string text, PostbackMessageModel? postback = null, List<MessageState>? states = null);
Task<RoleDialogModel> SendMessage(string agentId, string text,
PostbackMessageModel? postback = null, List<MessageState>? states = null, List<DialogElement>? dialogs = null);
}

View file

@ -17,4 +17,5 @@ global using BotSharp.Abstraction.Translation.Attributes;
global using BotSharp.Abstraction.Messaging.Enums;
global using BotSharp.Abstraction.Files.Models;
global using BotSharp.Abstraction.Files.Enums;
global using BotSharp.Abstraction.Knowledges.Models;
global using BotSharp.Abstraction.Knowledges.Models;
global using BotSharp.Abstraction.Crontab.Models;

View file

@ -1,5 +1,3 @@
using BotSharp.Core.Crontab.Models;
namespace BotSharp.Core.Crontab.Abstraction;
public interface ICrontabHook

View file

@ -1,5 +1,3 @@
using BotSharp.Core.Crontab.Models;
namespace BotSharp.Core.Crontab.Abstraction;
public interface ICrontabService

View file

@ -21,7 +21,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
<ProjectReference Include="..\BotSharp.Core\BotSharp.Core.csproj" />
</ItemGroup>
@ -29,4 +28,8 @@
<PackageReference Include="NCrontab" Version="3.3.3" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
</Project>

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Repositories;
using BotSharp.Abstraction.Routing;
using BotSharp.Abstraction.Users;
using BotSharp.Core.Crontab.Hooks;
@ -22,16 +23,18 @@ public class ScheduleTaskFn : IFunctionCallback
var user = _services.GetRequiredService<IUserIdentity>();
var crontabItem = new CrontabItem
{
Topic = args.Topic,
Title = args.Title,
Description = args.Description,
Cron = args.Cron,
Script = args.Script,
Language = args.Language,
UserId = user.Id,
AgentId = routing.EntryAgentId,
ConversationId = routing.ConversationId
ConversationId = routing.ConversationId,
Tasks = args.Tasks,
};
var db = _services.GetRequiredService<IBotSharpRepository>();
// var ret = db.UpsertCrontabItem(crontabItem);
return true;
}
}

View file

@ -1,14 +0,0 @@
namespace BotSharp.Core.Crontab.Models;
public class CrontabItem : ScheduleTaskArgs
{
public string UserId { get; set; } = null!;
public string AgentId { get; set; } = null!;
public string ConversationId { get; set; } = null!;
public string ExecutionResult { get; set; } = null!;
public override string ToString()
{
return $"{Topic}: {Description} [AgentId: {AgentId}, UserId: {UserId}]";
}
}

View file

@ -14,29 +14,7 @@
limitations under the License.
******************************************************************************/
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Routing;
using BotSharp.Core.Crontab.Models;
using BotSharp.Core.Infrastructures;
/*****************************************************************************
Copyright 2024 Written by Haiping Chen. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************/
using BotSharp.Abstraction.Repositories;
using Microsoft.Extensions.Logging;
namespace BotSharp.Core.Crontab.Services;
@ -58,24 +36,9 @@ public class CrontabService : ICrontabService
public async Task<List<CrontabItem>> GetCrontable()
{
var convService = _services.GetRequiredService<IConversationService>();
var conv = await convService.GetConversation("73a9ee27-d597-4739-958f-3bd79760ac8e");
if (conv == null || !conv.States.ContainsKey("cron_expression"))
{
return [];
}
return
[
new CrontabItem
{
Topic = conv.States["topic"],
Cron = conv.States["cron_expression"],
Description = conv.States["description"],
Script = conv.States["script"],
Language = conv.States["language"]
}
];
var repo = _services.GetRequiredService<IBotSharpRepository>();
var crontable = repo.GetCrontabItems(CrontabItemFilter.Empty());
return crontable.Items.ToList();
}
public async Task ScheduledTimeArrived(CrontabItem item)

View file

@ -46,24 +46,32 @@ public class CrontabWatcher : BackgroundService
var crons = await cron.GetCrontable();
foreach (var item in crons)
{
var schedule = CrontabSchedule.Parse(item.Cron, new CrontabSchedule.ParseOptions
try
{
IncludingSeconds = true // Ensure you account for seconds
});
var schedule = CrontabSchedule.Parse(item.Cron, new CrontabSchedule.ParseOptions
{
IncludingSeconds = true // Ensure you account for seconds
});
// Get the current time
var currentTime = DateTime.UtcNow;
// Get the current time
var currentTime = DateTime.UtcNow;
// Get the next occurrence from the schedule
var nextOccurrence = schedule.GetNextOccurrence(currentTime.AddSeconds(-1));
// Get the next occurrence from the schedule
var nextOccurrence = schedule.GetNextOccurrence(currentTime.AddSeconds(-1));
// Check if the current time matches the schedule
bool matches = currentTime >= nextOccurrence && currentTime < nextOccurrence.AddSeconds(1);
// Check if the current time matches the schedule
bool matches = currentTime >= nextOccurrence && currentTime < nextOccurrence.AddSeconds(1);
if (matches)
if (matches)
{
_logger.LogDebug($"The current time matches the cron expression {item}");
cron.ScheduledTimeArrived(item);
}
}
catch (Exception ex)
{
_logger.LogDebug($"The current time matches the cron expression {item}");
cron.ScheduledTimeArrived(item);
_logger.LogWarning($"Error when running cron task ({item.ConversationId}, {item.Title}, {item.Cron}): {ex.Message}\r\n{ex.InnerException}");
continue;
}
}
}

View file

@ -4,10 +4,10 @@ global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using BotSharp.Abstraction.Agents.Enums;
global using BotSharp.Abstraction.Crontab.Models;
global using BotSharp.Abstraction.Agents;
global using BotSharp.Abstraction.Plugins;
global using BotSharp.Abstraction.Conversations.Models;
global using BotSharp.Abstraction.Functions;
global using BotSharp.Core.Crontab.Services;
global using BotSharp.Core.Crontab.Abstraction;
global using BotSharp.Core.Crontab.Models;
global using BotSharp.Core.Crontab.Abstraction;

View file

@ -8,24 +8,37 @@
"type": "string",
"description": "cron expression include seconds"
},
"topic": {
"title": {
"type": "string",
"description": "task topic in 1-3 keywords related to business entities"
"description": "task short title"
},
"description": {
"type": "string",
"description": "task description without cron infromation, should include all key business entities"
"description": "the task summary"
},
"script": {
"type": "string",
"description": "task related script, commands or provided function with parameters"
},
"language": {
"type": "string",
"enum": ["sql", "function"],
"description": "script programming language"
"to_do_list": {
"type": "array",
"description": "task to do list, should include all key business entities",
"items": {
"type": "object",
"properties": {
"topic": {
"type": "string",
"description": "task topic in 1-3 keywords related to the step"
},
"script": {
"type": "string",
"description": "task related script, function with parameters or plain text"
},
"language": {
"type": "string",
"enum": [ "function", "sql", "python", "text" ],
"description": "programming language script, function or plain text"
}
}
}
}
},
"required": [ "cron_expression", "topic", "description", "script", "language" ]
"required": [ "cron_expression", "title", "description", "to_do_list" ]
}
}

View file

@ -80,9 +80,9 @@ public class BotSharpConversationSideCar : IConversationSideCar
}
public async Task<RoleDialogModel> SendMessage(string agentId, string text,
PostbackMessageModel? postback = null, List<MessageState>? states = null)
PostbackMessageModel? postback = null, List<MessageState>? states = null, List<DialogElement>? dialogs = null)
{
BeforeExecute();
BeforeExecute(dialogs);
var response = await InnerExecute(agentId, text, postback, states);
AfterExecute();
return response;
@ -114,7 +114,7 @@ public class BotSharpConversationSideCar : IConversationSideCar
return response;
}
private void BeforeExecute()
private void BeforeExecute(List<DialogElement>? dialogs)
{
enabled = true;
var state = _services.GetRequiredService<IConversationStateService>();
@ -123,8 +123,8 @@ public class BotSharpConversationSideCar : IConversationSideCar
var node = new ConversationContext
{
State = state.GetCurrentState(),
Dialogs = new(),
Breakpoints = new(),
Dialogs = dialogs ?? [],
Breakpoints = [],
RecursiveCounter = routing.Context.GetRecursiveCounter(),
RoutingStack = routing.Context.GetAgentStack()
};

View file

@ -0,0 +1,117 @@
using System.IO;
namespace BotSharp.Core.Repository;
public partial class FileRepository
{
public bool UpsertCrontabItem(CrontabItem cron)
{
if (cron == null || string.IsNullOrWhiteSpace(cron.ConversationId))
{
return false;
}
try
{
var baseDir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, cron.ConversationId);
if (!Directory.Exists(baseDir))
{
return false;
}
var cronFile = Path.Combine(baseDir, CRON_FILE);
var json = JsonSerializer.Serialize(cron, _options);
File.WriteAllText(cronFile, json);
return true;
}
catch (Exception ex)
{
_logger.LogError($"Error when saving crontab item: {ex.Message}\r\n{ex.InnerException}");
return false;
}
}
public bool DeleteCrontabItem(string conversationId)
{
if (string.IsNullOrWhiteSpace(conversationId))
{
return false;
}
try
{
var baseDir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, conversationId);
if (!Directory.Exists(baseDir))
{
return false;
}
var cronFile = Path.Combine(baseDir, CRON_FILE);
if (!File.Exists(cronFile))
{
return false;
}
File.Delete(cronFile);
return true;
}
catch (Exception ex)
{
_logger.LogError($"Error when deleting crontab item (${conversationId}): {ex.Message}\r\n{ex.InnerException}");
return false;
}
}
public PagedItems<CrontabItem> GetCrontabItems(CrontabItemFilter filter)
{
if (filter == null)
{
filter = CrontabItemFilter.Empty();
}
var records = new List<CrontabItem>();
var baseDir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir);
if (!Directory.Exists(baseDir))
{
Directory.CreateDirectory(baseDir);
}
var totalDirs = Directory.GetDirectories(baseDir);
foreach (var d in totalDirs)
{
var file = Path.Combine(d, CRON_FILE);
if (!File.Exists(file)) continue;
var json = File.ReadAllText(file);
var record = JsonSerializer.Deserialize<CrontabItem>(json, _options);
if (record == null) continue;
var matched = true;
if (filter?.AgentIds != null)
{
matched = matched && filter.AgentIds.Contains(record.AgentId);
}
if (filter?.ConversationIds != null)
{
matched = matched && filter.ConversationIds.Contains(record.ConversationId);
}
if (filter?.UserIds != null)
{
matched = matched && filter.UserIds.Contains(record.UserId);
}
if (!matched) continue;
records.Add(record);
}
return new PagedItems<CrontabItem>
{
Items = records.OrderByDescending(x => x.CreatedTime).Skip(filter.Offset).Take(filter.Size),
Count = records.Count(),
};
}
}

View file

@ -55,6 +55,8 @@ public partial class FileRepository : IBotSharpRepository
private const string PLUGIN_CONFIG_FILE = "config.json";
private const string STATS_FILE = "stats.json";
private const string CRON_FILE = "cron.json";
public FileRepository(
IServiceProvider services,
BotSharpDatabaseSettings dbSettings,
@ -88,7 +90,6 @@ public partial class FileRepository : IBotSharpRepository
private List<Agent> _agents = new List<Agent>();
private List<RoleAgent> _roleAgents = new List<RoleAgent>();
private List<UserAgent> _userAgents = new List<UserAgent>();
private List<Conversation> _conversations = new List<Conversation>();
private PluginConfig? _pluginConfig = null;
private IQueryable<Role> Roles

View file

@ -1,4 +1,3 @@
using BotSharp.Abstraction.Functions;
using BotSharp.Abstraction.Routing.Enums;
using BotSharp.Abstraction.Routing.Settings;
@ -26,6 +25,14 @@ public class RoutingAgentHook : AgentHookBase
var routing = _services.GetRequiredService<IRoutingService>();
var agents = routing.GetRoutableAgents(_agent.Profiles);
// 过滤 Planner
var planningRule = _agent.RoutingRules.FirstOrDefault(x => x.Type == "planner");
if (planningRule != null)
{
var planners = agents.Where(x => x.Type == AgentType.Planning && x.Name != planningRule.Field).ToArray();
agents = agents.Except(planners).ToArray();
}
// Postprocess agent required fields, remove it if the states exists
var states = _services.GetRequiredService<IConversationStateService>();
foreach (var agent in agents)

View file

@ -24,6 +24,7 @@ namespace BotSharp.Core.Routing.Reasoning;
/// </summary>
public class HFReasoner : IRoutingReasoner
{
public string Name => "Human-Feedback Reasoner";
private readonly IServiceProvider _services;
private readonly ILogger _logger;

View file

@ -29,7 +29,7 @@ namespace BotSharp.Core.Routing.Reasoning;
/// </summary>
public class OneStepForwardReasoner : IRoutingReasoner
{
public string Name => "one-step-forward";
public string Name => "One-Step-Forward-Reasoner";
private readonly IServiceProvider _services;
private readonly ILogger _logger;

View file

@ -35,8 +35,7 @@ public class RoutingPlugin : IBotSharpPlugin
services.AddScoped<IRoutingReasoner, NaiveReasoner>();
services.AddScoped<IRoutingReasoner, HFReasoner>();
services.AddScoped<IRoutingReasoner, SequentialReasoner>();
services.AddScoped<IRoutingReasoner, OneStepForwardReasoner>();
}
}

View file

@ -102,7 +102,7 @@ public partial class RoutingService
return _services.GetServices<IRoutingReasoner>().First(x => x.Name == "Naive Reasoner");
}
var reasoner = _services.GetServices<IRoutingReasoner>().FirstOrDefault(x => x.GetType().Name.EndsWith(rule.Field));
var reasoner = _services.GetServices<IRoutingReasoner>().FirstOrDefault(x => x.Name == rule.Field);
if (reasoner == null)
{

View file

@ -82,11 +82,10 @@ public partial class RoutingService : IRoutingService
var filter = new AgentFilter
{
Disabled = false,
Type = AgentType.Task
Disabled = false
};
var agents = db.GetAgents(filter);
var records = agents.SelectMany(x =>
var records = agents.Where(x => x.Type == AgentType.Task || x.Type == AgentType.Planning).SelectMany(x =>
{
x.RoutingRules.ForEach(r =>
{
@ -108,16 +107,16 @@ public partial class RoutingService : IRoutingService
var filter = new AgentFilter
{
Disabled = false,
Type = AgentType.Task
Disabled = false
};
var agents = db.GetAgents(filter);
var routableAgents = agents.Select(x => new RoutableAgent
var routableAgents = agents.Where(x => x.Type == AgentType.Task || x.Type == AgentType.Planning).Select(x => new RoutableAgent
{
AgentId = x.Id,
Description = x.Description,
Name = x.Name,
Type = x.Type,
Profiles = x.Profiles,
RequiredFields = x.RoutingRules
.Where(p => p.Required)

View file

@ -14,7 +14,7 @@ global using BotSharp.Abstraction.Routing;
global using BotSharp.Abstraction.Plugins;
global using BotSharp.Abstraction.Agents;
global using BotSharp.Abstraction.Conversations;
global using BotSharp.Abstraction.Knowledges;
global using BotSharp.Abstraction.Crontab.Models;
global using BotSharp.Abstraction.Users;
global using BotSharp.Abstraction.Roles;
global using BotSharp.Abstraction.Roles.Models;

View file

@ -12,7 +12,11 @@
"routingRules": [
{
"type": "reasoner",
"field": "HFReasoner"
"field": "One-Step-Forward-Reasoner"
},
{
"type": "planner",
"field": "Sequential-Planner"
}
]
}

View file

@ -1,5 +1,5 @@
using BotSharp.Abstraction.Crontab.Models;
using BotSharp.Core.Crontab.Abstraction;
using BotSharp.Core.Crontab.Models;
using Microsoft.AspNetCore.SignalR;
namespace BotSharp.Plugin.ChatHub.Hooks;

View file

@ -0,0 +1,48 @@
using BotSharp.Abstraction.Crontab.Models;
namespace BotSharp.Plugin.MongoStorage.Collections;
public class CrontabItemDocument : MongoBase
{
public string UserId { get; set; }
public string AgentId { get; set; }
public string ConversationId { get; set; }
public string ExecutionResult { get; set; }
public string Cron { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public IEnumerable<CronTaskMongoElement> Tasks { get; set; } = [];
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
public static CrontabItem ToDomainModel(CrontabItemDocument item)
{
return new CrontabItem
{
UserId = item.UserId,
AgentId = item.AgentId,
ConversationId = item.ConversationId,
ExecutionResult = item.ExecutionResult,
Cron = item.Cron,
Title = item.Title,
Description = item.Description,
Tasks = item.Tasks?.Select(x => CronTaskMongoElement.ToDomainElement(x))?.ToArray() ?? [],
CreatedTime = item.CreatedTime
};
}
public static CrontabItemDocument ToMongoModel(CrontabItem item)
{
return new CrontabItemDocument
{
UserId = item.UserId,
AgentId = item.AgentId,
ConversationId = item.ConversationId,
ExecutionResult = item.ExecutionResult,
Cron = item.Cron,
Title = item.Title,
Description = item.Description,
Tasks = item.Tasks?.Select(x => CronTaskMongoElement.ToMongoElement(x))?.ToList() ?? [],
CreatedTime = item.CreatedTime
};
}
}

View file

@ -0,0 +1,30 @@
using BotSharp.Abstraction.Crontab.Models;
namespace BotSharp.Plugin.MongoStorage.Models;
public class CronTaskMongoElement
{
public string Topic { get; set; }
public string Script { get; set; }
public string Language { get; set; }
public static CronTaskMongoElement ToMongoElement(ScheduleTaskItemArgs model)
{
return new CronTaskMongoElement
{
Topic = model.Topic,
Script = model.Script,
Language = model.Language
};
}
public static ScheduleTaskItemArgs ToDomainElement(CronTaskMongoElement model)
{
return new ScheduleTaskItemArgs
{
Topic = model.Topic,
Script = model.Script,
Language = model.Language
};
}
}

View file

@ -165,4 +165,7 @@ public class MongoDbContext
public IMongoCollection<RoleAgentDocument> RoleAgents
=> Database.GetCollection<RoleAgentDocument>($"{_collectionPrefix}_RoleAgents");
public IMongoCollection<CrontabItemDocument> CrontabItems
=> Database.GetCollection<CrontabItemDocument>($"{_collectionPrefix}_CronTabItems");
}

View file

@ -56,6 +56,7 @@ public partial class MongoRepository
var filterPromptLog = Builders<LlmCompletionLogDocument>.Filter.In(x => x.ConversationId, conversationIds);
var filterContentLog = Builders<ConversationContentLogDocument>.Filter.In(x => x.ConversationId, conversationIds);
var filterStateLog = Builders<ConversationStateLogDocument>.Filter.In(x => x.ConversationId, conversationIds);
var conbTabItems = Builders<CrontabItemDocument>.Filter.In(x => x.ConversationId, conversationIds);
var exeLogDeleted = _dc.ExectionLogs.DeleteMany(filterExeLog);
var promptLogDeleted = _dc.LlmCompletionLogs.DeleteMany(filterPromptLog);
@ -63,11 +64,13 @@ public partial class MongoRepository
var stateLogDeleted = _dc.StateLogs.DeleteMany(filterStateLog);
var statesDeleted = _dc.ConversationStates.DeleteMany(filterSates);
var dialogDeleted = _dc.ConversationDialogs.DeleteMany(filterDialog);
var cronDeleted = _dc.CrontabItems.DeleteMany(conbTabItems);
var convDeleted = _dc.Conversations.DeleteMany(filterConv);
return convDeleted.DeletedCount > 0 || dialogDeleted.DeletedCount > 0 || statesDeleted.DeletedCount > 0
|| exeLogDeleted.DeletedCount > 0 || promptLogDeleted.DeletedCount > 0
|| contentLogDeleted.DeletedCount > 0 || stateLogDeleted.DeletedCount > 0;
|| contentLogDeleted.DeletedCount > 0 || stateLogDeleted.DeletedCount > 0
|| convDeleted.DeletedCount > 0;
}
[SideCar]

View file

@ -0,0 +1,87 @@
using BotSharp.Abstraction.Crontab.Models;
using Microsoft.Extensions.Logging;
namespace BotSharp.Plugin.MongoStorage.Repository;
public partial class MongoRepository
{
public bool UpsertCrontabItem(CrontabItem item)
{
if (item == null || string.IsNullOrWhiteSpace(item.ConversationId))
{
return false;
}
try
{
var cronDoc = CrontabItemDocument.ToMongoModel(item);
cronDoc.Id = Guid.NewGuid().ToString();
var filter = Builders<CrontabItemDocument>.Filter.Eq(x => x.ConversationId, item.ConversationId);
var result = _dc.CrontabItems.ReplaceOne(filter, cronDoc, new ReplaceOptions
{
IsUpsert = true
});
return true;
}
catch (Exception ex)
{
_logger.LogError($"Error when saving crontab item: {ex.Message}\r\n{ex.InnerException}");
return false;
}
}
public bool DeleteCrontabItem(string conversationId)
{
if (string.IsNullOrWhiteSpace(conversationId))
{
return false;
}
var filter = Builders<CrontabItemDocument>.Filter.Eq(x => x.ConversationId, conversationId);
var result = _dc.CrontabItems.DeleteMany(filter);
return result.DeletedCount > 0;
}
public PagedItems<CrontabItem> GetCrontabItems(CrontabItemFilter filter)
{
if (filter == null)
{
filter = CrontabItemFilter.Empty();
}
var cronBuilder = Builders<CrontabItemDocument>.Filter;
var cronFilters = new List<FilterDefinition<CrontabItemDocument>>() { cronBuilder.Empty };
// Filter cron
if (filter?.AgentIds != null)
{
cronFilters.Add(cronBuilder.In(x => x.AgentId, filter.AgentIds));
}
if (filter?.ConversationIds != null)
{
cronFilters.Add(cronBuilder.In(x => x.ConversationId, filter.ConversationIds));
}
if (filter?.UserIds != null)
{
cronFilters.Add(cronBuilder.In(x => x.UserId, filter.UserIds));
}
// Sort and paginate
var filterDef = cronBuilder.And(cronFilters);
var sortDef = Builders<CrontabItemDocument>.Sort.Descending(x => x.CreatedTime);
var cronDocs = _dc.CrontabItems.Find(filterDef).Sort(sortDef).Skip(filter.Offset).Limit(filter.Size).ToList();
var count = _dc.CrontabItems.CountDocuments(filterDef);
var crontabItems = cronDocs.Select(x => CrontabItemDocument.ToDomainModel(x)).ToList();
return new PagedItems<CrontabItem>
{
Items = crontabItems,
Count = (int)count
};
}
}

View file

@ -19,6 +19,8 @@
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.2nd.plan.liquid" />
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.next.liquid" />
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.summarize.liquid" />
<None Remove="data\agents\3e75e818-a139-48a8-9e22-4662548c13a3\agent.json" />
<None Remove="data\agents\3e75e818-a139-48a8-9e22-4662548c13a3\instructions\instruction.liquid" />
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\util-planner-plan_secondary_stage.fn.liquid" />
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\util-planner-plan_primary_stage.fn.liquid" />
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\util-planner-plan_summary.fn.liquid" />
@ -52,6 +54,12 @@
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.1st.plan.liquid">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="data\agents\3e75e818-a139-48a8-9e22-4662548c13a3\agent.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="data\agents\3e75e818-a139-48a8-9e22-4662548c13a3\instructions\instruction.liquid">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\util-planner-plan_secondary_stage.fn.liquid">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View file

@ -0,0 +1,9 @@
using Microsoft.AspNetCore.Http;
namespace BotSharp.Plugin.Planner.Enums;
public class PlannerAgentId
{
public const string TwoStagePlanner = "282a7128-69a1-44b0-878c-a9159b88f3b9";
public const string SequentialPlanner = "3e75e818-a139-48a8-9e22-4662548c13a3";
}

View file

@ -49,8 +49,8 @@ public class PrimaryStagePlanFn : IFunctionCallback
var prompt = await GetFirstStagePlanPrompt(message, task.Requirements, knowledges);
var plannerAgent = new Agent
{
Id = BuiltInAgentId.Planner,
Name = "FirstStagePlanner",
Id = message.CurrentAgentId,
Name = Name,
Instruction = prompt,
TemplateDict = new Dictionary<string, object>(),
LlmConfig = currentAgent.LlmConfig
@ -70,7 +70,7 @@ public class PrimaryStagePlanFn : IFunctionCallback
var render = _services.GetRequiredService<ITemplateRender>();
var knowledgeHooks = _services.GetServices<IKnowledgeHook>();
var agent = await agentService.GetAgent(BuiltInAgentId.Planner);
var agent = await agentService.GetAgent(PlannerAgentId.TwoStagePlanner);
var template = agent.Templates.FirstOrDefault(x => x.Name == "two_stage.1st.plan")?.Content ?? string.Empty;
var responseFormat = JsonSerializer.Serialize(new FirstStagePlan{});

View file

@ -53,8 +53,8 @@ public class SecondaryStagePlanFn : IFunctionCallback
var plannerAgent = new Agent
{
Id = BuiltInAgentId.Planner,
Name = "SecondStagePlanner",
Id = PlannerAgentId.TwoStagePlanner,
Name = Name,
Instruction = prompt,
TemplateDict = new Dictionary<string, object>(),
LlmConfig = currentAgent.LlmConfig

View file

@ -1,8 +1,5 @@
using BotSharp.Abstraction.Planning;
using BotSharp.Plugin.Planner.TwoStaging;
using BotSharp.Plugin.Planner.TwoStaging.Models;
using static System.Net.Mime.MediaTypeNames;
using System.Text.RegularExpressions;
namespace BotSharp.Plugin.Planner.Functions;
@ -62,8 +59,8 @@ public class SummaryPlanFn : IFunctionCallback
var plannerAgent = new Agent
{
Id = BuiltInAgentId.Planner,
Name = "SummaryPlanner",
Id = PlannerAgentId.TwoStagePlanner,
Name = Name,
Instruction = prompt,
LlmConfig = currentAgent.LlmConfig
};
@ -93,7 +90,7 @@ public class SummaryPlanFn : IFunctionCallback
var render = _services.GetRequiredService<ITemplateRender>();
var knowledgeHooks = _services.GetServices<IKnowledgeHook>();
var agent = await agentService.GetAgent(BuiltInAgentId.Planner);
var agent = await agentService.GetAgent(PlannerAgentId.TwoStagePlanner);
var template = agent.Templates.FirstOrDefault(x => x.Name == "two_stage.summarize")?.Content ?? string.Empty;
var additionalRequirements = new List<string>();

View file

@ -2,7 +2,7 @@ namespace BotSharp.Plugin.Planner.Hooks;
public class PlannerAgentHook : AgentHookBase
{
public override string SelfId => BuiltInAgentId.Planner;
public override string SelfId => PlannerAgentId.TwoStagePlanner;
public PlannerAgentHook(IServiceProvider services, AgentSettings settings)
: base(services, settings)
@ -19,7 +19,7 @@ public class PlannerAgentHook : AgentHookBase
{
var k = hook.GetGlobalKnowledges(new RoleDialogModel(AgentRole.User, template)
{
CurrentAgentId = BuiltInAgentId.Planner
CurrentAgentId = PlannerAgentId.TwoStagePlanner
}).Result;
Knowledges.AddRange(k);
}

View file

@ -1,4 +1,4 @@
using BotSharp.Abstraction.Planning;
using BotSharp.Plugin.Planner.Sequential;
using BotSharp.Plugin.Planner.TwoStaging;
namespace BotSharp.Plugin.Planner;
@ -13,10 +13,15 @@ public class PlannerPlugin : IBotSharpPlugin
public string Description => "Provide AI with different planning approaches to improve AI's ability to solve complex problems.";
public string IconUrl => "https://e7.pngegg.com/pngimages/775/350/png-clipart-action-plan-computer-icons-plan-miscellaneous-text-thumbnail.png";
public string[] AgentIds => [ BuiltInAgentId.Planner ];
public string[] AgentIds =>
[
PlannerAgentId.TwoStagePlanner,
PlannerAgentId.SequentialPlanner
];
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
services.AddScoped<ITaskPlanner, SequentialPlanner>();
services.AddScoped<ITaskPlanner, TwoStageTaskPlanner>();
services.AddScoped<IAgentHook, PlannerAgentHook>();
services.AddScoped<IAgentUtilityHook, PlannerUtilityHook>();

View file

@ -14,26 +14,23 @@
limitations under the License.
******************************************************************************/
using BotSharp.Abstraction.MLTasks;
using BotSharp.Abstraction.Routing.Models;
using BotSharp.Abstraction.Routing.Reasoning;
using BotSharp.Abstraction.Templating;
namespace BotSharp.Core.Routing.Reasoning;
namespace BotSharp.Plugin.Planner.Sequential;
/// <summary>
/// Sequential tasks focused reasoning approach
/// A Sequential Planner for a large language model (LLM) is a framework or methodology to execute some list tasks in a predefined order by the user,
/// LLM can follow to produce an organized and coherent output.
/// Sequential Planners are useful for tasks that involve multiple stages of reasoning, information retrieval, or interdependent subtasks.
/// </summary>
public class SequentialReasoner : IRoutingReasoner
public class SequentialPlanner : ITaskPlanner
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
public string Name => "Sequential-Planner";
public bool HideDialogContext => true;
public int MaxLoopCount => 100;
private FunctionCallFromLlm _lastInst;
public SequentialReasoner(IServiceProvider services, ILogger<SequentialReasoner> logger)
public SequentialPlanner(IServiceProvider services, ILogger<SequentialPlanner> logger)
{
_services = services;
_logger = logger;
@ -91,7 +88,7 @@ public class SequentialReasoner : IRoutingReasoner
{
new RoleDialogModel(AgentRole.User, next)
{
FunctionName = nameof(SequentialReasoner),
FunctionName = nameof(SequentialPlanner),
MessageId = messageId
}
};
@ -158,7 +155,7 @@ public class SequentialReasoner : IRoutingReasoner
if (message.StopCompletion)
{
context.Empty(reason: $"Agent queue is cleared by {nameof(SequentialReasoner)}");
context.Empty(reason: $"Agent queue is cleared by {nameof(SequentialPlanner)}");
return false;
}
@ -204,7 +201,7 @@ public class SequentialReasoner : IRoutingReasoner
var response = await completion.GetChatCompletions(new Agent
{
Id = router.Id,
Name = nameof(SequentialReasoner),
Name = nameof(SequentialPlanner),
Instruction = systemPrompt
}, dialogs);

View file

@ -1,13 +1,38 @@
using BotSharp.Abstraction.Infrastructures.Enums;
using BotSharp.Abstraction.Planning;
using BotSharp.Core.Routing.Reasoning;
/*****************************************************************************
Copyright 2024 Written by Haiping Chen. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************/
namespace BotSharp.Plugin.Planner.TwoStaging;
/// <summary>
/// The Two-Stage Planner approach in large language models(LLMs) is an effective strategy to handle complex tasks by breaking them into manageable steps.
/// This involves creating a high-level plan in the first stage and then drilling down into the details in the second stage.
///
/// Primary stage:
/// The LLM generates a structured overview or roadmap for solving the problem.
/// The focus here is on creating a broad and logically organized set of actions or categories that guide the overall process.
///
/// Secondary stage:
/// For each step or component in the high-level plan, the LLM elaborates with specific actions, tools, or techniques.
/// The focus shifts to operationalizing the roadmap.
/// </summary>
public partial class TwoStageTaskPlanner : ITaskPlanner
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
public string Name => "Two-Stage-Planner";
public int MaxLoopCount => 10;
public TwoStageTaskPlanner(IServiceProvider services, ILogger<TwoStageTaskPlanner> logger)
@ -23,8 +48,8 @@ public partial class TwoStageTaskPlanner : ITaskPlanner
// chat completion
var completion = CompletionProvider.GetChatCompletion(_services,
provider: router?.LlmConfig?.Provider,
model: router?.LlmConfig?.Model);
provider: router?.LlmConfig?.Provider,
model: router?.LlmConfig?.Model);
// text completion
dialogs = new List<RoleDialogModel>
@ -36,12 +61,10 @@ public partial class TwoStageTaskPlanner : ITaskPlanner
}
};
var response = await completion.GetChatCompletions(router, dialogs);
inst = response.Content.JsonContent<FunctionCallFromLlm>();
// Fix LLM malformed response
ReasonerHelper.FixMalformedResponse(_services, inst);
return inst;
}
@ -99,7 +122,7 @@ public partial class TwoStageTaskPlanner : ITaskPlanner
private async Task<string> GetNextStepPrompt(Agent router)
{
var agentService = _services.GetRequiredService<IAgentService>();
var planner = await agentService.LoadAgent(BuiltInAgentId.Planner);
var planner = await agentService.LoadAgent(PlannerAgentId.TwoStagePlanner);
var template = planner.Templates.First(x => x.Name == "two_stage.next").Content;
var states = _services.GetRequiredService<IConversationStateService>();
var render = _services.GetRequiredService<ITemplateRender>();

View file

@ -18,19 +18,19 @@ global using BotSharp.Abstraction.Conversations;
global using BotSharp.Abstraction.Functions.Models;
global using BotSharp.Abstraction.Repositories;
global using BotSharp.Abstraction.Utilities;
global using BotSharp.Abstraction.Conversations.Models;
global using BotSharp.Abstraction.Functions;
global using BotSharp.Abstraction.Routing;
global using BotSharp.Abstraction.Templating;
global using BotSharp.Abstraction.Knowledges;
global using BotSharp.Abstraction.Knowledges.Settings;
global using BotSharp.Abstraction.Knowledges.Enums;
global using BotSharp.Abstraction.VectorStorage.Models;
global using BotSharp.Abstraction.VectorStorage.Extensions;
global using BotSharp.Abstraction.Infrastructures.Enums;
global using BotSharp.Abstraction.Planning;
global using BotSharp.Abstraction.MLTasks;
global using BotSharp.Abstraction.Routing.Models;
global using BotSharp.Core.Infrastructures;
global using BotSharp.Core.Routing.Reasoning;
global using BotSharp.Plugin.Planner.Hooks;
global using BotSharp.Plugin.Planner.Enums;
global using BotSharp.Core.Infrastructures;

View file

@ -1,8 +1,8 @@
{
"id": "282a7128-69a1-44b0-878c-a9159b88f3b9",
"name": "Planner",
"description": "Plan feasible implementation steps for complex user task request, including generating sql query",
"type": "task",
"name": "Two-Stage-Planner",
"description": "Plan feasible steps for complex user task request, including generating sql query",
"type": "planning",
"createdDateTime": "2023-08-27T10:39:00Z",
"updatedDateTime": "2023-08-27T14:39:00Z",
"iconUrl": "https://e7.pngegg.com/pngimages/775/350/png-clipart-action-plan-computer-icons-plan-miscellaneous-text-thumbnail.png",
@ -13,7 +13,7 @@
"utilities": [],
"llmConfig": {
"provider": "openai",
"model": "gpt-4o",
"model": "gpt-4o-2024-11-20",
"max_recursion_depth": 10
}
}

View file

@ -15,7 +15,8 @@ Thinking process:
4. Output all the subtasks as much detail as possible in JSON: [{{ response_format }}]
5. You can NOT generate the final query before calling function plan_summary.
Note:If the task includes repeat steps,e.g.same steps for multiple elements, only generate a single detailed solution without repeating steps for each elements. You can add multiple items in the input and output args.
Note:
* If the task includes repeat steps,e.g.same steps for multiple elements, only generate a single detailed solution without repeating steps for each elements.
{% if global_knowledges != empty -%}
=====

View file

@ -0,0 +1,19 @@
{
"id": "3e75e818-a139-48a8-9e22-4662548c13a3",
"name": "Sequential-Planner",
"description": "Plan an ordered plan steps to execute some tasks in a predefined order by the user",
"type": "planning",
"createdDateTime": "2023-08-27T10:39:00Z",
"updatedDateTime": "2023-08-27T14:39:00Z",
"iconUrl": "https://www.shutterstock.com/image-vector/sequential-process-glyph-icon-order-260nw-1015790182.jpg",
"disabled": false,
"isPublic": true,
"profiles": [ "planning" ],
"mergeUtility": true,
"utilities": [],
"llmConfig": {
"provider": "openai",
"model": "gpt-4o-2024-11-20",
"max_recursion_depth": 10
}
}

View file

@ -0,0 +1,15 @@
You are a Task Planner. you will breakdown user business requirements into excutable sub-steps.
Follow the instructions below to plan and execute tasks:
1. Look at all the steps first, think carefully, and decide which step to do first.
2. Look at the description of each step, and use the existing functions and tools to plan the execution steps.
{% if global_knowledges != empty -%}
=====
Global Knowledge:
Current date time is: {{ "now" | date: "%Y-%m-%d %H:%M" }}
{% for k in global_knowledges %}
{{ k }}
{% endfor %}
=====
{%- endif %}

View file

@ -4,7 +4,7 @@ namespace BotSharp.Plugin.SqlDriver.Hooks;
public class SqlDriverAgentHook : AgentHookBase, IAgentHook
{
public override string SelfId => BuiltInAgentId.Planner;
public override string SelfId => string.Empty;
public SqlDriverAgentHook(IServiceProvider services, AgentSettings settings)
: base(services, settings)

View file

@ -1,6 +1,7 @@
using BotSharp.Abstraction.Crontab.Models;
using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.SideCar;
using BotSharp.Core.Crontab.Abstraction;
using BotSharp.Core.Crontab.Models;
using Microsoft.EntityFrameworkCore.Query;
namespace BotSharp.Plugin.SqlDriver.Hooks;
@ -16,16 +17,22 @@ public class SqlDriverCrontabHook : ICrontabHook
public async Task OnCronTriggered(CrontabItem item)
{
if (item.Language != "sql")
/*var conv = _services.GetRequiredService<IConversationService>();
conv.SetConversationId("abd9df25-2210-4e4d-80d7-48b6a3b905a8", []);
if (item.Language == "text")
{
var sidecar = _services.GetService<IConversationSideCar>();
var response = await sidecar.SendMessage(BuiltInAgentId.AIAssistant, item.Description, states: new List<MessageState>());
return;
}
else if (item.Language != "sql")
{
return;
}
_logger.LogWarning($"Crontab item triggered: {item.Topic}. Run {item.Language}: {item.Script}");
var conv = _services.GetRequiredService<IConversationService>();
conv.SetConversationId("73a9ee27-d597-4739-958f-3bd79760ac8e", []);
var message = new RoleDialogModel(AgentRole.User, $"Run the query")
{
FunctionName = "sql_select",
@ -42,6 +49,6 @@ public class SqlDriverCrontabHook : ICrontabHook
item.ConversationId = conv.ConversationId;
item.AgentId = BuiltInAgentId.SqlDriver;
item.UserId = "41021346";
item.ExecutionResult = message.Content;
item.ExecutionResult = message.Content;*/
}
}

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>$(TargetFramework)</TargetFramework>
@ -29,6 +29,7 @@
<ItemGroup>
<ProjectReference Include="..\..\tests\BotSharp.Plugin.PizzaBot\BotSharp.Plugin.PizzaBot.csproj" />
<ProjectReference Include="..\BotSharp.ServiceDefaults\BotSharp.ServiceDefaults.csproj" />
<ProjectReference Include="..\Infrastructure\BotSharp.Core.Crontab\BotSharp.Core.Crontab.csproj" />
<ProjectReference Include="..\Infrastructure\BotSharp.Core.SideCar\BotSharp.Core.SideCar.csproj" />
</ItemGroup>

View file

@ -328,6 +328,7 @@
"Assemblies": [
"BotSharp.Core",
"BotSharp.Core.SideCar",
"BotSharp.Core.Crontab",
"BotSharp.Logger",
"BotSharp.Plugin.MongoStorage",
"BotSharp.Plugin.Dashboard",