425 lines
12 KiB
C#
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
|
|
}
|
|
} |