Files
xSaherElmAiApi/AI/Services/XAIService.cs
T
2026-04-17 03:04:14 +03:30

425 lines
12 KiB
C#

using System;
using OllamaSharp;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using xAiApi.AI.Interfaces;
using xCommons.Extensions;
using xExceptions.Constants;
using xAiApi.AI.Configuration;
using System.Collections.Generic;
using System.Threading;
using Microsoft.SemanticKernel.ChatCompletion;
using System.Runtime.CompilerServices;
namespace xAiApi.AI.Services
{
public class XAIService : IXAIService
{
/// <summary>
/// Provides Options for Chat ...
/// </summary>
/// <value></value>
public ChatOptions ChatOptions { get; }
/// <summary>
/// Provides History for Chat ...
/// </summary>
/// <value></value>
public ChatHistory ChatHistory { get; }
/// <summary>
/// a Client for Text Chat ...
/// </summary>
/// <value></value>
public IChatClient TextGenreatorClient { get; }
/// <summary>
/// a Client for Code Chat ...
/// </summary>
/// <value></value>
public IChatClient CodeGenreatorClient { get; }
/// <summary>
/// a Client for Image Chats ...
/// </summary>
/// <value></value>
public IChatClient ImageGenreatorClient { get; }
/// <summary>
/// Configuration ...
/// </summary>
/// <value></value>
public XAiApiConfiguration Configuration { get; }
/// <summary>
/// Constructing Service ...
/// </summary>
/// <param name="configuration">configuration ...</param>
public XAIService(
XAiApiConfiguration configuration
)
{
//
Configuration = configuration;
//
// here we are Initialize Text Generator Model ...
TextGenreatorClient = new ChatClientBuilder(new OllamaApiClient(
new Uri(configuration.Url),
configuration.TextModel
))
// .UseFunctionInvocation()
.Build();
//
// Code Generator Client ...
if (!configuration.CodeModel.IsNullOrEmpty())
{
//
CodeGenreatorClient = new ChatClientBuilder(new OllamaApiClient(
new Uri(configuration.Url),
configuration.CodeModel
))
// .UseFunctionInvocation()
.Build();
}
//
// Image Generator Client ...
if (!configuration.ImageModel.IsNullOrEmpty())
{
//
ImageGenreatorClient = new ChatClientBuilder(new OllamaApiClient(
new Uri(configuration.Url),
configuration.ImageModel
))
// .UseFunctionInvocation()
.Build();
}
//
// Configuring Chant Options ...
ChatOptions = new ChatOptions()
{
//
// Preparing Tools ...
// Tools = [
// //
// // Tempreature Tool ...
// AIFunctionFactory.Create((string location, string unit) => {
// //
// var temp = Random.Shared.Next(5, 20);
// var cond = Random.Shared.Next(0, 1) == 0 ? "sunny" : "rainy";
// //
// var result = $"The weather is {temp} degrees C and {cond}.";
// //
// return result;
// },
// "get_current_weather",
// "Get the current weather in given location"
// )
// ],
};
}
//
#region Text Actions ...
/// <summary>
/// Generated Response ...
/// </summary>
/// <param name="prompt"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<ChatResponse> GetResponseAsync(
string prompt,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid = !prompt.IsNullOrEmpty();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Preparing Prompt ...
prompt = await PreparePrompt(
prompt: prompt,
cancellationToken: cancellationToken
);
//
// Generate Response ...
var result = await TextGenreatorClient
.GetResponseAsync(
chatMessage: prompt,
options: ChatOptions,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Generated Response ...
/// </summary>
/// <param name="message">ChatMessage instance</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<ChatResponse> GetResponseByChatMessageAsync(
ChatMessage message,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid = !message.IsNull() && !message.Contents.HasChild();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Preparing Prompt ...
var prompt = await PreparePrompt(
message: message,
cancellationToken: cancellationToken
);
//
// Generate Response ...
var result = await TextGenreatorClient
.GetResponseAsync(
chatMessage: prompt,
options: ChatOptions,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Generated Response ...
/// </summary>
/// <param name="messages">ChatMessage Enumerable instance</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<ChatResponse> GetResponseByChatMessagesAsync(
IEnumerable<ChatMessage> messages,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid = !messages.IsNull() && messages.HasChild();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Preparing Prompt ...
var prompt = await PreparePrompt(
messages: messages,
cancellationToken: cancellationToken
);
//
// Generate Response ...
var result = await TextGenreatorClient
.GetResponseAsync(
messages: prompt,
options: ChatOptions,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Generated Text ...
/// </summary>
/// <param name="prompt"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<string> GetTextResponseAsync(
string prompt,
CancellationToken cancellationToken = default
)
{
//
var response = await GetResponseAsync(
prompt: prompt,
cancellationToken: cancellationToken
);
//
return response.Text;
}
/// <summary>
/// Generate Text Response Stream ...
/// </summary>
/// <param name="prompt"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async IAsyncEnumerable<string> GetTextReponseStreamAsync(
string prompt,
[EnumeratorCancellation]
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid = !prompt.IsNullOrEmpty();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Preparing Prompt ...
prompt = PreparePrompt(
prompt: prompt,
cancellationToken: cancellationToken
)
.RunTask();
//
// Generate Response ...
var stream = TextGenreatorClient
.GetStreamingResponseAsync(
chatMessage: prompt,
options: ChatOptions,
cancellationToken: cancellationToken
);
//
await foreach (var response in stream)
{
//
if (response.IsNull())
{
yield break;
}
//
var model = response.Text;
yield return model;
}
}
/// <summary>
/// Generate Text Response Stream ...
/// </summary>
/// <param name="prompt"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public IAsyncEnumerable<ChatResponseUpdate> GetReponseStreamAsync(
string prompt,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid = !prompt.IsNullOrEmpty();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Preparing Prompt ...
prompt = PreparePrompt(
prompt: prompt,
cancellationToken: cancellationToken
)
.RunTask();
//
// Generate Response ...
var result = TextGenreatorClient
.GetStreamingResponseAsync(
chatMessage: prompt,
options: ChatOptions,
cancellationToken: cancellationToken
);
//
return result;
}
#endregion
//
#region Code Actions ...
#endregion
//
#region Image Actions ...
#endregion
//
#region Private ...
/// <summary>
/// Preparing Prompt for AI ...
/// </summary>
/// <param name="prompt"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task<string> PreparePrompt(
string prompt,
CancellationToken cancellationToken = default
)
{
//
return await Task.Run(() =>
{
return prompt;
}, cancellationToken);
}
/// <summary>
/// Preparing Prompt for AI ...
/// </summary>
/// <param name="message"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task<ChatMessage> PreparePrompt(
ChatMessage message,
CancellationToken cancellationToken = default
)
{
//
return await Task.Run(() =>
{
return message;
}, cancellationToken);
}
/// <summary>
/// Preparing Prompt for AI ...
/// </summary>
/// <param name="messages"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task<IEnumerable<ChatMessage>> PreparePrompt(
IEnumerable<ChatMessage> messages,
CancellationToken cancellationToken = default
)
{
//
return await Task.Run(() =>
{
return messages;
}, cancellationToken);
}
#endregion
}
}