Merge branch 'master' into lida_Dev
This commit is contained in:
commit
2e76193898
11
BotSharp.sln
11
BotSharp.sln
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(TargetFramework)</TargetFramework>
|
||||
|
|
|
|||
|
|
@ -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}]";
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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!;
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
using BotSharp.Core.Crontab.Models;
|
||||
|
||||
namespace BotSharp.Core.Crontab.Abstraction;
|
||||
|
||||
public interface ICrontabHook
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using BotSharp.Core.Crontab.Models;
|
||||
|
||||
namespace BotSharp.Core.Crontab.Abstraction;
|
||||
|
||||
public interface ICrontabService
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}]";
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ public class RoutingPlugin : IBotSharpPlugin
|
|||
|
||||
services.AddScoped<IRoutingReasoner, NaiveReasoner>();
|
||||
services.AddScoped<IRoutingReasoner, HFReasoner>();
|
||||
services.AddScoped<IRoutingReasoner, SequentialReasoner>();
|
||||
|
||||
|
||||
services.AddScoped<IRoutingReasoner, OneStepForwardReasoner>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
"routingRules": [
|
||||
{
|
||||
"type": "reasoner",
|
||||
"field": "HFReasoner"
|
||||
"field": "One-Step-Forward-Reasoner"
|
||||
},
|
||||
{
|
||||
"type": "planner",
|
||||
"field": "Sequential-Planner"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
@ -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{});
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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 -%}
|
||||
=====
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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 %}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;*/
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -328,6 +328,7 @@
|
|||
"Assemblies": [
|
||||
"BotSharp.Core",
|
||||
"BotSharp.Core.SideCar",
|
||||
"BotSharp.Core.Crontab",
|
||||
"BotSharp.Logger",
|
||||
"BotSharp.Plugin.MongoStorage",
|
||||
"BotSharp.Plugin.Dashboard",
|
||||
|
|
|
|||
Loading…
Reference in a new issue