diff --git a/blazor/SyncfusionAISamples/Components/Service/AzureAIService.cs b/blazor/SyncfusionAISamples/Components/Service/AzureAIService.cs
index 229b964..a4aabcc 100644
--- a/blazor/SyncfusionAISamples/Components/Service/AzureAIService.cs
+++ b/blazor/SyncfusionAISamples/Components/Service/AzureAIService.cs
@@ -1,18 +1,34 @@
using Microsoft.Extensions.AI;
using Syncfusion.Blazor.SmartComponents;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using SyncfusionAISamples.Service;
+using Syncfusion.Blazor.Charts.Chart.Internal;
+using Azure.AI.OpenAI;
+using System.ClientModel;
+using Microsoft.JSInterop;
namespace SyncfusionAISamples.Service
{
public class AzureAIService
{
- private OpenAIConfiguration _openAIConfiguration;
+ //private readonly OpenAIConfiguration _openAIConfiguration;
+ private readonly UserTokenService _userTokenService;
private ChatParameters chatParameters_history = new ChatParameters();
+ private IChatClient _azureAIClient;
- public AzureAIService(OpenAIConfiguration openAIConfiguration)
+ public AzureAIService(UserTokenService userTokenService)
{
- _openAIConfiguration = openAIConfiguration;
+ string apiKey = "your-api-key";
+ string deploymentName = "your-deployment-name";
+ // your-azure-endpoint-url
+ string endpoint = "";
+ //_openAIConfiguration = openAIConfiguration;
+ _userTokenService = userTokenService;
+ _azureAIClient = new AzureOpenAIClient(new Uri(endpoint), new ApiKeyCredential(apiKey)).AsChatClient(deploymentName);
}
+
///
/// Gets a text completion from the Azure OpenAI service.
///
@@ -23,6 +39,14 @@ public AzureAIService(OpenAIConfiguration openAIConfiguration)
/// The AI-generated completion as a string.
public async Task GetCompletionAsync(string prompt, bool returnAsJson = true, bool appendPreviousResponse = false, string systemRole = null)
{
+ string userCode = await _userTokenService.GetUserFingerprintAsync();
+ int remainingTokens = await _userTokenService.GetRemainingTokensAsync(userCode);
+
+ if (remainingTokens <= 0)
+ {
+ await _userTokenService.ShowAlert();
+ return string.Empty;
+ }
string systemMessage = returnAsJson ? "You are a helpful assistant that only returns and replies with valid, iterable RFC8259 compliant JSON in your responses unless I ask for any other format. Do not provide introductory words such as 'Here is your result' or '```json', etc. in the response" : !string.IsNullOrEmpty(systemRole) ? systemRole : "You are a helpful assistant";
try
{
@@ -44,12 +68,13 @@ public async Task GetCompletionAsync(string prompt, bool returnAsJson =
new ChatMessage(ChatRole.User,prompt)
};
}
- var completion = await _openAIConfiguration.GetChatResponseAsync(chatParameters);
+ var completion = await GetChatResponseAsync(chatParameters);
if (appendPreviousResponse)
{
chatParameters_history?.Messages?.Add(new ChatMessage(ChatRole.Assistant, completion.ToString()));
}
- return completion.ToString();
+ await _userTokenService.UpdateTokensAsync(userCode, (int)(remainingTokens - completion.Usage.TotalTokenCount));
+ return completion.Message.Text.ToString();
}
catch (Exception ex)
{
@@ -57,5 +82,28 @@ public async Task GetCompletionAsync(string prompt, bool returnAsJson =
return "";
}
}
+
+ public async Task GetChatResponseAsync(ChatParameters options)
+ {
+ // Create a completion request with the provided parameters
+ var completionRequest = new ChatOptions
+ {
+ Temperature = options.Temperature ?? 0.5f,
+ TopP = options.TopP ?? 1.0f,
+ MaxOutputTokens = options.MaxTokens ?? 2000,
+ FrequencyPenalty = options.FrequencyPenalty ?? 0.0f,
+ PresencePenalty = options.PresencePenalty ?? 0.0f,
+ StopSequences = options.StopSequences
+ };
+ try
+ {
+ ChatCompletion completion = await _azureAIClient.CompleteAsync(options.Messages, completionRequest);
+ return completion;
+ }
+ catch (Exception ex)
+ {
+ throw;
+ }
+ }
}
}
diff --git a/blazor/SyncfusionAISamples/Components/Service/CustomInferenceBackend.cs b/blazor/SyncfusionAISamples/Components/Service/CustomInferenceBackend.cs
new file mode 100644
index 0000000..7abd94e
--- /dev/null
+++ b/blazor/SyncfusionAISamples/Components/Service/CustomInferenceBackend.cs
@@ -0,0 +1,57 @@
+using Azure.AI.OpenAI;
+using Microsoft.Extensions.AI;
+using Microsoft.JSInterop;
+using OpenAI;
+using Syncfusion.Blazor.SmartComponents;
+using SyncfusionAISamples.Service;
+using System.ClientModel;
+
+namespace SyncfusionAISamples.Components.Service
+{
+ public class CustomInferenceBackend : IInferenceBackend
+ {
+ private IChatClient client;
+ private readonly UserTokenService _userTokenService;
+ public CustomInferenceBackend(UserTokenService userTokenService)
+ {
+ string apiKey = "your-api-key";
+ string deploymentName = "your-deployment-name";
+ // your-azure-endpoint-url
+ string endpoint = "";
+ client = new AzureOpenAIClient(new Uri(endpoint), new ApiKeyCredential(apiKey)).AsChatClient(deploymentName);
+ _userTokenService = userTokenService;
+ }
+
+ public async Task GetChatResponseAsync(ChatParameters options)
+ {
+ //string userCode = await _userTokenService.GetUserFingerprintAsync();
+ //int remainingTokens = await _userTokenService.GetRemainingTokensAsync(userCode);
+
+ //if (remainingTokens <= 0)
+ //{
+ // await _userTokenService.ShowAlert();
+ // return string.Empty;
+ //}
+ // Create a completion request with the provided parameters
+ var completionRequest = new ChatOptions
+ {
+ Temperature = options.Temperature ?? 0.5f,
+ TopP = options.TopP ?? 1.0f,
+ MaxOutputTokens = options.MaxTokens ?? 2000,
+ FrequencyPenalty = options.FrequencyPenalty ?? 0.0f,
+ PresencePenalty = options.PresencePenalty ?? 0.0f,
+ StopSequences = options.StopSequences
+ };
+ try
+ {
+ ChatCompletion completion = await client.CompleteAsync(options.Messages, completionRequest);
+ //await _userTokenService.UpdateTokensAsync(userCode, (int)(remainingTokens - completion.Usage.TotalTokenCount));
+ return completion.Message.Text;
+ }
+ catch (Exception ex)
+ {
+ throw;
+ }
+ }
+ }
+}
diff --git a/blazor/SyncfusionAISamples/Components/Service/UserTokenService.cs b/blazor/SyncfusionAISamples/Components/Service/UserTokenService.cs
new file mode 100644
index 0000000..f9978da
--- /dev/null
+++ b/blazor/SyncfusionAISamples/Components/Service/UserTokenService.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Microsoft.JSInterop;
+
+namespace SyncfusionAISamples.Service
+{
+ public class UserTokenService
+ {
+ private readonly IJSRuntime _jsRuntime;
+ private const string TokenFilePath = "user_tokens.json";
+ private static readonly TimeZoneInfo IndianStandardTime = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
+
+ public UserTokenService(IJSRuntime jsRuntime)
+ {
+ _jsRuntime = jsRuntime;
+ }
+
+ public async Task GetUserFingerprintAsync()
+ {
+ return await _jsRuntime.InvokeAsync("fingerPrint");
+ }
+
+ public async Task GetRemainingTokensAsync(string userCode)
+ {
+ var tokens = await CheckAndResetTokensAsync(userCode);
+ return tokens.ContainsKey(userCode) ? tokens[userCode].RemainingTokens : 10000;
+ }
+
+ public async Task UpdateTokensAsync(string userCode, int tokens)
+ {
+ var tokenData = await ReadTokensFromFileAsync();
+ if (tokenData.ContainsKey(userCode))
+ {
+ tokenData[userCode].RemainingTokens = tokens;
+ }
+ else
+ {
+ tokenData[userCode] = new UserTokenInfo
+ {
+ UserId = userCode,
+ DateOfLogin = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, IndianStandardTime),
+ RemainingTokens = tokens
+ };
+ }
+ await WriteTokensToFileAsync(tokenData);
+ }
+
+ public async Task> CheckAndResetTokensAsync(string userCode)
+ {
+ var tokenData = await ReadTokensFromFileAsync();
+ if (tokenData.ContainsKey(userCode))
+ {
+ var userTokenInfo = tokenData[userCode];
+ var currentTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, IndianStandardTime);
+ var timeDifference = currentTime - userTokenInfo.DateOfLogin;
+
+ if (timeDifference.TotalHours > 1)
+ {
+ userTokenInfo.RemainingTokens = 10000; // Reset tokens
+ userTokenInfo.DateOfLogin = currentTime; // Update login time
+ await WriteTokensToFileAsync(tokenData);
+ }
+ }
+ return tokenData;
+ }
+
+ private async Task> ReadTokensFromFileAsync()
+ {
+ if (!File.Exists(TokenFilePath))
+ {
+ var initialData = new Dictionary();
+ await WriteTokensToFileAsync(initialData);
+ return initialData;
+ }
+
+ var json = await File.ReadAllTextAsync(TokenFilePath);
+ return JsonSerializer.Deserialize>(json) ?? new Dictionary();
+ }
+
+ private async Task WriteTokensToFileAsync(Dictionary tokenData)
+ {
+ var json = JsonSerializer.Serialize(tokenData, new JsonSerializerOptions { WriteIndented = true });
+ await File.WriteAllTextAsync(TokenFilePath, json);
+ }
+
+ public async Task ShowAlert()
+ {
+ await _jsRuntime.InvokeVoidAsync("showAlert", "You have no remaining tokens.");
+ }
+ }
+
+ public class UserTokenInfo
+ {
+ public string UserId { get; set; }
+ public DateTime DateOfLogin { get; set; }
+ public int RemainingTokens { get; set; }
+ }
+}
diff --git a/blazor/SyncfusionAISamples/Program.cs b/blazor/SyncfusionAISamples/Program.cs
index 68abb69..35f466f 100644
--- a/blazor/SyncfusionAISamples/Program.cs
+++ b/blazor/SyncfusionAISamples/Program.cs
@@ -1,8 +1,10 @@
using FileManagerAI.Services;
+using Microsoft.AspNetCore.DataProtection.KeyManagement;
using SmartComponents.LocalEmbeddings;
using Syncfusion.Blazor;
using Syncfusion.Blazor.SmartComponents;
using SyncfusionAISamples.Components;
+using SyncfusionAISamples.Components.Service;
using SyncfusionAISamples.Service;
var builder = WebApplication.CreateBuilder(args);
@@ -23,19 +25,13 @@
// Local Embeddings
builder.Services.AddSingleton();
-// OpenAI Service
-string apiKey = "your-api-key";
-string deploymentName = "your-deployment-name";
-// your-azure-endpoint-url
-string endpoint = "";
-//Injecting smart components
-builder.Services.AddSyncfusionSmartComponents()
- .ConfigureCredentials(new AIServiceCredentials(apiKey, deploymentName, endpoint)) //Configuring credentials for AI functionality to work
- .InjectOpenAIInference(); // Injecting OpenAI Services
-builder.Services.AddSingleton();
-builder.Services.AddSingleton();
+//builder.Services.AddSingleton();
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+builder.Services.AddSyncfusionSmartComponents();
#endregion
var app = builder.Build();
diff --git a/blazor/SyncfusionAISamples/SyncfusionAISamples.csproj b/blazor/SyncfusionAISamples/SyncfusionAISamples.csproj
index c799c8d..6c929ac 100644
--- a/blazor/SyncfusionAISamples/SyncfusionAISamples.csproj
+++ b/blazor/SyncfusionAISamples/SyncfusionAISamples.csproj
@@ -7,6 +7,7 @@
+
diff --git a/blazor/SyncfusionAISamples/wwwroot/scripts/smart-component.js b/blazor/SyncfusionAISamples/wwwroot/scripts/smart-component.js
index e902a96..812cb77 100644
--- a/blazor/SyncfusionAISamples/wwwroot/scripts/smart-component.js
+++ b/blazor/SyncfusionAISamples/wwwroot/scripts/smart-component.js
@@ -435,4 +435,23 @@ window.preventTabDefault = function (textareaId, dotnetRef) {
});
}
-/* Diagram scripts end */
\ No newline at end of file
+/* Diagram scripts end */
+
+async function fingerPrint() {
+ try {
+ // Import FingerprintJS and load the agent
+ const FingerprintJS = await import('https://openfpcdn.io/fingerprintjs/v4');
+ const fp = await FingerprintJS.load();
+
+ // Get the visitor identifier
+ const result = await fp.get();
+ return result.visitorId;
+ } catch (error) {
+ console.error(error);
+ return null;
+ }
+}
+
+function showAlert(message) {
+ alert(message);
+}