
### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Program.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace xAiApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Startup.cs

using System;
using System.IO;
using System.Linq;
using xTagService.DI;
using System.Net.Http;
using xAiApi.Database;
using xHttpService.DI;
using xPushService.DI;
using xFileService.DI;
using xDataService.DI;
using Newtonsoft.Json;
using System.Reflection;
using xAiApi.Extensions;
using xStringService.DI;
using xStorageService.DI;
using xIdentityService.DI;
using xDataService.Models;
using xCommons.Extensions;
using xCommons.Configurations;
using System.Collections.Generic;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using IdentityModel.AspNetCore.OAuth2Introspection;
using xPushService.Helpers;
using xAiApi.DI;
using xAiApi.Interfaces;
using xAiApi.Providers;
using xAiModels.DI;

namespace xAiApi
{
    public class Startup
    {
        //
        #region Props ...
        public IConfiguration Configuration { get; }
        private readonly List<XDatabaseDescriptor> databases;
        private readonly XAiApiDatabaseDescriptor apiDatabaseDescriptor;
        #endregion

        //
        #region Constructor(s) ...
        public Startup(IConfiguration configuration)
        {
            //
            Configuration = configuration;

            //
            // Create an Api Descriptor Class Instance ...
            apiDatabaseDescriptor = new XAiApiDatabaseDescriptor();
            databases = new List<XDatabaseDescriptor>
            {
                apiDatabaseDescriptor
            };
        }
        #endregion

        public void ConfigureServices(IServiceCollection services)
        {
            //
            // Register Validation Provider and all XCommons Module Services ...
            services.AddXCommons();

            //
            // Register App Configuration ...
            services.AddXAppConfiguration(Configuration);
            var appConfiguration = services.GetRegisteredService<XAppConfiguration>();

            //
            // Register Allowed Origins ...
            services.AddXCors(appConfiguration.AllowedOrigins);

            //
            // Register Swagger ...
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            services.AddXSwagger(Configuration, xmlFilePath: xmlPath);

            //
            // Register HttpService ...
            services.AddXHttpService(Configuration);

            //
            // Add Api V1 Versioning ...
            services.AddXApiV1Versioning();

            //
            // OAuthIntrospectin Http Client Handler ...
            // this is for handling SSLErrors ...
            services.AddHttpClient(OAuth2IntrospectionDefaults.BackChannelHttpClientName)
                .ConfigurePrimaryHttpMessageHandler(() =>
                {
                    return new HttpClientHandler
                    {
                        ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
                    };
                });

            //
            // Register Authorizations ...
            services.AddXAuthorization();

            //
            services.AddControllers()
                .AddNewtonsoftJson(x =>
                {
                    x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                    x.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                });

            //
            var lifeTime = ServiceLifetime.Scoped;
            var repositoryType = xDataService.Constants.XRepositoryType.EF;

            //
            // Register XIdentity Service ...
            services.AddXIdentityService(
                lifeTime: lifeTime,
                configuration: Configuration
            );

            //
            // Storage Service ...
            services.AddXStorageService(Configuration);

            //
            // Push Service ...
            services.AddXPushService(
                lifeTime: lifeTime,
                config: Configuration
            );

            //
            // Preparing DataBases ...
            if (databases.HasChild())
            {
                //
                databases
                    .ToList()
                    .ForEach(database =>
                    {
                        //
                        // Register DataBase ...
                        services.AddXDatabase(
                            lifeTime: lifeTime,
                            descriptor: database,
                            configuration: Configuration
                        );
                    });
            }

            //
            // Register String Service ...
            services.AddXStringService<XAiApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register Tag Service ...
            services.AddXTagService<XAiApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register File Service ...
            services.AddXFileService<XAiApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register AiApi Data Service ...
            services.AddXAiDataService<XAiApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register XAiApi Configuration ...
            services.AddXAiApiConfiguration(Configuration);

            //
            // Register Default Ai Service ...
            services.AddScoped<IXDefaultAiService, XDefaultAiService>();
            services.AddScoped<IXDefaultEmbeddingService, XDefaultEmbeddingService>();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //
            // Configure the HTTP request pipeline.
            var isDevelopmentEnvironment = false;
            if (env.IsDevelopment())
            {
                isDevelopmentEnvironment = true;
                app.UseDeveloperExceptionPage();
            }

            //
            // Use Swagger Middleware ...
            app.UseXSwagger();

            //
            // Force Https Redirection ...
            app.UseHttpsRedirection();

            //
            // Using Cors ...
            app.UseXCors();

            //
            // Using Routing ...
            app.UseRouting();

            //
            // Use xIdentityService ...
            app.UseXIdentityService();

            //
            // Use Authorization ...
            app.UseAuthorization();

            //
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            //
            // Use Storage Service ...
            app.UseXStorageService();

            //
            // Use PushService ...
            var pushHelper = new XPushServiceHelper();
            app.UseXPushService(pushHelper);

            //
            // Using DataBase ...
            if (databases.HasChild())
            {
                //
                databases
                    .ToList()
                    .ForEach(database =>
                    {
                        //
                        app.UseXDatabase(
                            descriptor: database,
                            isDevelopmentEnvironment: isDevelopmentEnvironment
                        );
                    });
            }

            //
            // Using String Service ...
            app.UseXStringService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );

            //
            // Using XTag Service ...
            app.UseXTagService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );

            //
            // Using File Service ...
            app.UseXFileService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Configurations\XAiApiConfiguration.cs

using xAiApi.Models;

namespace xAiApi.Configurations
{
    public class XAiApiConfiguration
    {
        /// <summary>
        /// Allowed Models to Use ...
        /// </summary>
        public XAiModelDescriptor[] Models { get; set; } = [];

