diff --git a/docs/assets/BotSharp.min.psd b/docs/assets/BotSharp.min.psd deleted file mode 100644 index 81e005f88..000000000 Binary files a/docs/assets/BotSharp.min.psd and /dev/null differ diff --git a/docs/assets/BotSharp.psd b/docs/assets/BotSharp.psd deleted file mode 100644 index 788c3b062..000000000 Binary files a/docs/assets/BotSharp.psd and /dev/null differ diff --git a/docs/assets/front-cover.psd b/docs/assets/front-cover.psd deleted file mode 100644 index 1a3bef71c..000000000 Binary files a/docs/assets/front-cover.psd and /dev/null differ diff --git a/docs/static/logos/BotSharp.min.png b/docs/static/logos/BotSharp.min.png deleted file mode 100644 index 335e43ad2..000000000 Binary files a/docs/static/logos/BotSharp.min.png and /dev/null differ diff --git a/docs/static/logos/BotSharp.png b/docs/static/logos/BotSharp.png deleted file mode 100644 index 2a1eb9071..000000000 Binary files a/docs/static/logos/BotSharp.png and /dev/null differ diff --git a/docs/static/logos/favicon.ico b/docs/static/logos/favicon.ico deleted file mode 100644 index b150f5f41..000000000 Binary files a/docs/static/logos/favicon.ico and /dev/null differ diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/IKnowledgeService.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IKnowledgeService.cs index d7a9c0f23..4f960feef 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Knowledges/IKnowledgeService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IKnowledgeService.cs @@ -5,6 +5,7 @@ namespace BotSharp.Abstraction.Knowledges; public interface IKnowledgeService { Task Feed(KnowledgeFeedModel knowledge); + Task EmbedKnowledge(KnowledgeCreationModel knowledge); Task GetKnowledges(KnowledgeRetrievalModel retrievalModel); Task> GetAnswer(KnowledgeRetrievalModel retrievalModel); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPdf2TextConverter.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPdf2TextConverter.cs index 0ae85b303..d2ca29403 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPdf2TextConverter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPdf2TextConverter.cs @@ -7,6 +7,6 @@ namespace BotSharp.Abstraction.Knowledges { public interface IPdf2TextConverter { - Task ConvertPdfToText(IFormFile formFile, int? startPageNum, int? endPageNum); + Task ConvertPdfToText(string filePath, int? startPageNum, int? endPageNum); } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/KnowledgeCreationModel.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/KnowledgeCreationModel.cs new file mode 100644 index 000000000..33d09bd6d --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/KnowledgeCreationModel.cs @@ -0,0 +1,6 @@ +namespace BotSharp.Abstraction.Knowledges.Models; + +public class KnowledgeCreationModel +{ + public string Content { get; set; } = string.Empty; +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentFilter.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentFilter.cs index b5da6d369..f685af645 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentFilter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentFilter.cs @@ -7,5 +7,6 @@ public class AgentFilter public bool? AllowRouting { get; set; } public bool? IsPublic { get; set; } public bool? IsRouter { get; set; } + public bool? IsEvaluator { get; set; } public List? AgentIds { get; set; } } diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs index eb3237265..0df9ed98d 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs @@ -8,6 +8,7 @@ using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Repositories.Models; using BotSharp.Abstraction.Routing.Settings; +using BotSharp.Abstraction.Evaluations.Settings; namespace BotSharp.Core.Repository; @@ -552,6 +553,14 @@ public List GetAgents(AgentFilter filter) query.Where(x => x.Id != route.AgentId); } + if (filter.IsEvaluator.HasValue) + { + var evaluate = _services.GetRequiredService(); + query = filter.IsEvaluator.Value ? + query.Where(x => x.Id == evaluate.AgentId) : + query.Where(x => x.Id != evaluate.AgentId); + } + if (filter.AgentIds != null) { query = query.Where(x => filter.AgentIds.Contains(x.Id)); diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs index 24f8a61b9..36c484760 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs @@ -1,3 +1,5 @@ +using BotSharp.Abstraction.Routing.Settings; + namespace BotSharp.OpenAPI.Controllers; [Authorize] @@ -13,6 +15,13 @@ public AgentController(IAgentService agentService, IServiceProvider services) _services = services; } + [HttpGet("/agent/settings")] + public AgentSettings GetSettings() + { + var settings = _services.GetRequiredService(); + return settings; + } + [HttpGet("/agent/{id}")] public async Task GetAgent([FromRoute] string id) { diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ApplicationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ApplicationController.cs new file mode 100644 index 000000000..1c8b9cbf6 --- /dev/null +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ApplicationController.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.Hosting; + +namespace BotSharp.OpenAPI.Controllers; + +[Authorize] +[ApiController] +public class ApplicationController : ControllerBase +{ + private readonly IServiceProvider _services; + public ApplicationController(IServiceProvider services) + { + _services = services; + } + + [HttpGet("/app/shutdown")] + public IActionResult Restart() + { + var app = _services.GetRequiredService(); + app.StopApplication(); + return Ok(); + } +} diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/EvaluationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/EvaluatorController.cs similarity index 79% rename from src/Infrastructure/BotSharp.OpenAPI/Controllers/EvaluationController.cs rename to src/Infrastructure/BotSharp.OpenAPI/Controllers/EvaluatorController.cs index d2ea3f0e2..b6d6f60eb 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/EvaluationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/EvaluatorController.cs @@ -5,29 +5,29 @@ namespace BotSharp.OpenAPI.Controllers; [Authorize] [ApiController] -public class EvaluationController : ControllerBase +public class EvaluatorController : ControllerBase { private readonly IServiceProvider _services; - public EvaluationController(IServiceProvider services) + public EvaluatorController(IServiceProvider services) { _services = services; } - [HttpPost("/evaluation/execute/{task}")] + [HttpPost("/evaluator/execute/{task}")] public async Task Execute([FromRoute] string task, [FromBody] EvaluationRequest request) { var eval = _services.GetRequiredService(); return await eval.Execute(task, request); } - [HttpPost("/evaluation/review/{conversationId}")] + [HttpPost("/evaluator/review/{conversationId}")] public async Task Review([FromRoute] string conversationId, [FromBody] EvaluationRequest request) { var eval = _services.GetRequiredService(); return await eval.Review(conversationId, request); } - [HttpPost("/evaluation/evaluate/{conversationId}")] + [HttpPost("/evaluator/evaluate/{conversationId}")] public async Task Evaluate([FromRoute] string conversationId, [FromBody] EvaluationRequest request) { var eval = _services.GetRequiredService(); diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeBaseController.cs similarity index 53% rename from src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeController.cs rename to src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeBaseController.cs index 0801fcf29..7e346b75d 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeBaseController.cs @@ -1,20 +1,22 @@ using BotSharp.Abstraction.Knowledges.Models; using BotSharp.Abstraction.Knowledges.Settings; +using Microsoft.AspNetCore.Http; namespace BotSharp.OpenAPI.Controllers; [Authorize] [ApiController] -public class KnowledgeController : ControllerBase +public class KnowledgeBaseController : ControllerBase { private readonly IKnowledgeService _knowledgeService; private readonly IServiceProvider _services; - public KnowledgeController(IKnowledgeService knowledgeService, IServiceProvider services) + public KnowledgeBaseController(IKnowledgeService knowledgeService, IServiceProvider services) { _knowledgeService = knowledgeService; _services = services; } + [HttpGet("/knowledge/{agentId}")] public async Task> RetrieveKnowledge([FromRoute] string agentId, [FromQuery(Name = "q")] string question) { @@ -25,6 +27,33 @@ public async Task> RetrieveKnowledge([FromRoute] string ag }); } + [HttpPost("/knowledge-base/upload")] + public async Task UploadKnowledge(IFormFile file, [FromQuery] int? startPageNum, [FromQuery] int? endPageNum) + { + var setttings = _services.GetRequiredService(); + var textConverter = _services.GetServices() + .First(x => x.GetType().FullName.EndsWith(setttings.Pdf2TextConverter)); + + var filePath = Path.GetTempFileName(); + using (var stream = System.IO.File.Create(filePath)) + { + await file.CopyToAsync(stream); + } + + var content = await textConverter.ConvertPdfToText(filePath, startPageNum, endPageNum); + + // Process uploaded files + // Don't rely on or trust the FileName property without validation. + + // Add FeedWithMetaData + await _knowledgeService.EmbedKnowledge(new KnowledgeCreationModel + { + Content = content + }); + + return Ok(new { count = 1, file.Length }); + } + [HttpPost("/knowledge/{agentId}")] public async Task FeedKnowledge([FromRoute] string agentId, List files, [FromQuery] int? startPageNum, [FromQuery] int? endPageNum, [FromQuery] bool? paddleModel) { @@ -34,9 +63,11 @@ public async Task FeedKnowledge([FromRoute] string agentId, List< foreach (var formFile in files) { - var content = ""; + var filePath = Path.GetTempFileName(); + using var stream = System.IO.File.Create(filePath); + await formFile.CopyToAsync(stream); - content = await textConverter.ConvertPdfToText(formFile, startPageNum, endPageNum); + var content = await textConverter.ConvertPdfToText(filePath, startPageNum, endPageNum); // Process uploaded files // Don't rely on or trust the FileName property without validation. diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/RouterController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/RouterController.cs new file mode 100644 index 000000000..a6b088018 --- /dev/null +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/RouterController.cs @@ -0,0 +1,21 @@ +using BotSharp.Abstraction.Routing.Settings; + +namespace BotSharp.OpenAPI.Controllers; + +[Authorize] +[ApiController] +public class RouterController : ControllerBase +{ + private readonly IServiceProvider _services; + public RouterController(IServiceProvider services) + { + _services = services; + } + + [HttpGet("/router/settings")] + public RoutingSettings GetSettings() + { + var settings = _services.GetRequiredService(); + return settings; + } +} diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.cs index eef38f63a..3cdc2d05e 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.cs @@ -15,6 +15,29 @@ public KnowledgeService(IServiceProvider services, _textChopper = textChopper; } + public async Task EmbedKnowledge(KnowledgeCreationModel knowledge) + { + var idStart = 0; + var lines = _textChopper.Chop(knowledge.Content, new ChunkOption + { + Size = 1024, + Conjunction = 32, + SplitByWord = true, + }); + + var db = GetVectorDb(); + var textEmbedding = GetTextEmbedding(); + + await db.CreateCollection("shared", textEmbedding.Dimension); + foreach (var line in lines) + { + var vec = await textEmbedding.GetVectorAsync(line); + await db.Upsert("shared", idStart, vec, line); + idStart++; + Console.WriteLine($"Saved vector {idStart}/{lines.Count}: {line}\n"); + } + } + public async Task Feed(KnowledgeFeedModel knowledge) { var idStart = 0; diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/PigPdf2TextConverter.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/PigPdf2TextConverter.cs index a8875ec16..58fb15529 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/PigPdf2TextConverter.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/PigPdf2TextConverter.cs @@ -1,4 +1,3 @@ -using Microsoft.AspNetCore.Http; using UglyToad.PdfPig; using UglyToad.PdfPig.Content; @@ -6,25 +5,13 @@ namespace BotSharp.Plugin.KnowledgeBase.Services; public class PigPdf2TextConverter : IPdf2TextConverter { - public async Task ConvertPdfToText(IFormFile formFile, int? startPageNum, int? endPageNum) + public async Task ConvertPdfToText(string filePath, int? startPageNum, int? endPageNum) { - return await OpenPdfDocumentAsync(formFile, startPageNum, endPageNum); + return await OpenPdfDocumentAsync(filePath, startPageNum, endPageNum); } - private async Task OpenPdfDocumentAsync(IFormFile formFile, int? startPageNum, int? endPageNum) + private async Task OpenPdfDocumentAsync(string filePath, int? startPageNum, int? endPageNum) { - if (formFile.Length <= 0) - { - return await Task.FromResult(string.Empty); - } - - var filePath = Path.GetTempFileName(); - - using (var stream = System.IO.File.Create(filePath)) - { - await formFile.CopyToAsync(stream); - } - var document = PdfDocument.Open(filePath); var content = ""; foreach (Page page in document.GetPages()) diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs index 7a967f2ab..4b94911d7 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Conversations.Models; +using BotSharp.Abstraction.Evaluations.Settings; using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Repositories.Models; @@ -470,6 +471,14 @@ public List GetAgents(AgentFilter filter) query.Where(x => x.Id != route.AgentId); } + if (filter.IsEvaluator.HasValue) + { + var evaluate = _services.GetRequiredService(); + query = filter.IsEvaluator.Value ? + query.Where(x => x.Id == evaluate.AgentId) : + query.Where(x => x.Id != evaluate.AgentId); + } + if (filter.AgentIds != null) { query = query.Where(x => filter.AgentIds.Contains(x.Id)); diff --git a/src/Plugins/BotSharp.Plugin.PaddleSharp/Providers/Pdf2TextConverter.cs b/src/Plugins/BotSharp.Plugin.PaddleSharp/Providers/Pdf2TextConverter.cs index e21811f7a..58f2015a5 100644 --- a/src/Plugins/BotSharp.Plugin.PaddleSharp/Providers/Pdf2TextConverter.cs +++ b/src/Plugins/BotSharp.Plugin.PaddleSharp/Providers/Pdf2TextConverter.cs @@ -12,10 +12,8 @@ using System.Threading.Tasks; using BotSharp.Abstraction.Knowledges; using System.Linq; -using Docnet; using Docnet.Core.Models; using Docnet.Core; -using Docnet.Core.Converters; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; @@ -33,9 +31,9 @@ public Pdf2TextConverter(PaddleSharpSettings paddleSharpSettings) _paddleSharpSettings = paddleSharpSettings; } - public async Task ConvertPdfToText(IFormFile formFile, int? startPageNum, int? endPageNum) + public async Task ConvertPdfToText(string filePath, int? startPageNum, int? endPageNum) { - await ConvertPdfToLocalImagesAsync(formFile, startPageNum, endPageNum); + await ConvertPdfToLocalImagesAsync(filePath, startPageNum, endPageNum); return await LocalImageToTextsAsync(); } @@ -115,17 +113,10 @@ public void DocnetConverter(string filePath, int width = 1080, int height = 1920 }; } - private async Task ConvertPdfToLocalImagesAsync(IFormFile formFile, int? startPageNum, int? endPageNum) + private async Task ConvertPdfToLocalImagesAsync(string filePath, int? startPageNum, int? endPageNum) { string rootFileName; - var filePath = Path.GetTempFileName(); - - using (var stream = System.IO.File.Create(filePath)) - { - await formFile.CopyToAsync(stream); - } - using var images = new MagickImageCollection(); // _magicReadSettings.Density = new Density((double)300); /* diff --git a/src/WebStarter/Program.cs b/src/WebStarter/Program.cs index 497fbf4e7..5aa02e012 100644 --- a/src/WebStarter/Program.cs +++ b/src/WebStarter/Program.cs @@ -39,7 +39,8 @@ builder.Services.AddCors(options => { options.AddPolicy("MyCorsPolicy", - builder => builder.WithOrigins("http://localhost:5015") + builder => builder.WithOrigins("http://localhost:5015", + "https://botsharp.scisharpstack.org") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials()); diff --git a/src/WebStarter/WebStarter.csproj b/src/WebStarter/WebStarter.csproj index ff79aa88a..1f011ef6f 100644 --- a/src/WebStarter/WebStarter.csproj +++ b/src/WebStarter/WebStarter.csproj @@ -38,8 +38,8 @@ - - + + diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index 68856631f..345aababd 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -143,7 +143,8 @@ // "TextEmbedding": "LLamaSharp.TextEmbeddingProvider", "TextCompletion": "AzureOpenAI.Providers.TextCompletionProvider", // "TextCompletion": "LLamaSharp.TextCompletionProvider", - "Pdf2TextConverter": "PaddleSharp.Providers.Pdf2TextConverter" + // "Pdf2TextConverter": "PaddleSharp.Providers.Pdf2TextConverter" + "Pdf2TextConverter": "PigPdf2TextConverter" }, "PluginLoader": { diff --git a/tests/Dishwasher-Whirlpool.pdf b/tests/Dishwasher-Whirlpool.pdf deleted file mode 100644 index 19b559dae..000000000 Binary files a/tests/Dishwasher-Whirlpool.pdf and /dev/null differ