Merge pull request #777 from hchen2020/master

Fix Mongo version issue.
This commit is contained in:
Haiping 2024-12-03 23:07:44 +00:00 committed by GitHub
commit 792096917d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 392 additions and 15 deletions

View file

@ -51,4 +51,14 @@ public class BuiltInAgentId
/// Evaluate prompt and conversation
/// </summary>
public const string Evaluator = "dfd9b46d-d00c-40af-8a75-3fbdc2b89869";
/// <summary>
/// Translates user-defined natural language rules into programmatic code
/// </summary>
public const string RuleEncoder = "6acfb93c-3412-402e-9ba5-c5d3cd8f0161";
/// <summary>
/// Schedule job
/// </summary>
public const string Crontab = "c2o139da-a62a-4355-8605-fdf0ffaca58e";
}

View file

@ -7,4 +7,5 @@ public class ConversationChannel
public const string Phone = "phone";
public const string Messenger = "messenger";
public const string Email = "email";
public const string Cron = "cron";
}

View file

@ -0,0 +1,7 @@
namespace BotSharp.Abstraction.Infrastructures;
public interface IDistributedLocker
{
bool Lock(string resource, Action action, int timeout = 30);
Task<bool> LockAsync(string resource, Func<Task> action, int timeout = 30);
}

View file

@ -0,0 +1,8 @@
using BotSharp.Core.Crontab.Models;
namespace BotSharp.Core.Crontab.Abstraction;
public interface ICrontabHook
{
Task OnCronTriggered(CrontabItem item);
}

View file

@ -0,0 +1,9 @@
using BotSharp.Core.Crontab.Models;
namespace BotSharp.Core.Crontab.Abstraction;
public interface ICrontabService
{
Task<List<CrontabItem>> GetCrontable();
Task ScheduledTimeArrived(CrontabItem item);
}

View file

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<None Remove="data\agents\c2o139da-a62a-4355-8605-fdf0ffaca58e\agent.json" />
</ItemGroup>
<ItemGroup>
<Content Include="data\agents\c2o139da-a62a-4355-8605-fdf0ffaca58e\agent.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
<ProjectReference Include="..\BotSharp.Core\BotSharp.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NCrontab" Version="3.3.3" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,40 @@
/*****************************************************************************
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.Core.Crontab;
/// <summary>
/// Crontab plugin is a time-based job scheduler in agent framework.
/// The cron system is used for automating repetitive tasks, such as trigger AI Agent to do specific task periodically.
/// </summary>
public class CrontabPlugin : IBotSharpPlugin
{
public string Id => "3155c15e-28d3-43f7-8ead-fc43324ec21a";
public string Name => "BotSharp Crontab";
public string Description => "Crontab plugin is a time-based job scheduler in agent framework. The cron system is used to trigger AI Agent to do specific task periodically.";
public string IconUrl => "https://icon-library.com/images/stop-watch-icon/stop-watch-icon-10.jpg";
public string[] AgentIds =
[
BuiltInAgentId.Crontab
];
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
services.AddScoped<ICrontabService, CrontabService>();
services.AddHostedService<CrontabWatcher>();
}
}

View file

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

View file

@ -0,0 +1,77 @@
/*****************************************************************************
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.Agents.Enums;
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 Microsoft.Extensions.Logging;
namespace BotSharp.Core.Crontab.Services;
/// <summary>
/// The Crontab service schedules distributed events based on the execution times provided by users.
/// In a scalable environment, distributed locks are used to ensure that each event is triggered only once.
/// </summary>
public class CrontabService : ICrontabService
{
private readonly IServiceProvider _services;
private ILogger _logger;
public CrontabService(IServiceProvider services, ILogger<CrontabService> logger)
{
_services = services;
_logger = logger;
}
public async Task<List<CrontabItem>> GetCrontable()
{
return
[
new CrontabItem
{
Cron = "*/30 * * * * *",
AgentId = BuiltInAgentId.AIAssistant,
}
];
}
public async Task ScheduledTimeArrived(CrontabItem item)
{
_logger.LogInformation("ScheduledTimeArrived");
await HookEmitter.Emit<ICrontabHook>(_services, async hook =>
await hook.OnCronTriggered(item)
);
await Task.Delay(1000 * 10);
}
}