        /// <summary>
        /// Allowed Prompts to Use ...
        /// </summary>
        public XAiPromptDescriptor[] Prompts { get; set; } = [];
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Constants\ConfigurationNodeNames.cs

namespace xAiApi.Constants
{
    public partial struct ConfigurationNodeNames
    {
        public const string AI_API_NODE = "AiAPiConfiguration";
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Constants\XAiApiConstants.cs

namespace xAiApi.Constants
{
    public struct XAiApiConstants
    {
        //
        // Database Descriptor ...
        public const string XAiApiDbIdentifier = "xAiApiDb";
        public const string XAiApiMigrationsAssemblyIdentifier = "xAiApi";

        //
        public const string XDILogTag = "XAiApi";
        public const string XAiApiIntroductionPromptName = "Introduction";

        //
        public const string XAiEmbeddingModelName = "Embed";
        public const string XAiEmbeddingPromptName = "Embedding";
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Constants\XAiProvider.cs

namespace xAiApi.Constants
{
    public enum XAiProvider
    {
        None,
        Ollama,
        DeepSeek,
        HuggingFace        
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Controllers\DefaultAiController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xAiApi.Interfaces;
using xCommons.Configurations;
using xCommons.Providers;

namespace xAiApi.Controllers
{
    [Authorize]
    [Route ("[controller]")]
    public class DefaultAiController : XAiServiceControllerBase<IXDefaultAiService>
    {
        public DefaultAiController(
            ILogger<DefaultAiController> logger,
            IXDefaultAiService aiService,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider
        ) : base(
            logger,
            aiService,
            appConfiguration,
            validationProvider
        )
        { }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Controllers\DefaultEmbeddingController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xAiApi.Interfaces;
using xCommons.Configurations;
using xCommons.Providers;

namespace xAiApi.Controllers
{
    [Authorize]
    [Route("[controller]")]
    public class DefaultEmbeddingController : XAiEmbeddingServiceControllerBase<IXDefaultEmbeddingService>
    {
        public DefaultEmbeddingController(
            ILogger<DefaultEmbeddingController> logger,
            IXDefaultEmbeddingService aiService,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider
        ) : base(
            logger,
            aiService,
            appConfiguration,
            validationProvider
        )
        { }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Controllers\StartupController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Controllers;
using xCommons.Providers;

namespace xAiApi.Controllers
{
    /// <summary>
    /// Runing when application start ...
    /// </summary>
    [Route("")]
    [AllowAnonymous]
    public class StartupController : XBaseController
    {

