From b55abdf4dcdf77770b6df8dd1ca6237d577bc336 Mon Sep 17 00:00:00 2001 From: hchen Date: Thu, 9 Nov 2023 15:11:36 -0600 Subject: [PATCH] IConversationAttachmentService --- README.md | 2 +- .../IConversationAttachmentService.cs | 6 ++++ .../Conversations/Models/Attachment.cs | 21 ++++++++++++++ .../BotSharpServiceCollectionExtensions.cs | 2 ++ .../Services/ConversationAttachmentService.cs | 28 ++++++++++++++++++ .../Controllers/ConversationController.cs | 29 +++++++++++++++++++ 6 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationAttachmentService.cs create mode 100644 src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Attachment.cs create mode 100644 src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationAttachmentService.cs diff --git a/README.md b/README.md index af398158..fc024a1f 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ It's written in C# running on .Net Core that is full cross-platform framework, t * Built-in multi-agents and conversation with state management. * Support multiple LLM Planning approaches to handle different tasks. * Built-in RAG related interfaces, Memeory based vector searching. -* Support multiple LLM platforms (ChatGPT 3.5 / 4.0, PaLM 2, LLaMA 2). +* Support multiple LLM platforms (ChatGPT 3.5 / 4.0, PaLM 2, LLaMA 2, HuggingFace). * Allow multiple agents with different responsibilities cooperate to complete complex tasks. * Build, test, evaluate and audit your LLM agent in one place. * Support different open source UI [Chatbot UI](src/Plugins/BotSharp.Plugin.ChatbotUI/Chatbot-UI.md), [HuggingChat UI](src/Plugins/BotSharp.Plugin.HuggingFace/HuggingChat-UI.md). diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationAttachmentService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationAttachmentService.cs new file mode 100644 index 00000000..feec3fab --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationAttachmentService.cs @@ -0,0 +1,6 @@ +namespace BotSharp.Abstraction.Conversations; + +public interface IConversationAttachmentService +{ + string GetDirectory(string conversationId); +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Attachment.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Attachment.cs new file mode 100644 index 00000000..47cdf30d --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Attachment.cs @@ -0,0 +1,21 @@ +namespace BotSharp.Abstraction.Conversations.Models; + +public class Attachment +{ + public string ContentType { get; set; } + + // + // Summary: + // Gets the raw Content-Disposition header of the uploaded file. + public string ContentDisposition { get; set; } + + // + // Summary: + // Gets the file length in bytes. + public long Length { get; set; } + + // + // Summary: + // Gets the file name from the Content-Disposition header. + public string FileName { get; set; } +} diff --git a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs index 52c70488..7ba9dbb1 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs +++ b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs @@ -102,6 +102,8 @@ public static class BotSharpServiceCollectionExtensions services.AddScoped(); services.AddScoped(); + services.AddScoped(); + return services; } diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationAttachmentService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationAttachmentService.cs new file mode 100644 index 00000000..b0625fa8 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationAttachmentService.cs @@ -0,0 +1,28 @@ +using BotSharp.Abstraction.Repositories; +using System.IO; + +namespace BotSharp.Core.Conversations.Services; + +public class ConversationAttachmentService : IConversationAttachmentService +{ + private readonly BotSharpDatabaseSettings _dbSettings; + private readonly IServiceProvider _services; + + public ConversationAttachmentService( + BotSharpDatabaseSettings dbSettings, + IServiceProvider services) + { + _dbSettings = dbSettings; + _services = services; + } + + public string GetDirectory(string conversationId) + { + var dir = Path.Combine(_dbSettings.FileRepository, "conversations", conversationId, "attachments"); + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + return dir; + } +} diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index 4635c8cd..7b5d83b0 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -2,6 +2,8 @@ using BotSharp.Abstraction.ApiAdapters; using BotSharp.Abstraction.Conversations.Models; using BotSharp.Abstraction.Models; using BotSharp.OpenAPI.ViewModels.Conversations; +using Microsoft.AspNetCore.Http; +using System.Net.Http.Headers; namespace BotSharp.OpenAPI.Controllers; @@ -78,4 +80,31 @@ public class ConversationController : ControllerBase, IApiAdapter return response; } + + [HttpPost("/conversation/{agentId}/{conversationId}/attachments")] + public IActionResult UploadAttachments([FromRoute] string agentId, + [FromRoute] string conversationId, + IFormFile[] files) + { + if (files != null && files.Length > 0) + { + var attachmentService = _services.GetRequiredService(); + var dir = attachmentService.GetDirectory(conversationId); + foreach (var file in files) + { + // Save the file, process it, etc. + var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"'); + var filePath = Path.Combine(dir, fileName); + + using (var stream = new FileStream(filePath, FileMode.Create)) + { + file.CopyTo(stream); + } + } + + return Ok(new { message = "File uploaded successfully." }); + } + + return BadRequest(new { message = "Invalid file." }); + } }