From d8db4f0dceb7070446d6826a600d37718ab91844 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 5 Jan 2025 14:33:34 +0100 Subject: [PATCH] Refactored embedding settings --- .../Components/Settings/SettingsPanelBase.cs | 3 + .../Settings/SettingsPanelEmbeddings.razor | 70 +++++++++++ .../Settings/SettingsPanelEmbeddings.razor.cs | 112 ++++++++++++++++++ app/MindWork AI Studio/Pages/Settings.razor | 71 +---------- .../Pages/Settings.razor.cs | 99 +--------------- 5 files changed, 188 insertions(+), 167 deletions(-) create mode 100644 app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor create mode 100644 app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelBase.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelBase.cs index 6b12e282..f7f3a1d2 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelBase.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelBase.cs @@ -17,4 +17,7 @@ public abstract class SettingsPanelBase : ComponentBase [Inject] protected MessageBus MessageBus { get; init; } = null!; + + [Inject] + protected RustService RustService { get; init; } = null!; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor new file mode 100644 index 00000000..ea82ce7a --- /dev/null +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor @@ -0,0 +1,70 @@ +@using AIStudio.Provider +@using AIStudio.Settings.DataModel +@inherits SettingsPanelBase + +@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager)) +{ + + + + Configured Embeddings + + + Embeddings are a way to represent words, sentences, entire documents, or even images and videos as digital + fingerprints. Just like each person has a unique fingerprint, embedding models create unique digital patterns + that capture the meaning and characteristics of the content they analyze. When two things are similar in meaning + or content, their digital fingerprints will look very similar. For example, the fingerprints for 'happy' and + 'joyful' would be more alike than those for 'happy' and 'sad'. + + + + This helps AI Studio understand and compare things in a way that's similar to how humans do. When you're working on + something, AI Studio can automatically identify related documents and data by comparing their digital fingerprints. + For instance, if you're writing about customer service, AI Studio can instantly find other documents in your data that + discuss similar topics or experiences, even if they use different words. + + + + + + + + + + + # + Name + Provider + Model + Actions + + + @context.Num + @context.Name + @context.UsedLLMProvider + @this.GetEmbeddingProviderModelName(context) + + + + Open Dashboard + + + Edit + + + Delete + + + + + + @if (this.SettingsManager.ConfigurationData.EmbeddingProviders.Count == 0) + { + No embeddings configured yet. + } + + + Add Embedding + + +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs new file mode 100644 index 00000000..afa50246 --- /dev/null +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs @@ -0,0 +1,112 @@ +using AIStudio.Dialogs; +using AIStudio.Settings; + +using Microsoft.AspNetCore.Components; + +using DialogOptions = AIStudio.Dialogs.DialogOptions; + +namespace AIStudio.Components.Settings; + +public partial class SettingsPanelEmbeddings : SettingsPanelBase +{ + [Parameter] + public List> AvailableEmbeddingProviders { get; set; } = new(); + + [Parameter] + public EventCallback>> AvailableEmbeddingProvidersChanged { get; set; } + + 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() + { + var dialogParameters = new DialogParameters + { + { x => x.IsEditing, false }, + }; + + var dialogReference = await this.DialogService.ShowAsync("Add Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN); + 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); + await this.UpdateEmbeddingProviders(); + + await this.SettingsManager.StoreSettings(); + await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); + } + + private async Task EditEmbeddingProvider(EmbeddingProvider embeddingProvider) + { + var dialogParameters = new DialogParameters + { + { 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 }, + }; + + var dialogReference = await this.DialogService.ShowAsync("Edit Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN); + 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; + await this.UpdateEmbeddingProviders(); + + await this.SettingsManager.StoreSettings(); + await this.MessageBus.SendMessage(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("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(); + } + + await this.UpdateEmbeddingProviders(); + await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); + } + + private async Task UpdateEmbeddingProviders() + { + this.AvailableEmbeddingProviders.Clear(); + foreach (var provider in this.SettingsManager.ConfigurationData.EmbeddingProviders) + this.AvailableEmbeddingProviders.Add(new (provider.Name, provider.Id)); + + await this.AvailableEmbeddingProvidersChanged.InvokeAsync(this.AvailableEmbeddingProviders); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Pages/Settings.razor b/app/MindWork AI Studio/Pages/Settings.razor index ea3c42f5..f55be829 100644 --- a/app/MindWork AI Studio/Pages/Settings.razor +++ b/app/MindWork AI Studio/Pages/Settings.razor @@ -1,7 +1,6 @@ @attribute [Route(Routes.SETTINGS)] @using AIStudio.Provider @using AIStudio.Settings -@using AIStudio.Settings.DataModel @using AIStudio.Components.Settings @using Host = AIStudio.Provider.SelfHosted.Host @@ -129,74 +128,8 @@ } - - @if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager)) - { - - - - Configured Embeddings - - - Embeddings are a way to represent words, sentences, entire documents, or even images and videos as digital - fingerprints. Just like each person has a unique fingerprint, embedding models create unique digital patterns - that capture the meaning and characteristics of the content they analyze. When two things are similar in meaning - or content, their digital fingerprints will look very similar. For example, the fingerprints for 'happy' and - 'joyful' would be more alike than those for 'happy' and 'sad'. - - - - This helps AI Studio understand and compare things in a way that's similar to how humans do. When you're working on - something, AI Studio can automatically identify related documents and data by comparing their digital fingerprints. - For instance, if you're writing about customer service, AI Studio can instantly find other documents in your data that - discuss similar topics or experiences, even if they use different words. - - - - - - - - - - - # - Name - Provider - Model - Actions - - - @context.Num - @context.Name - @context.UsedLLMProvider - @this.GetEmbeddingProviderModelName(context) - - - - Open Dashboard - - - Edit - - - Delete - - - - - - @if (this.SettingsManager.ConfigurationData.EmbeddingProviders.Count == 0) - { - No embeddings configured yet. - } - - - Add Embedding - - - } - + + diff --git a/app/MindWork AI Studio/Pages/Settings.razor.cs b/app/MindWork AI Studio/Pages/Settings.razor.cs index cadcb35b..6d8e5c23 100644 --- a/app/MindWork AI Studio/Pages/Settings.razor.cs +++ b/app/MindWork AI Studio/Pages/Settings.razor.cs @@ -26,7 +26,7 @@ public partial class Settings : ComponentBase, IMessageBusReceiver, IDisposable private RustService RustService { get; init; } = null!; private readonly List> availableLLMProviders = new(); - private readonly List> availableEmbeddingProviders = new(); + private List> availableEmbeddingProviders = new(); #region Overrides of ComponentBase @@ -159,103 +159,6 @@ public partial class Settings : ComponentBase, IMessageBusReceiver, IDisposable await this.SettingsManager.StoreSettings(); } - #endregion - - #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() - { - var dialogParameters = new DialogParameters - { - { x => x.IsEditing, false }, - }; - - var dialogReference = await this.DialogService.ShowAsync("Add Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN); - 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(this, Event.CONFIGURATION_CHANGED); - } - - private async Task EditEmbeddingProvider(EmbeddingProvider embeddingProvider) - { - var dialogParameters = new DialogParameters - { - { 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 }, - }; - - var dialogReference = await this.DialogService.ShowAsync("Edit Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN); - 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(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("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(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 #region Implementation of IMessageBusReceiver