2024-08-21 06:30:01 +00:00
using AIStudio.Dialogs ;
2024-04-20 15:06:50 +00:00
using AIStudio.Provider ;
2024-04-19 19:25:44 +00:00
using AIStudio.Settings ;
2024-12-03 20:02:37 +00:00
using AIStudio.Settings.DataModel ;
2024-07-24 13:17:45 +00:00
2024-04-19 19:25:44 +00:00
using Microsoft.AspNetCore.Components ;
2024-08-21 06:30:01 +00:00
using DialogOptions = AIStudio . Dialogs . DialogOptions ;
2024-09-01 18:10:03 +00:00
using RustService = AIStudio . Tools . RustService ;
2024-06-30 13:26:28 +00:00
2024-04-19 19:25:44 +00:00
// ReSharper disable ClassNeverInstantiated.Global
2024-08-21 06:30:01 +00:00
namespace AIStudio.Pages ;
2024-04-19 19:25:44 +00:00
2024-07-28 09:20:00 +00:00
public partial class Settings : ComponentBase , IMessageBusReceiver , IDisposable
2024-04-19 19:25:44 +00:00
{
[Inject]
2024-09-01 18:10:03 +00:00
private SettingsManager SettingsManager { get ; init ; } = null ! ;
2024-04-19 19:25:44 +00:00
[Inject]
2024-09-01 18:10:03 +00:00
private IDialogService DialogService { get ; init ; } = null ! ;
2024-04-20 15:06:50 +00:00
[Inject]
2024-09-01 18:10:03 +00:00
private MessageBus MessageBus { get ; init ; } = null ! ;
2024-07-24 13:17:45 +00:00
2024-09-01 18:10:03 +00:00
[Inject]
private RustService RustService { get ; init ; } = null ! ;
2024-07-28 09:20:00 +00:00
2024-12-03 14:24:40 +00:00
private readonly List < ConfigurationSelectData < string > > availableLLMProviders = new ( ) ;
private readonly List < ConfigurationSelectData < string > > availableEmbeddingProviders = new ( ) ;
2024-07-28 09:20:00 +00:00
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync ( )
{
// Register this component with the message bus:
this . MessageBus . RegisterComponent ( this ) ;
this . MessageBus . ApplyFilters ( this , [ ] , [ Event . CONFIGURATION_CHANGED ] ) ;
this . UpdateProviders ( ) ;
await base . OnInitializedAsync ( ) ;
}
#endregion
2024-04-19 19:25:44 +00:00
2024-12-03 20:02:37 +00:00
#region Preview - feature related
private void UpdatePreviewFeatures ( PreviewVisibility previewVisibility )
{
this . SettingsManager . ConfigurationData . App . PreviewVisibility = previewVisibility ;
this . SettingsManager . ConfigurationData . App . EnabledPreviewFeatures = previewVisibility . FilterPreviewFeatures ( this . SettingsManager . ConfigurationData . App . EnabledPreviewFeatures ) ;
}
#endregion
2024-05-04 08:55:00 +00:00
#region Provider related
2024-12-03 14:24:40 +00:00
private async Task AddLLMProvider ( )
2024-04-19 19:25:44 +00:00
{
2024-04-19 21:27:38 +00:00
var dialogParameters = new DialogParameters < ProviderDialog >
{
2024-04-20 15:06:50 +00:00
{ x = > x . IsEditing , false } ,
2024-04-19 21:27:38 +00:00
} ;
2024-04-20 15:06:50 +00:00
2024-12-03 14:24:40 +00:00
var dialogReference = await this . DialogService . ShowAsync < ProviderDialog > ( "Add LLM Provider" , dialogParameters , DialogOptions . FULLSCREEN ) ;
2024-04-19 19:25:44 +00:00
var dialogResult = await dialogReference . Result ;
2024-07-24 13:17:45 +00:00
if ( dialogResult is null | | dialogResult . Canceled )
2024-04-19 19:25:44 +00:00
return ;
2024-07-24 13:17:45 +00:00
var addedProvider = ( AIStudio . Settings . Provider ) dialogResult . Data ! ;
2024-05-19 18:28:25 +00:00
addedProvider = addedProvider with { Num = this . SettingsManager . ConfigurationData . NextProviderNum + + } ;
2024-04-20 15:06:50 +00:00
this . SettingsManager . ConfigurationData . Providers . Add ( addedProvider ) ;
2024-07-28 09:20:00 +00:00
this . UpdateProviders ( ) ;
2024-04-20 15:06:50 +00:00
await this . SettingsManager . StoreSettings ( ) ;
2024-07-24 13:17:45 +00:00
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
2024-04-20 15:06:50 +00:00
}
2024-12-03 14:24:40 +00:00
private async Task EditLLMProvider ( AIStudio . Settings . Provider provider )
2024-04-20 15:06:50 +00:00
{
var dialogParameters = new DialogParameters < ProviderDialog >
{
2024-05-19 18:28:25 +00:00
{ x = > x . DataNum , provider . Num } ,
2024-04-20 15:06:50 +00:00
{ x = > x . DataId , provider . Id } ,
{ x = > x . DataInstanceName , provider . InstanceName } ,
2024-09-13 19:50:00 +00:00
{ x = > x . DataLLMProvider , provider . UsedLLMProvider } ,
2024-05-19 14:16:16 +00:00
{ x = > x . DataModel , provider . Model } ,
2024-07-03 18:31:04 +00:00
{ x = > x . DataHostname , provider . Hostname } ,
{ x = > x . IsSelfHosted , provider . IsSelfHosted } ,
2024-04-20 15:06:50 +00:00
{ x = > x . IsEditing , true } ,
2024-07-16 08:28:13 +00:00
{ x = > x . DataHost , provider . Host } ,
2024-04-20 15:06:50 +00:00
} ;
2024-12-03 14:24:40 +00:00
var dialogReference = await this . DialogService . ShowAsync < ProviderDialog > ( "Edit LLM Provider" , dialogParameters , DialogOptions . FULLSCREEN ) ;
2024-04-20 15:06:50 +00:00
var dialogResult = await dialogReference . Result ;
2024-07-24 13:17:45 +00:00
if ( dialogResult is null | | dialogResult . Canceled )
2024-04-20 15:06:50 +00:00
return ;
2024-07-24 13:17:45 +00:00
var editedProvider = ( AIStudio . Settings . Provider ) dialogResult . Data ! ;
2024-05-19 18:28:25 +00:00
// Set the provider number if it's not set. This is important for providers
// added before we started saving the provider number.
if ( editedProvider . Num = = 0 )
editedProvider = editedProvider with { Num = this . SettingsManager . ConfigurationData . NextProviderNum + + } ;
2024-04-20 15:06:50 +00:00
this . SettingsManager . ConfigurationData . Providers [ this . SettingsManager . ConfigurationData . Providers . IndexOf ( provider ) ] = editedProvider ;
2024-07-28 09:20:00 +00:00
this . UpdateProviders ( ) ;
2024-04-20 15:06:50 +00:00
await this . SettingsManager . StoreSettings ( ) ;
2024-07-24 13:17:45 +00:00
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
2024-04-20 15:06:50 +00:00
}
2024-12-03 14:24:40 +00:00
private async Task DeleteLLMProvider ( AIStudio . Settings . Provider provider )
2024-04-20 15:06:50 +00:00
{
var dialogParameters = new DialogParameters
{
{ "Message" , $"Are you sure you want to delete the provider '{provider.InstanceName}'?" } ,
} ;
2024-12-03 14:24:40 +00:00
var dialogReference = await this . DialogService . ShowAsync < ConfirmDialog > ( "Delete LLM Provider" , dialogParameters , DialogOptions . FULLSCREEN ) ;
2024-04-20 15:06:50 +00:00
var dialogResult = await dialogReference . Result ;
2024-07-24 13:17:45 +00:00
if ( dialogResult is null | | dialogResult . Canceled )
2024-04-20 15:06:50 +00:00
return ;
2024-12-03 14:24:40 +00:00
var deleteSecretResponse = await this . RustService . DeleteAPIKey ( provider ) ;
2024-04-20 15:06:50 +00:00
if ( deleteSecretResponse . Success )
{
this . SettingsManager . ConfigurationData . Providers . Remove ( provider ) ;
await this . SettingsManager . StoreSettings ( ) ;
}
2024-07-24 13:17:45 +00:00
2024-07-28 09:20:00 +00:00
this . UpdateProviders ( ) ;
2024-07-24 13:17:45 +00:00
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
2024-04-19 19:25:44 +00:00
}
2024-05-04 08:55:00 +00:00
2024-12-03 14:24:40 +00:00
private string GetLLMProviderModelName ( AIStudio . Settings . Provider provider )
2024-07-24 17:27:25 +00:00
{
const int MAX_LENGTH = 36 ;
var modelName = provider . Model . ToString ( ) ;
return modelName . Length > MAX_LENGTH ? "[...] " + modelName [ ^ Math . Min ( MAX_LENGTH , modelName . Length ) . . ] : modelName ;
}
2024-07-28 09:20:00 +00:00
private void UpdateProviders ( )
{
2024-12-03 14:24:40 +00:00
this . availableLLMProviders . Clear ( ) ;
2024-07-28 09:20:00 +00:00
foreach ( var provider in this . SettingsManager . ConfigurationData . Providers )
2024-12-03 14:24:40 +00:00
this . availableLLMProviders . Add ( new ( provider . InstanceName , provider . Id ) ) ;
2024-07-28 09:20:00 +00:00
}
2024-09-13 19:50:00 +00:00
private string GetCurrentConfidenceLevelName ( LLMProviders llmProvider )
2024-09-11 21:08:02 +00:00
{
2024-09-13 19:50:00 +00:00
if ( this . SettingsManager . ConfigurationData . LLMProviders . CustomConfidenceScheme . TryGetValue ( llmProvider , out var level ) )
2024-09-11 21:08:02 +00:00
return level . GetName ( ) ;
return "Not yet configured" ;
}
2024-09-13 19:50:00 +00:00
private string SetCurrentConfidenceLevelColorStyle ( LLMProviders llmProvider )
2024-09-11 21:08:02 +00:00
{
2024-09-13 19:50:00 +00:00
if ( this . SettingsManager . ConfigurationData . LLMProviders . CustomConfidenceScheme . TryGetValue ( llmProvider , out var level ) )
2024-09-15 10:30:07 +00:00
return $"background-color: {level.GetColor(this.SettingsManager)};" ;
2024-09-11 21:08:02 +00:00
2024-09-15 10:30:07 +00:00
return $"background-color: {ConfidenceLevel.UNKNOWN.GetColor(this.SettingsManager)};" ;
2024-09-11 21:08:02 +00:00
}
2024-09-13 19:50:00 +00:00
private async Task ChangeCustomConfidenceLevel ( LLMProviders llmProvider , ConfidenceLevel level )
2024-09-11 21:08:02 +00:00
{
2024-09-13 19:50:00 +00:00
this . SettingsManager . ConfigurationData . LLMProviders . CustomConfidenceScheme [ llmProvider ] = level ;
2024-09-11 21:08:02 +00:00
await this . SettingsManager . StoreSettings ( ) ;
}
2024-09-08 19:01:51 +00:00
#endregion
2024-12-03 14:24:40 +00:00
#region Embedding provider related
private string GetEmbeddingProviderModelName ( EmbeddingProvider provider )
{
const int MAX_LENGTH = 36 ;
var modelName = provider . Model . ToString ( ) ;
return modelName . Length > MAX_LENGTH ? "[...] " + modelName [ ^ Math . Min ( MAX_LENGTH , modelName . Length ) . . ] : modelName ;
}
private async Task AddEmbeddingProvider ( )
{
2025-01-01 14:49:27 +00:00
var dialogParameters = new DialogParameters < EmbeddingProviderDialog >
2024-12-03 14:24:40 +00:00
{
{ x = > x . IsEditing , false } ,
} ;
2025-01-01 14:49:27 +00:00
var dialogReference = await this . DialogService . ShowAsync < EmbeddingProviderDialog > ( "Add Embedding Provider" , dialogParameters , DialogOptions . FULLSCREEN ) ;
2024-12-03 14:24:40 +00:00
var dialogResult = await dialogReference . Result ;
if ( dialogResult is null | | dialogResult . Canceled )
return ;
var addedEmbedding = ( EmbeddingProvider ) dialogResult . Data ! ;
addedEmbedding = addedEmbedding with { Num = this . SettingsManager . ConfigurationData . NextEmbeddingNum + + } ;
this . SettingsManager . ConfigurationData . EmbeddingProviders . Add ( addedEmbedding ) ;
this . UpdateEmbeddingProviders ( ) ;
await this . SettingsManager . StoreSettings ( ) ;
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
}
private async Task EditEmbeddingProvider ( EmbeddingProvider embeddingProvider )
{
2025-01-01 14:49:27 +00:00
var dialogParameters = new DialogParameters < EmbeddingProviderDialog >
2024-12-03 14:24:40 +00:00
{
{ x = > x . DataNum , embeddingProvider . Num } ,
{ x = > x . DataId , embeddingProvider . Id } ,
{ x = > x . DataName , embeddingProvider . Name } ,
{ x = > x . DataLLMProvider , embeddingProvider . UsedLLMProvider } ,
{ x = > x . DataModel , embeddingProvider . Model } ,
{ x = > x . DataHostname , embeddingProvider . Hostname } ,
{ x = > x . IsSelfHosted , embeddingProvider . IsSelfHosted } ,
{ x = > x . IsEditing , true } ,
{ x = > x . DataHost , embeddingProvider . Host } ,
} ;
2025-01-01 14:49:27 +00:00
var dialogReference = await this . DialogService . ShowAsync < EmbeddingProviderDialog > ( "Edit Embedding Provider" , dialogParameters , DialogOptions . FULLSCREEN ) ;
2024-12-03 14:24:40 +00:00
var dialogResult = await dialogReference . Result ;
if ( dialogResult is null | | dialogResult . Canceled )
return ;
var editedEmbeddingProvider = ( EmbeddingProvider ) dialogResult . Data ! ;
// Set the provider number if it's not set. This is important for providers
// added before we started saving the provider number.
if ( editedEmbeddingProvider . Num = = 0 )
editedEmbeddingProvider = editedEmbeddingProvider with { Num = this . SettingsManager . ConfigurationData . NextEmbeddingNum + + } ;
this . SettingsManager . ConfigurationData . EmbeddingProviders [ this . SettingsManager . ConfigurationData . EmbeddingProviders . IndexOf ( embeddingProvider ) ] = editedEmbeddingProvider ;
this . UpdateEmbeddingProviders ( ) ;
await this . SettingsManager . StoreSettings ( ) ;
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
}
private async Task DeleteEmbeddingProvider ( EmbeddingProvider provider )
{
var dialogParameters = new DialogParameters
{
{ "Message" , $"Are you sure you want to delete the embedding provider '{provider.Name}'?" } ,
} ;
var dialogReference = await this . DialogService . ShowAsync < ConfirmDialog > ( "Delete Embedding Provider" , dialogParameters , DialogOptions . FULLSCREEN ) ;
var dialogResult = await dialogReference . Result ;
if ( dialogResult is null | | dialogResult . Canceled )
return ;
var deleteSecretResponse = await this . RustService . DeleteAPIKey ( provider ) ;
if ( deleteSecretResponse . Success )
{
this . SettingsManager . ConfigurationData . EmbeddingProviders . Remove ( provider ) ;
await this . SettingsManager . StoreSettings ( ) ;
}
this . UpdateEmbeddingProviders ( ) ;
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
}
private void UpdateEmbeddingProviders ( )
{
this . availableEmbeddingProviders . Clear ( ) ;
foreach ( var provider in this . SettingsManager . ConfigurationData . EmbeddingProviders )
this . availableEmbeddingProviders . Add ( new ( provider . Name , provider . Id ) ) ;
}
#endregion
2024-09-08 19:01:51 +00:00
#region Profile related
private async Task AddProfile ( )
{
var dialogParameters = new DialogParameters < ProfileDialog >
{
{ x = > x . IsEditing , false } ,
} ;
var dialogReference = await this . DialogService . ShowAsync < ProfileDialog > ( "Add Profile" , dialogParameters , DialogOptions . FULLSCREEN ) ;
var dialogResult = await dialogReference . Result ;
if ( dialogResult is null | | dialogResult . Canceled )
return ;
var addedProfile = ( Profile ) dialogResult . Data ! ;
addedProfile = addedProfile with { Num = this . SettingsManager . ConfigurationData . NextProfileNum + + } ;
this . SettingsManager . ConfigurationData . Profiles . Add ( addedProfile ) ;
await this . SettingsManager . StoreSettings ( ) ;
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
}
private async Task EditProfile ( Profile profile )
{
var dialogParameters = new DialogParameters < ProfileDialog >
{
{ x = > x . DataNum , profile . Num } ,
{ x = > x . DataId , profile . Id } ,
{ x = > x . DataName , profile . Name } ,
{ x = > x . DataNeedToKnow , profile . NeedToKnow } ,
{ x = > x . DataActions , profile . Actions } ,
{ x = > x . IsEditing , true } ,
} ;
var dialogReference = await this . DialogService . ShowAsync < ProfileDialog > ( "Edit Profile" , dialogParameters , DialogOptions . FULLSCREEN ) ;
var dialogResult = await dialogReference . Result ;
if ( dialogResult is null | | dialogResult . Canceled )
return ;
var editedProfile = ( Profile ) dialogResult . Data ! ;
this . SettingsManager . ConfigurationData . Profiles [ this . SettingsManager . ConfigurationData . Profiles . IndexOf ( profile ) ] = editedProfile ;
await this . SettingsManager . StoreSettings ( ) ;
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
}
private async Task DeleteProfile ( Profile profile )
{
var dialogParameters = new DialogParameters
{
{ "Message" , $"Are you sure you want to delete the profile '{profile.Name}'?" } ,
} ;
var dialogReference = await this . DialogService . ShowAsync < ConfirmDialog > ( "Delete Profile" , dialogParameters , DialogOptions . FULLSCREEN ) ;
var dialogResult = await dialogReference . Result ;
if ( dialogResult is null | | dialogResult . Canceled )
return ;
this . SettingsManager . ConfigurationData . Profiles . Remove ( profile ) ;
await this . SettingsManager . StoreSettings ( ) ;
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
}
2024-10-28 14:41:00 +00:00
#endregion
#region Bias - of - the - day related
private async Task ResetBiasOfTheDayHistory ( )
{
var dialogParameters = new DialogParameters
{
{ "Message" , "Are you sure you want to reset your bias-of-the-day statistics? The system will no longer remember which biases you already know. As a result, biases you are already familiar with may be addressed again." } ,
} ;
var dialogReference = await this . DialogService . ShowAsync < ConfirmDialog > ( "Reset your bias-of-the-day statistics" , dialogParameters , DialogOptions . FULLSCREEN ) ;
var dialogResult = await dialogReference . Result ;
if ( dialogResult is null | | dialogResult . Canceled )
return ;
this . SettingsManager . ConfigurationData . BiasOfTheDay . UsedBias . Clear ( ) ;
this . SettingsManager . ConfigurationData . BiasOfTheDay . DateLastBiasDrawn = DateOnly . MinValue ;
await this . SettingsManager . StoreSettings ( ) ;
await this . MessageBus . SendMessage < bool > ( this , Event . CONFIGURATION_CHANGED ) ;
}
2024-07-28 09:20:00 +00:00
#endregion
#region Implementation of IMessageBusReceiver
public Task ProcessMessage < TMsg > ( ComponentBase ? sendingComponent , Event triggeredEvent , TMsg ? data )
{
switch ( triggeredEvent )
{
case Event . CONFIGURATION_CHANGED :
this . StateHasChanged ( ) ;
break ;
}
return Task . CompletedTask ;
}
public Task < TResult ? > ProcessMessageWithResult < TPayload , TResult > ( ComponentBase ? sendingComponent , Event triggeredEvent , TPayload ? data )
{
return Task . FromResult < TResult ? > ( default ) ;
}
#endregion
#region Implementation of IDisposable
public void Dispose ( )
{
this . MessageBus . Unregister ( this ) ;
}
2024-07-24 17:27:25 +00:00
2024-05-04 08:55:00 +00:00
#endregion
2024-04-19 19:25:44 +00:00
}