Files
xSaherelmWorkspace/Documents/GeneratedContext/xDashboard-xAiApi-20260926_085146.txt
T
2026-09-26 10:46:28 +03:30

2600 lines
78 KiB
Plaintext

### 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 xAiModels.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";
//
public const string XOpenAINoKey = "no-key-required";
}
}
### 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("Embedding")]
public async Task<ActionResult<float[]>> Embedding(
[FromQuery] string content,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate ...
ValidationProvider.NotEmpty(content);
//
var result = await aiService.Embedding(
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("Embeddings")]
public async Task<ActionResult<IReadOnlyList<float[]>>> Embeddings(
[FromQuery] string[] batch,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate ...
ValidationProvider.NotZeroChilds(batch);
//
var result = await aiService.Embeddings(
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 xAiApi.Constants;
using xAiApi.Extensions;
using xCommons.Extensions;
using xAiApi.Configurations;
using xExceptions.Constants;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
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.Linq;
using xAiApi.Constants;
using xAiModels.Models;
using xCommons.Extensions;
using xAiModels.Extensions;
using xAiApi.Configurations;
using System.Collections.Generic;
namespace xAiApi.Extensions
{
public static class XModelsExtensions
{
/// <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>
/// 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 Microsoft.Extensions.AI;
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[]> Embedding(
string content,
CancellationToken cancellationToken = default
);
/// <summary>
/// Embedding Specified Batch ...
/// </summary>
/// <param name="batch"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IReadOnlyList<float[]>> Embeddings(
string[] batch,
CancellationToken cancellationToken = default
);
/// <summary>
/// Access Embedding Client ...
/// </summary>
/// <returns></returns>
OllamaApiClient GetEmbeddingClient();
IEmbeddingGenerator<string, Embedding<float>> GetEmbeddingGenerator();
}
}
### 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("Embedding")]
Task<ActionResult<float[]>> Embedding(
[FromQuery] string content,
CancellationToken cancellationToken = default
);
/// <summary>
/// Request For Embedding Specified Batch ...
/// </summary>
/// <param name="batch"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("Embeddings")]
Task<ActionResult<IReadOnlyList<float[]>>> Embeddings(
[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\Providers\XAiEmbeddingServiceBase.cs
using System;
using System.Linq;
using OllamaSharp;
using System.Threading;
using xAiApi.Constants;
using xAiModels.Models;
using xAiApi.Extensions;
using xAiApi.Interfaces;
using OllamaSharp.Models;
using xAiService.Helpers;
using xCommons.Extensions;
using xAiModels.Extensions;
using xAiModels.Interfaces;
using xAiApi.Configurations;
using xExceptions.Constants;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.AI;
using xAiModels.Constants;
using OpenAI;
using System.ClientModel;
using System.ClientModel.Primitives;
namespace xAiApi.Providers
{
/// <summary>
/// Base Embedding Provider Service ...
/// </summary>
public abstract class XAiEmbeddingServiceBase : XAIServiceBase, IXAiEmbeddingServiceBase
{
private readonly XAiModelDescriptor descriptor;
private readonly ILogger<XAiEmbeddingServiceBase> logger;
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();
}
//
this.logger = logger;
}
/// <summary>
/// Embedding Specified String ...
/// </summary>
/// <param name="content"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<float[]> Embedding(
string content,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
if (content.IsNullOrEmpty())
{
XException.InvalidArgs.Throw();
}
//
using var generator = GetEmbeddingGenerator();
GeneratedEmbeddings<Embedding<float>> response = null;
try
{
response = await generator.GenerateAsync([content]);
}
catch (Exception ex)
{
logger.LogError(ex.Message);
}
//
if (response.IsNullOrDefault())
{
XException.ActionFailed.Throw();
}
//
// Generae Result ...
var result = response
.First()?
.Vector
.ToArray()
?? [];
if (result.Length == 0)
{
XException.ActionFailed.Throw();
}
//
// Retrieve Ollama Client ...
// using var client = GetEmbeddingClient();
// //
// // Create Embedding 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[]>> Embeddings(
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 Embedding 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;
}
public IEmbeddingGenerator<string, Embedding<float>> GetEmbeddingGenerator()
{
//
IEmbeddingGenerator<string, Embedding<float>> result = null;
//
if (!descriptor.IsValid())
{
XException.InvalidData.Throw("Invalid Embedding Model ...");
}
//
switch (descriptor.Provider)
{
//
case XAiModelProviderType.OpenAI:
//
var openAiClient = new OpenAIClient(
new ApiKeyCredential(descriptor.ApiKey.IsNullOrEmpty() ? XAiApiConstants.XOpenAINoKey : descriptor.ApiKey),
new OpenAIClientOptions
{
Endpoint = new Uri(descriptor.Url),
Transport = new HttpClientPipelineTransport(GetHttpClient(descriptor.Url))
}
);
result = openAiClient
.GetEmbeddingClient(descriptor.LLM)
.AsIEmbeddingGenerator();
break;
//
case XAiModelProviderType.Ollama:
//
var ollamaClient = new OllamaApiClient(new Uri(descriptor.Url));
result = ollamaClient;
break;
}
//
if (result.IsNull())
{
XException.InvalidData.Throw("Invalid Embedding Model ...");
}
//
return result;
}
}
}
### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xAiApi\Providers\XAIServiceBase.cs
using System;
using OpenAI;
using OllamaSharp;
using System.Net.Http;
using System.Threading;
using xAiApi.Constants;
using xAiApi.Interfaces;
using xAiApi.Extensions;
using System.ClientModel;
using xCommons.Extensions;
using xAiModels.Constants;
using xAiModels.Interfaces;
using xAiModels.Extensions;
using xAiApi.Configurations;
using xExceptions.Constants;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using System.ClientModel.Primitives;
using System.Runtime.CompilerServices;
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 XAiModelProviderType.Ollama:
//
// Instance Ollama Client using Custom HttpCLient ...
var ollamaClient = new OllamaApiClient(httpClient, model);
result =
new ChatClientBuilder(ollamaClient)
.Build();
break;
//
case XAiModelProviderType.OpenAI:
//
// Instance Ollama Client using Custom HttpCLient ...
var openAiClient = new OpenAIClient(
new ApiKeyCredential(apiKey.IsNullOrEmpty() ? XAiApiConstants.XOpenAINoKey : apiKey),
new OpenAIClientOptions
{
Endpoint = url,
Transport = new HttpClientPipelineTransport(httpClient)
}
);
result =
openAiClient
.GetChatClient(model)
.AsIChatClient();
break;
//
case XAiModelProviderType.DeepSeek:
break;
//
case XAiModelProviderType.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
)
{ }
}
}