diff --git a/Interfaces/IXFileContentExtractor.cs b/Interfaces/Extractors/IXFileContentExtractor.cs similarity index 94% rename from Interfaces/IXFileContentExtractor.cs rename to Interfaces/Extractors/IXFileContentExtractor.cs index 7349d11..4194aa3 100644 --- a/Interfaces/IXFileContentExtractor.cs +++ b/Interfaces/Extractors/IXFileContentExtractor.cs @@ -2,7 +2,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -namespace xAiApi.Interfaces +namespace xAiApi.Interfaces.Extractors { /// /// a Service for Extracting File Content ... diff --git a/Interfaces/Extractors/IXPdfFileContentExtractor.cs b/Interfaces/Extractors/IXPdfFileContentExtractor.cs new file mode 100644 index 0000000..ed74569 --- /dev/null +++ b/Interfaces/Extractors/IXPdfFileContentExtractor.cs @@ -0,0 +1,5 @@ +namespace xAiApi.Interfaces.Extractors +{ + public interface IXPdfFileContentExtractor : IXFileContentExtractor + { } +} \ No newline at end of file diff --git a/Interfaces/Extractors/IXPlainTextFileContentExtractor.cs b/Interfaces/Extractors/IXPlainTextFileContentExtractor.cs new file mode 100644 index 0000000..cace3a5 --- /dev/null +++ b/Interfaces/Extractors/IXPlainTextFileContentExtractor.cs @@ -0,0 +1,5 @@ +namespace xAiApi.Interfaces.Extractors +{ + public interface IXPlainTextFileContentExtractor : IXFileContentExtractor + { } +} \ No newline at end of file diff --git a/Providers/Extractors/XFileContentExtractor.cs b/Providers/Extractors/XFileContentExtractor.cs new file mode 100644 index 0000000..d56288a --- /dev/null +++ b/Providers/Extractors/XFileContentExtractor.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Reflection; +using xCommons.Extensions; +using xExceptions.Constants; +using System.Threading.Tasks; +using System.Collections.Generic; +using xAiApi.Interfaces.Extractors; + +namespace xAiApi.Providers +{ + /// + /// Composite extractor that delegates to appropriate extractor + /// based on MIME type ... + /// + public class XFileContentExtractor : IXFileContentExtractor + { + // + private readonly IList extractors = []; + + public XFileContentExtractor() + { + // + var path = Path.Combine(AppContext.BaseDirectory); + var files = Directory.GetFiles(path, "*.dll"); + foreach (var dll in files) + { + // + // Retrieve DLL Assembly ... + var assembly = Assembly.LoadFrom(dll); + + // + // Extract Registerar Types ... + var extractorTypes = assembly + .GetExportedTypes() + .Where(t => + !t.IsAbstract && + typeof(IXFileContentExtractor).IsAssignableFrom(t)); + foreach (var extractorType in extractorTypes) + { + // + // Ignore XFileContentExtractor ... + if (extractorType.FullName.Contains(nameof(XFileContentExtractor))) + { + continue; + } + + // + // Create Instance of Service ... + var instance = (IXFileContentExtractor)Activator.CreateInstance(extractorType); + if (!instance.IsNull()) + { + // + // Add Registerar Instance to Collection ... + extractors.Add(instance); + } + } + } + } + + /// + /// Check if this extractor supports the specified MIME type ... + /// + public bool CanExtract(string mimeType) + { + return extractors.Any(e => e.CanExtract(mimeType)); + } + + /// + /// Extract text content from file stream ... + /// + public async Task ExtractAsync( + Stream fileStream, + string mimeType, + CancellationToken cancellationToken = default + ) + { + // + var extractor = extractors + .FirstOrDefault(e => e.CanExtract(mimeType)); + if (extractor.IsNull()) + { + // + XException.NotAllowed.Throw( + $"Unsupported file type: {mimeType}" + ); + } + + // + var result = await extractor + .ExtractAsync( + mimeType: mimeType, + fileStream: fileStream, + cancellationToken: cancellationToken + ); + + // + return result; + } + } +} \ No newline at end of file diff --git a/Providers/XPdfContentExtractor.cs b/Providers/Extractors/XPdfFileContentExtractor.cs similarity index 94% rename from Providers/XPdfContentExtractor.cs rename to Providers/Extractors/XPdfFileContentExtractor.cs index 22afa57..14834d1 100644 --- a/Providers/XPdfContentExtractor.cs +++ b/Providers/Extractors/XPdfFileContentExtractor.cs @@ -4,15 +4,15 @@ using System.Linq; using System.Text; using UglyToad.PdfPig; using System.Threading; -using xAiApi.Interfaces; using System.Threading.Tasks; +using xAiApi.Interfaces.Extractors; namespace xAiApi.Providers { /// /// Extracts content from PDF files using PdfPig ... /// - public class XPdfContentExtractor : IXFileContentExtractor + public class XPdfFileContentExtractor : IXPdfFileContentExtractor { /// /// Supported MIME Types ... diff --git a/Providers/XPlainTextContentExtractor.cs b/Providers/Extractors/XPlainTextFileContentExtractor.cs similarity index 92% rename from Providers/XPlainTextContentExtractor.cs rename to Providers/Extractors/XPlainTextFileContentExtractor.cs index d704221..c087b32 100644 --- a/Providers/XPlainTextContentExtractor.cs +++ b/Providers/Extractors/XPlainTextFileContentExtractor.cs @@ -2,15 +2,15 @@ using System; using System.IO; using System.Linq; using System.Threading; -using xAiApi.Interfaces; using System.Threading.Tasks; +using xAiApi.Interfaces.Extractors; namespace xAiApi.Providers { /// /// Extracts content from plain text files (txt, md, csv, json, xml) ... /// - public class XPlainTextContentExtractor : IXFileContentExtractor + public class XPlainTextFileContentExtractor : IXPlainTextFileContentExtractor { /// /// Supported MIME Types ... diff --git a/Providers/XAIServiceBase.cs b/Providers/XAIServiceBase.cs index 06eb38b..63ad345 100644 --- a/Providers/XAIServiceBase.cs +++ b/Providers/XAIServiceBase.cs @@ -27,6 +27,7 @@ using Microsoft.Extensions.AI; using Microsoft.AspNetCore.Http; using System.Collections.Generic; using Microsoft.Extensions.Logging; +using xAiApi.Interfaces.Extractors; using System.ClientModel.Primitives; using System.Runtime.CompilerServices; @@ -52,6 +53,7 @@ namespace xAiApi.Providers private readonly ILogger logger; private readonly XAiApiConfiguration configuration; private readonly XValidationProvider validationProvider; + private readonly IXFileContentExtractor fileContentExtractor; protected XAIServiceBase( IXFileProvider fileProvider, @@ -59,6 +61,7 @@ namespace xAiApi.Providers ILogger logger, XAiApiConfiguration configuration, XValidationProvider validationProvider, + IXFileContentExtractor fileContentExtractor, string model = null ) { @@ -68,6 +71,7 @@ namespace xAiApi.Providers this.dataProvider = dataProvider; this.configuration = configuration; this.validationProvider = validationProvider; + this.fileContentExtractor = fileContentExtractor; // // Prepare Embedding Model Descriptor ... diff --git a/Providers/XAiEmbeddingServiceBase.cs b/Providers/XAiEmbeddingServiceBase.cs index cd96a26..02eabeb 100644 --- a/Providers/XAiEmbeddingServiceBase.cs +++ b/Providers/XAiEmbeddingServiceBase.cs @@ -20,7 +20,9 @@ using xFileService.Interfaces; using Microsoft.Extensions.AI; using System.Collections.Generic; using Microsoft.Extensions.Logging; +using xAiApi.Interfaces.Extractors; using System.ClientModel.Primitives; +using xCommons.Providers; namespace xAiApi.Providers { @@ -37,9 +39,19 @@ namespace xAiApi.Providers IXFileProvider fileProvider, IXAiDataProvider dataProvider, XAiApiConfiguration configuration, + XValidationProvider validationProvider, ILogger logger, + IXFileContentExtractor fileContentExtractor, string embeddingModelName = XAiApiConstants.XAiEmbeddingModelName - ) : base(fileProvider, dataProvider, logger, configuration, null) + ) : base( + fileProvider, + dataProvider, + logger, + configuration, + validationProvider, + fileContentExtractor, + null + ) { // // Prepare Embedding Model Descriptor ... diff --git a/Providers/XCompositeFileContentExtractor.cs b/Providers/XCompositeFileContentExtractor.cs deleted file mode 100644 index 4dc747f..0000000 --- a/Providers/XCompositeFileContentExtractor.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.IO; -using System.Linq; -using System.Threading; -using xAiApi.Interfaces; -using xCommons.Extensions; -using xExceptions.Constants; -using System.Threading.Tasks; -using System.Collections.Generic; - -namespace xAiApi.Providers -{ - /// - /// Composite extractor that delegates to appropriate extractor - /// based on MIME type ... - /// - public class XCompositeFileContentExtractor : IXFileContentExtractor - { - // - private readonly IEnumerable extractors; - - public XCompositeFileContentExtractor( - IEnumerable extractors - ) - { - this.extractors = extractors; - } - - /// - /// Check if this extractor supports the specified MIME type ... - /// - public bool CanExtract(string mimeType) - { - return extractors.Any(e => e.CanExtract(mimeType)); - } - - /// - /// Extract text content from file stream ... - /// - public async Task ExtractAsync( - Stream fileStream, - string mimeType, - CancellationToken cancellationToken = default - ) - { - // - var extractor = extractors - .FirstOrDefault(e => e.CanExtract(mimeType)); - if (extractor.IsNull()) - { - // - XException.NotAllowed.Throw( - $"Unsupported file type: {mimeType}" - ); - } - - // - var result = await extractor - .ExtractAsync( - mimeType: mimeType, - fileStream: fileStream, - cancellationToken: cancellationToken - ); - - // - return result; - } - } -} \ No newline at end of file diff --git a/Providers/XDefaultAiService.cs b/Providers/XDefaultAiService.cs index 7ae7a5e..dd84fc9 100644 --- a/Providers/XDefaultAiService.cs +++ b/Providers/XDefaultAiService.cs @@ -5,6 +5,7 @@ using xAiModels.Interfaces; using xAiApi.Configurations; using xFileService.Interfaces; using Microsoft.Extensions.Logging; +using xAiApi.Interfaces.Extractors; namespace xAiApi.Providers { @@ -15,13 +16,15 @@ namespace xAiApi.Providers IXAiDataProvider dataProvider, ILogger logger, XAiApiConfiguration configuration, - XValidationProvider validationProvider + XValidationProvider validationProvider, + IXFileContentExtractor fileContentExtractor ) : base( fileProvider, dataProvider, logger, configuration, validationProvider, + fileContentExtractor, XAiApiConstants.XAiDefaultModelName ) { } diff --git a/Providers/XDefaultEmbeddingService.cs b/Providers/XDefaultEmbeddingService.cs index 2ca0d70..dd5d2dc 100644 --- a/Providers/XDefaultEmbeddingService.cs +++ b/Providers/XDefaultEmbeddingService.cs @@ -4,6 +4,8 @@ using xAiModels.Interfaces; using xAiApi.Configurations; using xFileService.Interfaces; using Microsoft.Extensions.Logging; +using xAiApi.Interfaces.Extractors; +using xCommons.Providers; namespace xAiApi.Providers { @@ -11,14 +13,18 @@ namespace xAiApi.Providers { public XDefaultEmbeddingService( IXFileProvider fileProvider, - IXAiDataProvider dataProvider, - XAiApiConfiguration configuration, - ILogger logger + IXAiDataProvider dataProvider, + XAiApiConfiguration configuration, + XValidationProvider validationProvider, + ILogger logger, + IXFileContentExtractor fileContentExtractor ) : base( fileProvider, - dataProvider, - configuration, + dataProvider, + configuration, + validationProvider, logger, + fileContentExtractor, XAiApiConstants.XAiEmbeddingModelName ) { } diff --git a/Providers/XDefaultThinkingAiService.cs b/Providers/XDefaultThinkingAiService.cs index 6b83d04..30caada 100644 --- a/Providers/XDefaultThinkingAiService.cs +++ b/Providers/XDefaultThinkingAiService.cs @@ -6,6 +6,7 @@ using xAiApi.Configurations; using Microsoft.Extensions.AI; using xFileService.Interfaces; using Microsoft.Extensions.Logging; +using xAiApi.Interfaces.Extractors; namespace xAiApi.Providers { @@ -17,6 +18,7 @@ namespace xAiApi.Providers ILogger logger, XAiApiConfiguration configuration, XValidationProvider validationProvider, + IXFileContentExtractor fileContentExtractor, ReasoningEffort effort = ReasoningEffort.Medium, ReasoningOutput output = ReasoningOutput.Full ) : base( @@ -25,6 +27,7 @@ namespace xAiApi.Providers logger, configuration, validationProvider, + fileContentExtractor, XAiApiConstants.XAiDefaultThinkingModelName ) { diff --git a/Startup.cs b/Startup.cs index 5674408..598bda1 100644 --- a/Startup.cs +++ b/Startup.cs @@ -26,6 +26,7 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; +using xAiApi.Interfaces.Extractors; using Newtonsoft.Json.Serialization; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -187,9 +188,9 @@ namespace xAiApi // // Register File Content Extractors ... - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + // services.AddSingleton(); + // services.AddSingleton(); + services.AddSingleton(); // // Register Default Ai Service ...