2651 lines
78 KiB
Plaintext
2651 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 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
|
|
)
|
|
{ }
|
|
}
|
|
}
|