View file

@ -0,0 +1,70 @@
using BotSharp.Abstraction.Infrastructures;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NCrontab;
namespace BotSharp.Core.Crontab.Services;
public class CrontabWatcher : BackgroundService
{
private readonly ILogger _logger;
private readonly IServiceProvider _services;
public CrontabWatcher(IServiceProvider services, ILogger<CrontabWatcher> logger)
{
_logger = logger;
_services = services;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Crontab Watcher background service is running.");
using (var scope = _services.CreateScope())
{
var locker = scope.ServiceProvider.GetRequiredService<IDistributedLocker>();
while (!stoppingToken.IsCancellationRequested)
{
var delay = Task.Delay(1000, stoppingToken);
await locker.LockAsync("CrontabWatcher", async () =>
{
await RunCronChecker(scope.ServiceProvider);
});
await delay;
}
_logger.LogWarning("Crontab Watcher background service is stopped.");
}
}
private async Task RunCronChecker(IServiceProvider services)
{
var cron = services.GetRequiredService<ICrontabService>();
var crons = await cron.GetCrontable();
foreach (var item in crons)
{
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 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);
if (matches)
{
_logger.LogInformation($"The current time matches the cron expression {item}");
cron.ScheduledTimeArrived(item);
}
}
}
}

View file

@ -0,0 +1,7 @@
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using BotSharp.Abstraction.Agents.Enums;
global using BotSharp.Abstraction.Plugins;
global using BotSharp.Core.Crontab.Services;
global using BotSharp.Core.Crontab.Abstraction;

View file

@ -0,0 +1,24 @@
{
"id": "c2o139da-a62a-4355-8605-fdf0ffaca58e",
"name": "Crontab",
"description": "Convert the user-specified schedule into a Cron expression, accurate to the second level.",
"iconUrl": "https://icon-library.com/images/stop-watch-icon/stop-watch-icon-10.jpg",
"type": "task",
"createdDateTime": "2024-12-03T00:00:00Z",
"updatedDateTime": "2024-12-03T00:00:00Z",
"disabled": false,
"isPublic": true,
"profiles": [ "cron" ],
"llmConfig": {
"provider": "openai",
"model": "gpt-4o-mini"
},
"routingRules": [
{
"field": "cron_expression",
"required": true,
"field_type": "string",
"description": "A Cron expression, accurate to the second level."
}
]
}

View file

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,19 @@
namespace BotSharp.Core.Rules;
public class RulesPlugin : IBotSharpPlugin
{
public string Id => "0197c1bc-9ae6-4c56-a305-8a1b4095bebc";
public string Name => "BotSharp Rules";
public string Description => "Translates user-defined natural language rules into programmatic code and is responsible for executing these rules under user-specified conditions.";
public string IconUrl => "https://w7.pngwing.com/pngs/442/614/png-transparent-regulation-computer-icons-regulatory-compliance-medical-device-manufacturing-others-miscellaneous-blue-text-thumbnail.png";
public string[] AgentIds =
[
BuiltInAgentId.RuleEncoder
];
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
}
}

View file

@ -0,0 +1,4 @@
global using BotSharp.Abstraction.Agents.Enums;
global using BotSharp.Abstraction.Plugins;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;

View file