        public StartupController(
            ILogger<StartupController> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        { }

        /// <summary>
        /// Show Configured Welcome Message 
        /// </summary>
        /// <returns></returns>
        [HttpGet("")]
        [AllowAnonymous]
        public virtual ActionResult<string> Index()
        {
            //
            var controllerName = GetControllerName();
            var message = $"{AppConfiguration.WelcomeMessage}";

            //
            return Ok(message);
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Controllers\XAiEmbeddingServiceControllerBase.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xAiApi.Interfaces;
using xCommons.Configurations;
using xCommons.Providers;

namespace xAiApi.Controllers
{
    [Authorize]
    [Route("[controller]")]
    public abstract class XAiEmbeddingServiceControllerBase<TAiService> : XAiServiceControllerBase<TAiService>, IXAiEmbeddingServiceControllerBase
    where TAiService : IXAiEmbeddingServiceBase
    {
        private readonly TAiService aiService;

        protected XAiEmbeddingServiceControllerBase(
            ILogger logger, 
            TAiService aiService,
            XAppConfiguration appConfiguration, 
            XValidationProvider validationProvider
        ) : base(
            logger, 
            aiService,
            appConfiguration, 
            validationProvider
        )
        {
            this.aiService = aiService;
        }

        /// <summary>
        /// Request For Embedding Specified String ...
        /// </summary>
        /// <param name="content"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("Embeding")]
        public async Task<ActionResult<float[]>> Embeding(
            [FromQuery] string content, 
            CancellationToken cancellationToken = default    
        )
        {
            //
            try
            {
                //
                // Validate ...
                ValidationProvider.NotEmpty(content);

                //
                var result = await aiService.Embeding(
                    content: content,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Request For Embedding Specified Batch ...
        /// </summary>
        /// <param name="batch"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("Embedings")]
        public async Task<ActionResult<IReadOnlyList<float[]>>> Embedings(
            [FromQuery] string[] batch, 
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                ValidationProvider.NotZeroChilds(batch);

                //
                var result = await aiService.Embedings(
                    batch: batch,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Controllers\XAiServiceControllerBase.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xAiApi.Interfaces;
using xCommons.Configurations;
using xCommons.Controllers;
using xCommons.Providers;

namespace xAiApi.Controllers
{
    [Authorize]
    [Route ("[controller]")]
    public abstract class XAiServiceControllerBase<TAiService> : XBaseController, IXAiServiceControllerBase
    where TAiService : IXAiServiceBase
    {
        private readonly TAiService aiService;

        protected XAiServiceControllerBase(
            ILogger logger,
            TAiService aiService,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        {
            this.aiService = aiService;
        }

        /// <summary>
        /// Ask Question and Get Response ...
        /// </summary>
        /// <param name="question"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("Ask")]
        public virtual async Task<ActionResult<string>> Ask(
            [FromQuery] string question,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                ValidationProvider.NotEmpty(question);

                //
                var result = await aiService.AskAsync(
                    prompt: question,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Database\XAiApiDatabaseDescriptor.cs

using xAiApi.Constants;
using xDataService.Interfaces;
using xDataService.Models;

namespace xAiApi.Database
{
    /// <summary>
    /// Ai Api Database Descriptor ... 
    /// </summary>
    public class XAiApiDatabaseDescriptor : XDatabaseDescriptor<XAiApiDbContext>, IXDatabaseDescriptor<XAiApiDbContext>
    {
        public XAiApiDatabaseDescriptor() : base(
            name: XAiApiConstants.XAiApiDbIdentifier,
            repositories: []
        )
        {
            OptionsBuilder = b => b.MigrationsAssembly(XAiApiConstants.XAiApiMigrationsAssemblyIdentifier);
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Database\XAiApiDbContext.cs

using Microsoft.EntityFrameworkCore;
using xAiApi.Constants;
using xAiModels.Providers;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Providers;
using xFileService.Providers;
using xStringService.Providers;
using xTagService.Providers;

namespace xAiApi.Database
{
    /// <summary>
    /// Db Context of AiApi ...
    /// </summary>
    public class XAiApiDbContext : XDbContext
    {
        //
        #region DbSets ...
        #endregion

        //
        #region Navigation Property Entities ...
        #endregion

        //
        #region Constructor ...
        public XAiApiDbContext(
            DbContextOptions options,
            XDataServiceConfiguration config,
            XEntityRegisterarHandlerService dynamicEntityHandlers
        ) : base(
            config: config,
            options: options,
            database: XAiApiConstants.XAiApiDbIdentifier,
            dynamicEntityHandlers: dynamicEntityHandlers,
            dynamicEntityRegisterarsNames: [
                nameof(XTagEntityRegisterar),
                nameof(XFileEntityRegisterar),
                nameof(XStringEntityRegisterar),
                nameof(XAiMessageEntityRegisterar),
                nameof(XAiProjectEntityRegisterar),
                nameof(XAiConversationEntityRegisterar),
            ]
        )
        { }
        #endregion

        //
        #region Overrides ...
        //
        public override void OnXModelCreating(ModelBuilder modelBuilder)
        { }

        //
        public override void OnXConfiguring(DbContextOptionsBuilder optionsBuilder)
        { }
        #endregion
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\DI\XDIHelperExtension.cs

using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xAiApi.Configurations;
using xAiApi.Constants;
using xAiApi.Extensions;
using xCommons.Extensions;
using xExceptions.Constants;

namespace xAiApi.DI
{
    public static partial class XDIHelperExtension
    {
        /// <summary>
        /// Extract AI Configuration ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XAiApiConfiguration GetXAiApiConfiguration(this IConfiguration source)
        {
            //
            XAiApiConfiguration result = null;

            //
            var section = source.GetSection(ConfigurationNodeNames.AI_API_NODE);
            if (!section.IsNull())
            {
                result = section.Get<XAiApiConfiguration>();
            }

            //
            return result;
        }

        /// <summary>
        /// Register AiApi Configuration ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        public static void AddXAiApiConfiguration(
            this IServiceCollection source,
            IConfiguration configuration
        )
        {
            //
            var apiConfig = configuration.GetXAiApiConfiguration();
            source.AddXAiApiConfiguration(apiConfig);
        }

        /// <summary>
        /// Register AiApi Configuration ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        public static void AddXAiApiConfiguration(
            this IServiceCollection source,
            XAiApiConfiguration configuration
        )
        {
            //
            if (!configuration.IsValid())
            {
                XException.InvalidConfiguration.Throw();
            }

            //
            source.AddSingleton(configuration);
        }

        //
        #region Private ...
        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XAiApiConstants.XDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }
        #endregion
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Extensions\XModelsExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xAiApi.Configurations;
using xAiApi.Constants;
using xAiApi.Models;
using xCommons.Extensions;

namespace xAiApi.Extensions
{
    public static class XModelsExtensions
    {
        /// <summary>
        /// Validate a Model Descriptor ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XAiModelDescriptor source)
        {
            //
            var result =
                !source.IsNullOrDefault() &&
                !source.Name.IsNullOrEmpty() &&
                !source.Url.IsNullOrEmpty() &&
                source.Url.IsValidUrl() &&
                !source.LLM.IsNullOrEmpty() &&
                source.Provider != Constants.XAiProvider.None;

            //
            return result;
        }

        /// <summary>
        /// Validate Configurations ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XAiApiConfiguration source)
        {
            //
            var result =
                !source.IsNullOrDefault() &&
                source.Models.HasChild() &&
                source.Models.All(m => m.IsValid()) &&
                source.Prompts.All(m => m.IsValid()) &&
                source.Prompts.Any(p => p.Name
                    .Equals(
                        XAiApiConstants.XAiApiIntroductionPromptName,
                        System.StringComparison.InvariantCultureIgnoreCase));

            //
            return result;
        }

        /// <summary>
        /// Validate Specified Param ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XAiPromptParam source)
        {
            //
            var result =
                !source.IsNullOrDefault() &&
                !source.Name.IsNullOrEmpty() &&
                !source.Param.IsNullOrEmpty();

            //
            return result;
        }

        /// <summary>
        /// Validate Specified Prompt ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XAiPromptDescriptor source)
        {
            //
            var result =
                !source.IsNullOrDefault() &&
                !source.Name.IsNullOrEmpty() &&
                !source.Template.IsNullOrEmpty();
            if (!result)
            {
                return result;
            }

            //
            if (source.Params.HasChild())
            {
                result =
                    result &&
                    source.Params.All(x => x.IsValid());
            }

            //
            return result;
        }

        /// <summary>
        /// Extract Default Model Descriptor ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XAiModelDescriptor GetDefaultModel(this XAiApiConfiguration source)
        {
            //
            XAiModelDescriptor result = null;

            //
            if (source.IsValid())
            {
                result = source.Models[0];
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Specified Model from Config ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static XAiModelDescriptor GetModel(
            this XAiApiConfiguration source,
            string name
        )
        {
            //
            XAiModelDescriptor result = null;

            //
            if (source.IsValid())
            {
                //
                if (name.IsNullOrEmpty())
                {
                    result = source.GetDefaultModel();
                }
                else
                {
                    result = source.Models
                        .FirstOrDefault(m => m.Name
                            .Equals(name, System.StringComparison.InvariantCultureIgnoreCase));
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Introduction Prompt ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XAiPromptDescriptor GetIntroductionPrompt(this XAiApiConfiguration source)
        {
            //
            XAiPromptDescriptor result = null;

            //
            if (source.IsValid())
            {
                //
                result = source.Prompts
                    .FirstOrDefault(p => p.Name
                        .Equals(
                            XAiApiConstants.XAiApiIntroductionPromptName,
                            System.StringComparison.InvariantCultureIgnoreCase));
            }

            //
            return result;
        }

        /// <summary>
        /// Select Specified Prompts and Parse it's Template
        /// and Generate Message ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="name"></param>
        /// <param name="params"></param>
        /// <returns></returns>
        public static string GetPrompt(
            this XAiApiConfiguration source,
            string name = null,
            IDictionary<string, string> @params = null
        )
        {
            //
            var result = string.Empty;

            //
            // Normalize ...
            if (name.IsNullOrEmpty())
            {
                name = XAiApiConstants.XAiApiIntroductionPromptName;
            }

            //
            if (source.IsValid())
            {
                //
                var prompt = source.Prompts
                    .FirstOrDefault(p => p.Name
                        .Equals(
                            name,
                            System.StringComparison.InvariantCultureIgnoreCase
                        )
                    );
                if (!prompt.IsNullOrDefault())
                {
                    //
                    result = prompt.Template;

                    //
                    // Handle Params ...
                    if (!@params.IsNullOrDefault() && @params.HasChild())
                    {
                        //
                        // Select Params ...
                        var existsParams = prompt.Params
                            .Where(p => @params.Any(pr => pr.Key == p.Name))
                            .Distinct()
                            .ToList();

                        //
                        // Replace Selected Params ...
                        existsParams
                            .ForEach(pk =>
                            {
                                result = result.Replace(pk.Param, @params[pk.Name]);
                            });
                    }
                }
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Extensions\XProgramExtensions.cs

using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Authorization;
using xCommons.Extensions;
using xIdentityHelper;

namespace xAiApi.Extensions
{
    public static class XProgramExtensions
    {
        /// <summary>
        /// Register Authorization Policies
        /// </summary>
        /// <param name="services"></param>
        /// <param name="policies"></param>
        public static void AddXAuthorization(
            this IServiceCollection services,
            IDictionary<string, AuthorizationPolicy> policies = null
        )
        {
            //
            services.AddAuthorization(options =>
            {
                //
                if (!policies.IsNull())
                {
                    //
                    // Fill Policies ...
                    using (var policiesEnumerator = policies.GetEnumerator())
                    {
                        while (policiesEnumerator.MoveNext())
                        {
                            var policyDescriptor = policiesEnumerator.Current;
                            options.AddPolicy(policyDescriptor.Key, policyDescriptor.Value);
                        }
                    }
                }

                //
                var xPolicies = XAuthorizationHelper.GetXAuthorizationPolicies();
                if (!xPolicies.IsNull())
                {
                    //
                    // Fill Policies ...
                    using (var policiesEnumerator = xPolicies.GetEnumerator())
                    {
                        while (policiesEnumerator.MoveNext())
                        {
                            var policyDescriptor = policiesEnumerator.Current;
                            options.AddPolicy(policyDescriptor.Key, policyDescriptor.Value);
                        }
                    }
                }
            });

            //
            services.AddSingleton<IAuthorizationHandler, RequiredRolesHandler>();
        }

        /// <summary>
        /// Use Forward Headers Options for resolving behind a proxy issues ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static void UseXForwardOptions(this IApplicationBuilder source)
        {
            //
            var forwardOptions = new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
                RequireHeaderSymmetry = false
            };

            //
            forwardOptions.KnownNetworks.Clear();
            forwardOptions.KnownProxies.Clear();

            //
            // ref: https://github.com/aspnet/Docs/issues/2384
            source.UseForwardedHeaders(forwardOptions);
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Interfaces\IXAiEmbeddingServiceBase.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using OllamaSharp;

namespace xAiApi.Interfaces
{
    /// <summary>
    /// Base Embedding Provider Service ...
    /// </summary>
    public interface IXAiEmbeddingServiceBase : IXAiServiceBase
    {
        /// <summary>
        /// Embedding Specified String ...
        /// </summary>
        /// <param name="content"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<float[]> Embeding(
            string content,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Embedding Specified Batch ...
        /// </summary>
        /// <param name="batch"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IReadOnlyList<float[]>> Embedings(
            string[] batch,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Access Embedding Client ...
        /// </summary>
        /// <returns></returns>
        OllamaApiClient GetEmbeddingClient();
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Interfaces\IXAiEmbeddingServiceControllerBase.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace xAiApi.Interfaces
{
    public interface IXAiEmbeddingServiceControllerBase : IXAiServiceControllerBase
    {
        /// <summary>
        /// Request For Embedding Specified String ...
        /// </summary>
        /// <param name="content"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Embeding")]
        Task<ActionResult<float[]>> Embeding(
            [FromQuery] string content,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Request For Embedding Specified Batch ...
        /// </summary>
        /// <param name="batch"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Embedings")]
        Task<ActionResult<IReadOnlyList<float[]>>> Embedings(
            [FromQuery] string[] batch,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Interfaces\IXAiServiceBase.cs

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;

namespace xAiApi.Interfaces
{
    /// <summary>
    /// Describe a Base Service Actions of any Ai Based Services ...
    /// </summary>
    public interface IXAiServiceBase : IDisposable
    {
        /// <summary>
        /// Base Method for Communicate with LLM ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<string> AskAsync(
            string prompt,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Base Method for Communicate with LLM ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        IAsyncEnumerable<string> AskAsEnumerable(
            string prompt,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get LLM Client instance for Communicating with LLM ...
        /// </summary>
        /// <param name="llm"></param>
        /// <returns></returns>
        IChatClient GetClient(string llm = null);

        /// <summary>
        /// Create Custom HttpClient for Communicating with LLM API ...
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        HttpClient GetHttpClient(string url = null);

        /// <summary>
        /// Prepare a Message History List for LLM Communication based on Prompt ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="forcePrompt"></param>
        /// <returns></returns>
        IList<ChatMessage> GetHistory(
            string prompt = null,
            bool forcePrompt = true
        );

        /// <summary>
        /// Prepare a Message History List for LLM Communication based on Prompt ...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="forceMessage"></param>
        /// <returns></returns>
        IList<ChatMessage> GetHistory(
            ChatMessage message = null,
            bool forceMessage = true
        );
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Interfaces\IXAiServiceControllerBase.cs

using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace xAiApi.Interfaces
{
    public interface IXAiServiceControllerBase
    {
        /// <summary>
        /// Ask Question and Get Response ...
        /// </summary>
        /// <param name="question"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Ask")]
        Task<ActionResult<string>> Ask(
            [FromQuery] string question,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Interfaces\IXDefaultAiService.cs

namespace xAiApi.Interfaces
{
    public interface IXDefaultAiService : IXAiServiceBase
    { }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Interfaces\IXDefaultEmbeddingService.cs

namespace xAiApi.Interfaces
{
    public interface IXDefaultEmbeddingService : IXAiEmbeddingServiceBase
    { }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Migrations\20260906032616_InitialMigrationAiApi.cs

using System;
using Microsoft.EntityFrameworkCore.Migrations;

namespace xAiApi.Migrations
{
    public partial class InitialMigrationAiApi : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "AiConversations",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Deleted = table.Column<bool>(nullable: false),
                    OwnerId = table.Column<string>(maxLength: 255, nullable: false),
                    Title = table.Column<string>(maxLength: 255, nullable: false),
                    CreatedOn = table.Column<DateTime>(nullable: false),
                    UpdatedAt = table.Column<DateTime>(nullable: false),
                    ProjectId = table.Column<Guid>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AiConversations", x => x.Id);
                });

            migrationBuilder.CreateTable(
                name: "AiMessages",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Deleted = table.Column<bool>(nullable: false),
                    OwnerId = table.Column<string>(maxLength: 255, nullable: false),
                    Content = table.Column<string>(nullable: false),
                    Role = table.Column<int>(nullable: false),
                    CreatedOn = table.Column<DateTime>(nullable: false),
                    UpdatedAt = table.Column<DateTime>(nullable: false),
                    ConversationId = table.Column<Guid>(maxLength: 255, nullable: false),
                    MeatDatas = table.Column<string>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AiMessages", x => x.Id);
                });

            migrationBuilder.CreateTable(
                name: "AiProjects",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Deleted = table.Column<bool>(nullable: false),
                    OwnerId = table.Column<string>(maxLength: 255, nullable: false),
                    Title = table.Column<string>(maxLength: 255, nullable: false),
                    Description = table.Column<string>(maxLength: 1000, nullable: true),
                    Prompt = table.Column<string>(nullable: true),
                    CreatedOn = table.Column<DateTime>(nullable: false),
                    UpdatedAt = table.Column<DateTime>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_AiProjects", x => x.Id);
                });

            migrationBuilder.CreateTable(
                name: "Files",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Deleted = table.Column<bool>(nullable: false),
                    Type = table.Column<int>(nullable: false),
                    OwnerId = table.Column<string>(maxLength: 255, nullable: false),
                    Name = table.Column<string>(maxLength: 255, nullable: false),
                    Path = table.Column<string>(nullable: false),
                    Thumb = table.Column<string>(nullable: true),
                    ThumbPath = table.Column<string>(nullable: true),
                    UploadedOn = table.Column<DateTime>(nullable: false),
                    FileName = table.Column<string>(nullable: true),
                    References = table.Column<string>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Files", x => x.Id);
                });

            migrationBuilder.CreateTable(
                name: "Strings",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("Sqlite:Autoincrement", true),
                    Deleted = table.Column<bool>(nullable: false),
                    Language = table.Column<string>(maxLength: 10, nullable: false),
                    ResourceTitle = table.Column<string>(maxLength: 255, nullable: false),
                    TranslatedValue = table.Column<string>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Strings", x => x.Id);
                });

            migrationBuilder.CreateTable(
                name: "Tags",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("Sqlite:Autoincrement", true),
                    Deleted = table.Column<bool>(nullable: false),
                    Tag = table.Column<string>(maxLength: 255, nullable: false),
                    References = table.Column<string>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Tags", x => x.Id);
                });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "AiConversations");

            migrationBuilder.DropTable(
                name: "AiMessages");

            migrationBuilder.DropTable(
                name: "AiProjects");

            migrationBuilder.DropTable(
                name: "Files");

            migrationBuilder.DropTable(
                name: "Strings");

            migrationBuilder.DropTable(
                name: "Tags");
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Migrations\20260906032616_InitialMigrationAiApi.Designer.cs

// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using xAiApi.Database;

namespace xAiApi.Migrations
{
    [DbContext(typeof(XAiApiDbContext))]
    [Migration("20260906032616_InitialMigrationAiApi")]
    partial class InitialMigrationAiApi
    {
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "3.1.14");

            modelBuilder.Entity("xAiModels.Models.Entities.XAiConversation", b =>
                {
                    b.Property<Guid>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("TEXT");

                    b.Property<DateTime>("CreatedOn")
                        .HasColumnType("TEXT");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("OwnerId")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<Guid>("ProjectId")
                        .HasColumnType("TEXT");

                    b.Property<string>("Title")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<DateTime>("UpdatedAt")
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("AiConversations");
                });

            modelBuilder.Entity("xAiModels.Models.Entities.XAiMessage", b =>
                {
                    b.Property<Guid>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("TEXT");

                    b.Property<string>("Content")
                        .IsRequired()
                        .HasColumnType("TEXT");

                    b.Property<Guid>("ConversationId")
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<DateTime>("CreatedOn")
                        .HasColumnType("TEXT");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("MeatDatas")
                        .HasColumnType("TEXT");

                    b.Property<string>("OwnerId")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<int>("Role")
                        .HasColumnType("INTEGER");

                    b.Property<DateTime>("UpdatedAt")
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("AiMessages");
                });

            modelBuilder.Entity("xAiModels.Models.Entities.XAiProject", b =>
                {
                    b.Property<Guid>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("TEXT");

                    b.Property<DateTime>("CreatedOn")
                        .HasColumnType("TEXT");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("Description")
                        .HasColumnType("TEXT")
                        .HasMaxLength(1000);

                    b.Property<string>("OwnerId")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<string>("Prompt")
                        .HasColumnType("TEXT");

                    b.Property<string>("Title")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<DateTime>("UpdatedAt")
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("AiProjects");
                });

            modelBuilder.Entity("xFileService.Models.Entities.XFile", b =>
                {
                    b.Property<Guid>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("TEXT");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("FileName")
                        .HasColumnType("TEXT");

                    b.Property<string>("Name")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<string>("OwnerId")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<string>("Path")
                        .IsRequired()
                        .HasColumnType("TEXT");

                    b.Property<string>("References")
                        .HasColumnType("TEXT");

                    b.Property<string>("Thumb")
                        .HasColumnType("TEXT");

                    b.Property<string>("ThumbPath")
                        .HasColumnType("TEXT");

                    b.Property<int>("Type")
                        .HasColumnType("INTEGER");

                    b.Property<DateTime>("UploadedOn")
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("Files");
                });

            modelBuilder.Entity("xStringService.Models.Entities.XString", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("INTEGER");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("Language")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(10);

                    b.Property<string>("ResourceTitle")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<string>("TranslatedValue")
                        .IsRequired()
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("Strings");
                });

            modelBuilder.Entity("xTagService.Models.Entities.XTag", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("INTEGER");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("References")
                        .HasColumnType("TEXT");

                    b.Property<string>("Tag")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.HasKey("Id");

                    b.ToTable("Tags");
                });
#pragma warning restore 612, 618
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Migrations\XAiApiDbContextModelSnapshot.cs

// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using xAiApi.Database;

namespace xAiApi.Migrations
{
    [DbContext(typeof(XAiApiDbContext))]
    partial class XAiApiDbContextModelSnapshot : ModelSnapshot
    {
        protected override void BuildModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "3.1.14");

            modelBuilder.Entity("xAiModels.Models.Entities.XAiConversation", b =>
                {
                    b.Property<Guid>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("TEXT");

                    b.Property<DateTime>("CreatedOn")
                        .HasColumnType("TEXT");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("OwnerId")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<Guid>("ProjectId")
                        .HasColumnType("TEXT");

                    b.Property<string>("Title")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<DateTime>("UpdatedAt")
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("AiConversations");
                });

            modelBuilder.Entity("xAiModels.Models.Entities.XAiMessage", b =>
                {
                    b.Property<Guid>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("TEXT");

                    b.Property<string>("Content")
                        .IsRequired()
                        .HasColumnType("TEXT");

                    b.Property<Guid>("ConversationId")
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<DateTime>("CreatedOn")
                        .HasColumnType("TEXT");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("MeatDatas")
                        .HasColumnType("TEXT");

                    b.Property<string>("OwnerId")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<int>("Role")
                        .HasColumnType("INTEGER");

                    b.Property<DateTime>("UpdatedAt")
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("AiMessages");
                });

            modelBuilder.Entity("xAiModels.Models.Entities.XAiProject", b =>
                {
                    b.Property<Guid>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("TEXT");

                    b.Property<DateTime>("CreatedOn")
                        .HasColumnType("TEXT");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("Description")
                        .HasColumnType("TEXT")
                        .HasMaxLength(1000);

                    b.Property<string>("OwnerId")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<string>("Prompt")
                        .HasColumnType("TEXT");

                    b.Property<string>("Title")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<DateTime>("UpdatedAt")
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("AiProjects");
                });

            modelBuilder.Entity("xFileService.Models.Entities.XFile", b =>
                {
                    b.Property<Guid>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("TEXT");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("FileName")
                        .HasColumnType("TEXT");

                    b.Property<string>("Name")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<string>("OwnerId")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<string>("Path")
                        .IsRequired()
                        .HasColumnType("TEXT");

                    b.Property<string>("References")
                        .HasColumnType("TEXT");

                    b.Property<string>("Thumb")
                        .HasColumnType("TEXT");

                    b.Property<string>("ThumbPath")
                        .HasColumnType("TEXT");

                    b.Property<int>("Type")
                        .HasColumnType("INTEGER");

                    b.Property<DateTime>("UploadedOn")
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("Files");
                });

            modelBuilder.Entity("xStringService.Models.Entities.XString", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("INTEGER");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("Language")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(10);

                    b.Property<string>("ResourceTitle")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.Property<string>("TranslatedValue")
                        .IsRequired()
                        .HasColumnType("TEXT");

                    b.HasKey("Id");

                    b.ToTable("Strings");
                });

            modelBuilder.Entity("xTagService.Models.Entities.XTag", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("INTEGER");

                    b.Property<bool>("Deleted")
                        .HasColumnType("INTEGER");

                    b.Property<string>("References")
                        .HasColumnType("TEXT");

                    b.Property<string>("Tag")
                        .IsRequired()
                        .HasColumnType("TEXT")
                        .HasMaxLength(255);

                    b.HasKey("Id");

                    b.ToTable("Tags");
                });
#pragma warning restore 612, 618
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Models\XAiModelDescriptor.cs

using xAiApi.Constants;

namespace xAiApi.Models
{
    /// <summary>
    /// Describe an Ai Model ...
    /// </summary>
    public class XAiModelDescriptor
    {
        /// <summary>
        /// Provider Name ...
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// LLM Provider Url ...
        /// </summary>
        public string Url { get; set; }

        /// <summary>
        /// Model Name ...
        /// </summary>
        public string LLM { get; set; }

        /// <summary>
        /// Api Key for Connection ...
        /// </summary>
        public string ApiKey { get; set; } = null;

        /// <summary>
        /// Model Provider ...
        /// </summary>
        public XAiProvider Provider { get; set; } = XAiProvider.Ollama;
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Models\XAiPromptDescriptor.cs

namespace xAiApi.Models
{
    /// <summary>
    /// Describe Specified Prompt ...
    /// </summary>
    public class XAiPromptDescriptor
    {
        /// <summary>
        /// Prompt Name ...
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Prompt Template ... 
        /// </summary>
        public string Template { get; set; }

        /// <summary>
        /// Prompt Description ...
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Prompt Template Params ...
        /// </summary>
        public XAiPromptParam[] Params { get; set; } = [];
    }

    /// <summary>
    /// Specified a Prompt Param ...
    /// </summary>
    public class XAiPromptParam
    {
        /// <summary>
        /// Param Name ...
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Param Identifier ...
        /// </summary>
        public string Param { get; set; }

        /// <summary>
        /// Parma Description ...
        /// </summary>
        public string Description { get; set; }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Providers\XAiEmbeddingServiceBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OllamaSharp;
using OllamaSharp.Models;
using xAiApi.Configurations;
using xAiApi.Constants;
using xAiApi.Extensions;
using xAiApi.Interfaces;
using xAiApi.Models;
using xAiModels.Interfaces;
using xAiService.Helpers;
using xCommons.Extensions;
using xExceptions.Constants;

namespace xAiApi.Providers
{
    /// <summary>
    /// Base Embedding Provider Service ...
    /// </summary>
    public abstract class XAiEmbeddingServiceBase : XAIServiceBase, IXAiEmbeddingServiceBase
    {
        private readonly XAiModelDescriptor descriptor;

        protected XAiEmbeddingServiceBase(
            IXAiDataProvider dataProvider,
            XAiApiConfiguration configuration,
            ILogger<XAiEmbeddingServiceBase> logger,
            string embeddingModelName = XAiApiConstants.XAiEmbeddingModelName
        ) : base(
            dataProvider,
            logger,
            configuration
        )
        {
            //
            // Prepare Embedding Model Descriptor ...
            descriptor = configuration.GetModel(embeddingModelName);
            if (!descriptor.IsValid())
            {
                XException.InvalidConfiguration.Throw();
            }
        }

        /// <summary>
        /// Embedding Specified String ...
        /// </summary>
        /// <param name="content"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<float[]> Embeding(
            string content,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (content.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Ollama Client ...
            using var client = GetEmbeddingClient();

            //
            // Create Embeding Request ....
            var request = new EmbedRequest
            {
                Input = [content],
                Model = descriptor.LLM,
            };

            //
            // Make Request and Recieve Response ...
            var response = await client.EmbedAsync(
                request: request,
                cancellationToken: cancellationToken
            );
            if (response.IsNullOrDefault())
            {
                XException.ActionFailed.Throw();
            }

            //
            // Generae Result ...
            var result = response?
                .Embeddings?
                .FirstOrDefault()
                ?? [];
            if (result.Length == 0)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Normalize ...
            VectorHelper.Normalize(result);

            //
            return result;
        }

        /// <summary>
        /// Embedding Specified Batch ...
        /// </summary>
        /// <param name="batch"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IReadOnlyList<float[]>> Embedings(
            string[] batch,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (!batch.HasChild() ||
                !batch.All(x => !x.IsNullOrEmpty())
            )
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Ollama Client ...
            using var client = GetEmbeddingClient();

            //
            // Create Embeding Request ....
            var request = new EmbedRequest
            {
                Input = [.. batch],
                Model = descriptor.LLM,
            };

            //
            // Make Request and Recieve Response ...
            var response = await client.EmbedAsync(
                request: request,
                cancellationToken: cancellationToken
            );
            if (response.IsNullOrDefault())
            {
                XException.ActionFailed.Throw();
            }

            //
            // Generae Result ...
            var result = response?
                .Embeddings
                .ToArray()
                ?? [];

            //
            // Validate Result ...
            if (result.Length == 0)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Normalize ...
            foreach (var vector in result)
            {
                VectorHelper.Normalize(vector);
            }

            //
            return result;
        }

        /// <summary>
        /// Access Embedding Client ...
        /// </summary>
        /// <returns></returns>
        public OllamaApiClient GetEmbeddingClient()
        {
            //
            var result = new OllamaApiClient(new Uri(descriptor.Url));

            //
            return result;
        }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Providers\XAIServiceBase.cs

using System;
using System.Threading;
using xAiApi.Interfaces;
using xCommons.Extensions;
using xAiModels.Interfaces;
using xExceptions.Constants;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.AI;
using xAiModels.Extensions;
using xAiApi.Configurations;
using xAiApi.Extensions;
using System.Net.Http;
using OllamaSharp;

namespace xAiApi.Providers
{
    public abstract class XAIServiceBase : IXAiServiceBase
    {
        private readonly IXAiDataProvider dataProvider;
        private readonly ILogger<XAIServiceBase> logger;
        private readonly XAiApiConfiguration configuration;

        protected XAIServiceBase(
            IXAiDataProvider dataProvider,
            ILogger<XAIServiceBase> logger,
            XAiApiConfiguration configuration
        )
        {
            this.logger = logger;
            this.dataProvider = dataProvider;
            this.configuration = configuration;
        }

        //
        #region Actions ...
        /// <summary>
        /// Base Method for Communicate with LLM ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<string> AskAsync(
            string prompt,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check Prompt Exists ...
            if (prompt.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            using var client = GetClient();
            var history = GetHistory(prompt);
            var response = await client.GetResponseAsync(
                messages: history,
                cancellationToken: cancellationToken
            );

            //
            // Validate Response ...
            if (!response.IsValid())
            {
                //
                // Dispose Client ...
                client.Dispose();
                XException.ActionFailed.Throw();
            }

            //
            // Retrieve Response Text ...
            var result = response.Text;

            //
            // Dispose Client ...
            client.Dispose();

            //
            return result;
        }

        /// <summary>
        /// Base Method for Communicate with LLM ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async IAsyncEnumerable<string> AskAsEnumerable(
            string prompt,
            [EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check Prompt Exists ...
            if (prompt.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            using var client = GetClient();
            var history = GetHistory(prompt);
            var enumerable = client.GetStreamingResponseAsync(
                options: null,
                messages: history
            );

            //
            var result = "";
            await foreach (var res in enumerable)
            {
                //
                // Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    yield break;
                }

                //
                result += res.Text;
            }

            //
            // Dispose Client ...
            client.Dispose();

            //
            yield return result;
        }

        /// <summary>
        /// Get LLM Client instance for Communicating with LLM ...
        /// </summary>
        /// <param name="llm"></param>
        /// <returns></returns>
        public virtual IChatClient GetClient(string llm = null)
        {
            //
            // Retrieve Model Descriptor ...
            var modelDescriptor = configuration.GetModel(llm);
            if (modelDescriptor.IsNullOrDefault())
            {
                XException.NotFound.Throw();
            }

            //
            // Try to Initialize LLm ...
            var model = modelDescriptor.LLM;
            var apiKey = modelDescriptor.ApiKey;
            var url = new Uri(modelDescriptor.Url);
            var httpClient = GetHttpClient(modelDescriptor.Url);

            //
            IChatClient result = null;
            switch (modelDescriptor.Provider)
            {
                //
                case Constants.XAiProvider.Ollama:
                    //
                    // Instance Ollama Client using Custom HttpCLient ...
                    var ollamaClient = new OllamaApiClient(httpClient, model);
                    result =
                        new ChatClientBuilder(ollamaClient)
                        .Build();
                    break;

                //
                case Constants.XAiProvider.DeepSeek:
                    break;

                //
                case Constants.XAiProvider.HuggingFace:
                    break;

                //
                default:
                    break;
            }

            // //
            // if (isOllamaBased)
            // {
            // }
            // else if (isDeepSeekBased)
            // {
            //     //
            //     if (apiKey is null ||
            //         string.IsNullOrWhiteSpace(apiKey))
            //     {
            //         throw new Exception("Inavlid Args ...");
            //     }

            //     //
            //     var deepseekClient = new DeepSeekChatClient(apiKey: apiKey);
            //     result = deepseekClient;
            // }
            // else
            // {
            //     //
            //     // TODO: Implement this ...
            // }

            //
            if (result.IsNullOrDefault())
            {
                XException.InvalidData.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Create Custom HttpClient for Communicating with LLM API ...
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public virtual HttpClient GetHttpClient(string url = null)
        {
            //
            var result = new HttpClient
            {
                //
                // Disable timeout completely (not recommended for production)
                Timeout = Timeout.InfiniteTimeSpan,

                //
                BaseAddress = url.IsNullOrEmpty()
                    ? null
                    : new Uri(url),

                //
                // OR set a very long timeout (e.g., 30 minutes for large file uploads)
                // Timeout = TimeSpan.FromMinutes(30)
            };

            //
            return result;
        }

        /// <summary>
        /// Prepare a Message History List for LLM Communication based on Prompt ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="forcePrompt"></param>
        /// <returns></returns>
        public virtual IList<ChatMessage> GetHistory(
            string prompt = null,
            bool forcePrompt = true
        )
        {
            //
            // Validate Args ...
            if (prompt.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // User Prompt ...
            var promptMessage = new ChatMessage(
                ChatRole.User,
                prompt
            );

            //
            // Preparing Introduction Prompt ...
            var introductionPrompt = new ChatMessage(
                ChatRole.System,
                configuration.GetPrompt()
            );

            //
            List<ChatMessage> result =
            [
                introductionPrompt,
            ];
            if (forcePrompt &&
                prompt is not null &&
                !string.IsNullOrWhiteSpace(prompt))
            {
                result.Add(promptMessage);
            }

            //
            return result;
        }

        /// <summary>
        /// Prepare a Message History List for LLM Communication based on Prompt ...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="forceMessage"></param>
        /// <returns></returns>
        public virtual IList<ChatMessage> GetHistory(
            ChatMessage message = null,
            bool forceMessage = true
        )
        {
            //
            // Preparing Introduction Prompt ...
            var introductionPrompt = new ChatMessage(
                ChatRole.System,
                configuration.GetPrompt()
            );

            //
            List<ChatMessage> result =
            [
                introductionPrompt,
            ];
            if (forceMessage &&
                message is not null)
            {
                result.Add(message);
            }

            //
            return result;
        }
        #endregion

        /// <summary>
        /// Base Dispose Action ...
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        public virtual void Dispose()
        { }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Providers\XDefaultAiService.cs

using Microsoft.Extensions.Logging;
using xAiApi.Configurations;
using xAiApi.Interfaces;
using xAiModels.Interfaces;

namespace xAiApi.Providers
{
    public class XDefaultAiService : XAIServiceBase, IXDefaultAiService
    {
        public XDefaultAiService(
            IXAiDataProvider dataProvider,
            ILogger<XDefaultAiService> logger,
            XAiApiConfiguration configuration
        ) : base(
            dataProvider,
            logger,
            configuration
        )
        { }
    }
}

### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Providers\XDefaultEmbeddingService.cs

using Microsoft.Extensions.Logging;
using xAiApi.Configurations;
using xAiApi.Interfaces;
using xAiModels.Interfaces;

namespace xAiApi.Providers
{
    public class XDefaultEmbeddingService : XAiEmbeddingServiceBase, IXDefaultEmbeddingService
    {
        public XDefaultEmbeddingService(
            IXAiDataProvider dataProvider, 
            XAiApiConfiguration configuration, 
            ILogger<XDefaultEmbeddingService> logger
        ) : base(
            dataProvider, 
            configuration, 
            logger
        )
        { }
    }
}
