diff --git a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor index 2dc5bf8..3f0978c 100644 --- a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor +++ b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs index 87889b0..28f2b4b 100644 --- a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs +++ b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs @@ -1,3 +1,4 @@ +using AIStudio.Provider; using AIStudio.Settings; using Microsoft.AspNetCore.Components; @@ -43,6 +44,25 @@ public partial class ConfigurationProviderSelection : ComponentBase, IMessageBus #endregion + private IEnumerable> FilteredData() + { + if (this.SettingsManager.ConfigurationData.LLMProviders is { EnforceGlobalMinimumConfidence: true, GlobalMinimumConfidence: not ConfidenceLevel.NONE and not ConfidenceLevel.UNKNOWN }) + { + var minimumLevel = this.SettingsManager.ConfigurationData.LLMProviders.GlobalMinimumConfidence; + foreach (var providerId in this.Data) + { + var provider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == providerId.Value); + if (provider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel) + yield return providerId; + } + } + else + { + foreach (var provider in this.Data) + yield return provider; + } + } + #region Implementation of IMessageBusReceiver public async Task ProcessMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data) diff --git a/app/MindWork AI Studio/Components/ProviderSelection.razor b/app/MindWork AI Studio/Components/ProviderSelection.razor index aebe6e5..3ac64b9 100644 --- a/app/MindWork AI Studio/Components/ProviderSelection.razor +++ b/app/MindWork AI Studio/Components/ProviderSelection.razor @@ -1,7 +1,7 @@ @using AIStudio.Settings - @foreach (var provider in this.SettingsManager.ConfigurationData.Providers) + @foreach (var provider in this.GetAvailableProviders()) { } diff --git a/app/MindWork AI Studio/Components/ProviderSelection.razor.cs b/app/MindWork AI Studio/Components/ProviderSelection.razor.cs index ad2249f..82ff2e7 100644 --- a/app/MindWork AI Studio/Components/ProviderSelection.razor.cs +++ b/app/MindWork AI Studio/Components/ProviderSelection.razor.cs @@ -1,3 +1,4 @@ +using AIStudio.Provider; using AIStudio.Settings; using Microsoft.AspNetCore.Components; @@ -16,11 +17,27 @@ public partial class ProviderSelection : ComponentBase public Func ValidateProvider { get; set; } = _ => null; [Inject] - protected SettingsManager SettingsManager { get; set; } = null!; + private SettingsManager SettingsManager { get; init; } = null!; private async Task SelectionChanged(Settings.Provider provider) { this.ProviderSettings = provider; await this.ProviderSettingsChanged.InvokeAsync(provider); } + + private IEnumerable GetAvailableProviders() + { + if (this.SettingsManager.ConfigurationData.LLMProviders is { EnforceGlobalMinimumConfidence: true, GlobalMinimumConfidence: not ConfidenceLevel.NONE and not ConfidenceLevel.UNKNOWN }) + { + var minimumLevel = this.SettingsManager.ConfigurationData.LLMProviders.GlobalMinimumConfidence; + foreach (var provider in this.SettingsManager.ConfigurationData.Providers) + if (provider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel) + yield return provider; + } + else + { + foreach (var provider in this.SettingsManager.ConfigurationData.Providers) + yield return provider; + } + } } \ 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 faeda70..50f40da 100644 --- a/app/MindWork AI Studio/Pages/Settings.razor +++ b/app/MindWork AI Studio/Pages/Settings.razor @@ -80,6 +80,12 @@ Either you choose a common schema, or you configure the trust levels for each LLM provider yourself. + + @if(this.SettingsManager.ConfigurationData.LLMProviders.EnforceGlobalMinimumConfidence) + { + + } + @if (this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence) { diff --git a/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs b/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs index c48ea6d..44b17af 100644 --- a/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs +++ b/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs @@ -4,6 +4,7 @@ using AIStudio.Assistants.IconFinder; using AIStudio.Assistants.RewriteImprove; using AIStudio.Assistants.TextSummarizer; using AIStudio.Assistants.EMail; +using AIStudio.Provider; using AIStudio.Settings.DataModel; using WritingStylesRewrite = AIStudio.Assistants.RewriteImprove.WritingStyles; @@ -142,4 +143,24 @@ public static class ConfigurationSelectDataFactory foreach (var scheme in Enum.GetValues()) yield return new(scheme.GetListDescription(), scheme); } + + public static IEnumerable> GetConfidenceLevelsData() + { + foreach (var level in Enum.GetValues()) + { + switch (level) + { + case ConfidenceLevel.UNKNOWN: + continue; + + case ConfidenceLevel.NONE: + yield return new("No minimum confidence level chosen", level); + break; + + default: + yield return new(level.GetName(), level); + break; + } + } + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/Data.cs b/app/MindWork AI Studio/Settings/DataModel/Data.cs index 1fe0a92..5970f6d 100644 --- a/app/MindWork AI Studio/Settings/DataModel/Data.cs +++ b/app/MindWork AI Studio/Settings/DataModel/Data.cs @@ -9,7 +9,7 @@ public sealed class Data /// The version of the settings file. Allows us to upgrade the settings /// when a new version is available. /// - public Version Version { get; init; } = Version.V4; + public Version Version { get; init; } = Version.V5; /// /// List of configured providers. diff --git a/app/MindWork AI Studio/Settings/DataModel/DataLLMProviders.cs b/app/MindWork AI Studio/Settings/DataModel/DataLLMProviders.cs index c7c9b66..a716476 100644 --- a/app/MindWork AI Studio/Settings/DataModel/DataLLMProviders.cs +++ b/app/MindWork AI Studio/Settings/DataModel/DataLLMProviders.cs @@ -4,6 +4,16 @@ namespace AIStudio.Settings.DataModel; public sealed class DataLLMProviders { + /// + /// Should we enforce a global minimum confidence level? + /// + public bool EnforceGlobalMinimumConfidence { get; set; } + + /// + /// The global minimum confidence level to enforce. + /// + public ConfidenceLevel GlobalMinimumConfidence { get; set; } = ConfidenceLevel.NONE; + /// /// Should we show the provider confidence level? /// diff --git a/app/MindWork AI Studio/Settings/DataModel/PreviousModels/DataV4.cs b/app/MindWork AI Studio/Settings/DataModel/PreviousModels/DataV4.cs new file mode 100644 index 0000000..ecaebe8 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/PreviousModels/DataV4.cs @@ -0,0 +1,65 @@ +namespace AIStudio.Settings.DataModel.PreviousModels; + +public sealed class DataV4 +{ + /// + /// The version of the settings file. Allows us to upgrade the settings + /// when a new version is available. + /// + public Version Version { get; init; } + + /// + /// List of configured providers. + /// + public List Providers { get; init; } = []; + + /// + /// Settings concerning the LLM providers. + /// + public DataLLMProviders LLMProviders { get; init; } = new(); + + /// + /// List of configured profiles. + /// + public List Profiles { get; init; } = []; + + /// + /// The next provider number to use. + /// + public uint NextProviderNum { get; set; } = 1; + + /// + /// The next profile number to use. + /// + public uint NextProfileNum { get; set; } = 1; + + public DataApp App { get; init; } = new(); + + public DataChat Chat { get; init; } = new(); + + public DataWorkspace Workspace { get; init; } = new(); + + public DataIconFinder IconFinder { get; init; } = new(); + + public DataTranslation Translation { get; init; } = new(); + + public DataCoding Coding { get; init; } = new(); + + public DataTextSummarizer TextSummarizer { get; init; } = new(); + + public DataTextContentCleaner TextContentCleaner { get; init; } = new(); + + public DataAgenda Agenda { get; init; } = new(); + + public DataGrammarSpelling GrammarSpelling { get; init; } = new(); + + public DataRewriteImprove RewriteImprove { get; init; } = new(); + + public DataEMail EMail { get; set; } = new(); + + public DataLegalCheck LegalCheck { get; set; } = new(); + + public DataSynonyms Synonyms { get; set; } = new(); + + public DataMyTasks MyTasks { get; set; } = new(); +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/PreviousModels/ProviderV4.cs b/app/MindWork AI Studio/Settings/DataModel/PreviousModels/ProviderV4.cs new file mode 100644 index 0000000..1d0fd89 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/PreviousModels/ProviderV4.cs @@ -0,0 +1,15 @@ +using AIStudio.Provider; + +using Host = AIStudio.Provider.SelfHosted.Host; + +namespace AIStudio.Settings.DataModel.PreviousModels; + +public readonly record struct Provider( + uint Num, + string Id, + string InstanceName, + LLMProviders UsedProvider, + Model Model, + bool IsSelfHosted = false, + string Hostname = "http://localhost:1234", + Host Host = Host.NONE); \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/PreviousModels/ProviderV4Extensions.cs b/app/MindWork AI Studio/Settings/DataModel/PreviousModels/ProviderV4Extensions.cs new file mode 100644 index 0000000..50be698 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/PreviousModels/ProviderV4Extensions.cs @@ -0,0 +1,21 @@ +namespace AIStudio.Settings.DataModel.PreviousModels; + +public static class ProviderV4Extensions +{ + public static List MigrateFromV4ToV5(this IEnumerable providers) + { + return providers.Select(provider => provider.MigrateFromV4ToV5()).ToList(); + } + + public static Settings.Provider MigrateFromV4ToV5(this Provider provider) => new() + { + Num = provider.Num, + Id = provider.Id, + InstanceName = provider.InstanceName, + UsedLLMProvider = provider.UsedProvider, + Model = provider.Model, + IsSelfHosted = provider.IsSelfHosted, + Hostname = provider.Hostname, + Host = provider.Host, + }; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs index a568aff..485d550 100644 --- a/app/MindWork AI Studio/Settings/SettingsManager.cs +++ b/app/MindWork AI Studio/Settings/SettingsManager.cs @@ -114,7 +114,9 @@ public sealed class SettingsManager(ILogger logger) public Provider GetPreselectedProvider(Tools.Components component) { - if(this.ConfigurationData.Providers.Count == 1) + var minimumLevel = this.ConfigurationData.LLMProviders.EnforceGlobalMinimumConfidence ? this.ConfigurationData.LLMProviders.GlobalMinimumConfidence : ConfidenceLevel.NONE; + + if (this.ConfigurationData.Providers.Count == 1 && this.ConfigurationData.Providers[0].UsedLLMProvider.GetConfidence(this).Level >= minimumLevel) return this.ConfigurationData.Providers[0]; var preselection = component switch @@ -135,10 +137,10 @@ public sealed class SettingsManager(ILogger logger) _ => default, }; - if (preselection != default) + if(preselection != default && preselection.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel) return preselection; - return this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.App.PreselectedProvider); + return this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.App.PreselectedProvider && x.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel); } public Profile GetPreselectedProfile(Tools.Components component) diff --git a/app/MindWork AI Studio/Settings/SettingsMigrations.cs b/app/MindWork AI Studio/Settings/SettingsMigrations.cs index 9c5bd3a..da2a5ee 100644 --- a/app/MindWork AI Studio/Settings/SettingsMigrations.cs +++ b/app/MindWork AI Studio/Settings/SettingsMigrations.cs @@ -23,7 +23,8 @@ public static class SettingsMigrations configV1 = MigrateV1ToV2(logger, configV1); configV1 = MigrateV2ToV3(logger, configV1); - return MigrateV3ToV4(logger, configV1); + var configV14 = MigrateV3ToV4(logger, configV1); + return MigrateV4ToV5(logger, configV14); case Version.V2: var configV2 = JsonSerializer.Deserialize(configData, jsonOptions); @@ -34,7 +35,8 @@ public static class SettingsMigrations } configV2 = MigrateV2ToV3(logger, configV2); - return MigrateV3ToV4(logger, configV2); + var configV24 = MigrateV3ToV4(logger, configV2); + return MigrateV4ToV5(logger, configV24); case Version.V3: var configV3 = JsonSerializer.Deserialize(configData, jsonOptions); @@ -44,18 +46,29 @@ public static class SettingsMigrations return new(); } - return MigrateV3ToV4(logger, configV3); - - default: - logger.LogInformation("No configuration migration is needed."); - var configV4 = JsonSerializer.Deserialize(configData, jsonOptions); + var configV34 = MigrateV3ToV4(logger, configV3); + return MigrateV4ToV5(logger, configV34); + + case Version.V4: + var configV4 = JsonSerializer.Deserialize(configData, jsonOptions); if (configV4 is null) { logger.LogError("Failed to parse the v4 configuration. Using default values."); return new(); } - return configV4; + return MigrateV4ToV5(logger, configV4); + + default: + logger.LogInformation("No configuration migration is needed."); + var configV5 = JsonSerializer.Deserialize(configData, jsonOptions); + if (configV5 is null) + { + logger.LogError("Failed to parse the v4 configuration. Using default values."); + return new(); + } + + return configV5; } } @@ -110,7 +123,7 @@ public static class SettingsMigrations }; } - private static Data MigrateV3ToV4(ILogger logger, DataV1V3 previousConfig) + private static DataV4 MigrateV3ToV4(ILogger logger, DataV1V3 previousConfig) { // // Summary: @@ -194,4 +207,38 @@ public static class SettingsMigrations }, }; } + + private static Data MigrateV4ToV5(ILogger logger, DataV4 previousConfig) + { + // + // Summary: + // We renamed the LLM provider enum. + // + + logger.LogInformation("Migrating from v4 to v5..."); + return new() + { + Version = Version.V5, + Providers = previousConfig.Providers.MigrateFromV4ToV5(), + LLMProviders = previousConfig.LLMProviders, + Profiles = previousConfig.Profiles, + NextProviderNum = previousConfig.NextProviderNum, + NextProfileNum = previousConfig.NextProfileNum, + App = previousConfig.App, + Chat = previousConfig.Chat, + Workspace = previousConfig.Workspace, + IconFinder = previousConfig.IconFinder, + Translation = previousConfig.Translation, + Coding = previousConfig.Coding, + TextSummarizer = previousConfig.TextSummarizer, + TextContentCleaner = previousConfig.TextContentCleaner, + Agenda = previousConfig.Agenda, + GrammarSpelling = previousConfig.GrammarSpelling, + RewriteImprove = previousConfig.RewriteImprove, + EMail = previousConfig.EMail, + LegalCheck = previousConfig.LegalCheck, + Synonyms = previousConfig.Synonyms, + MyTasks = previousConfig.MyTasks, + }; + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/Version.cs b/app/MindWork AI Studio/Settings/Version.cs index 2b38b8f..dc6f99d 100644 --- a/app/MindWork AI Studio/Settings/Version.cs +++ b/app/MindWork AI Studio/Settings/Version.cs @@ -12,4 +12,5 @@ public enum Version V2, V3, V4, + V5, } \ No newline at end of file diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.11.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.11.md index 4c8c68a..b9dd0a2 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.9.11.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.11.md @@ -1,3 +1,4 @@ # v0.9.11, build 186 - Added a tooltip to the confidence card button. +- Added an option to enforce a minimum confidence level throughout the entire app. - Renamed the `Providers` enum to `LLMProviders` for better clarity. Renamed also all dependent variables and methods. \ No newline at end of file