@ -8,8 +8,10 @@ namespace BotSharp.Core.SideCar;
public class BotSharpSideCarPlugin : IBotSharpPlugin
{
public string Id => "06e5a276-bba0-45af-9625-889267c341c9";
public string Name => "Side Car";
public string Description => "Provides side car for calling agent cluster in conversation";
public string Name => "BotSharp SideCar";
public string Description => "Provide side car pattern to to better handle Agent Cluster calls in the same conversation. Agent cluster is composed of multiple Routing Agents.";
public string? IconUrl => "https://icons.veryicon.com/png/128/internet--web/2022-alibaba-cloud-product-icon-cloud/aliyuncvc-cloud-video-conference.png";
public SettingsMeta Settings => new SettingsMeta("SideCar");
public object GetNewSettingsInstance() => new SideCarSettings();

View file

@ -25,7 +25,7 @@ public static class BotSharpCoreExtensions
config.Bind("Interpreter", interpreterSettings);
services.AddSingleton(x => interpreterSettings);
services.AddSingleton<DistributedLocker>();
services.AddSingleton<IDistributedLocker, DistributedLocker>();
// Register template render
services.AddSingleton<ITemplateRender, TemplateRender>();

View file

@ -1,9 +1,10 @@
using BotSharp.Abstraction.Infrastructures;
using Medallion.Threading.Redis;
using StackExchange.Redis;
namespace BotSharp.Core.Infrastructures;
public class DistributedLocker
public class DistributedLocker : IDistributedLocker
{
private readonly IConnectionMultiplexer _redis;
private readonly ILogger _logger;
@ -14,7 +15,7 @@ public class DistributedLocker
_logger = logger;
}
public async Task<T> Lock<T>(string resource, Func<Task<T>> action, int timeoutInSeconds = 30)
public async Task<bool> LockAsync(string resource, Func<Task> action, int timeoutInSeconds = 30)
{
var timeout = TimeSpan.FromSeconds(timeoutInSeconds);
@ -24,9 +25,11 @@ public class DistributedLocker
if (handle == null)
{
_logger.LogWarning($"Acquire lock for {resource} failed due to after {timeout}s timeout.");
return false;
}
return await action();
await action();
return true;
}
}

View file

@ -11,7 +11,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Anthropic.SDK" Version="4.1.1" />
<PackageReference Include="Anthropic.SDK" Version="4.3.0" />
</ItemGroup>
<ItemGroup>

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
@ -28,7 +28,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.8" />
<PackageReference Include="MySql.Data" Version="9.0.0" />
<PackageReference Include="NPOI" Version="2.7.1" />
</ItemGroup>

View file

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Jint" Version="4.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,24 @@
using BotSharp.Abstraction.Plugins;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace BotSharp.Plugin.JavaScriptInterpreter;
public class JsInterpreterPlugin : IBotSharpAppPlugin
{
public string Id => "7a5a8cd7-26d9-4ac3-9d79-d02084bea372";
public string Name => "JavaScript Interpreter";
public string Description => "";
public string? IconUrl => "";
public void Configure(IApplicationBuilder app)
{
}
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
}
}

View file

@ -11,7 +11,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LLamaSharp" Version="0.12.0" />
<PackageReference Include="LLamaSharp" Version="0.18.0" />
</ItemGroup>
<ItemGroup>

View file

@ -36,7 +36,6 @@ public class LlamaAiModel
_params = new ModelParams(Path.Combine(_settings.ModelDir, model))
{
ContextSize = (uint)_settings.MaxContextLength,
Seed = 1337,
GpuLayerCount = _settings.NumberOfGpuLayer
};

View file

@ -1,4 +1,6 @@
using System.IO;
using System.Xml.Linq;
using static System.Net.Mime.MediaTypeNames;
namespace BotSharp.Plugin.LLamaSharp.Providers;
@ -19,7 +21,7 @@ public class TextEmbeddingProvider : ITextEmbedding
_settings = settings;
}
public Task<float[]> GetVectorAsync(string text)
public async Task<float[]> GetVectorAsync(string text)
{
if (_embedder == null)
{
@ -29,10 +31,10 @@ public class TextEmbeddingProvider : ITextEmbedding
_embedder = new LLamaEmbedder(weights, @params);
}
return _embedder.GetEmbeddings(text);
return (await _embedder.GetEmbeddings(text)).First();
}
public Task<List<float[]>> GetVectorsAsync(List<string> texts)
public async Task<List<float[]>> GetVectorsAsync(List<string> texts)
{
throw new NotImplementedException();
}

View file

@ -25,7 +25,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="pythonnet" Version="3.0.3" />
<PackageReference Include="pythonnet" Version="3.0.4" />
</ItemGroup>
<ItemGroup>