Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,13 @@ private void ApplyPolicyPreselection(bool preferPolicyPreselection = false)
}

// Try to apply the policy preselection:
if (Settings.Provider.IsNoProviderPreselection(this.selectedPolicy.PreselectedProvider))
{
this.ProviderSettings = Settings.Provider.NONE;
this.CurrentProfile = this.ResolveProfileSelection();
return;
}

var policyProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.selectedPolicy.PreselectedProvider);
if (policyProvider is not null && policyProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel)
{
Expand Down Expand Up @@ -763,7 +770,9 @@ private string GenerateLuaPolicyExport()
["MinimumProviderConfidence"] = "{{this.selectedPolicy.MinimumProviderConfidence}}",

-- Optional: preselect a provider or profile by ID.
-- The IDs must exist in CONFIG["LLM_PROVIDERS"] or CONFIG["PROFILES"].
-- Use an empty provider ID to fall back to the app default provider.
-- Use "{{Settings.Provider.NO_PROVIDER_PRESELECTION_ID}}" to explicitly preselect no provider.
-- Any other IDs must exist in CONFIG["LLM_PROVIDERS"] or CONFIG["PROFILES"].
["PreselectedProvider"] = "{{preselectedProvider}}",
["PreselectedProfile"] = "{{preselectedProfile}}",

Expand Down
3 changes: 3 additions & 0 deletions app/MindWork AI Studio/Assistants/I18N/allTexts.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2191,6 +2191,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T20906218
-- Use app default
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3672477670"] = "Use app default"

-- No provider
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3740605451"] = "No provider"

-- No shortcut configured
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONSHORTCUT::T3099115336"] = "No shortcut configured"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using AIStudio.Settings;
using AIStudio.Tools.PluginSystem;
using Microsoft.AspNetCore.Components;
using SettingsProvider = AIStudio.Settings.Provider;

namespace AIStudio.Components;

Expand Down Expand Up @@ -38,8 +39,11 @@ public partial class ConfigurationProviderSelection : MSGComponentBase
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private IEnumerable<ConfigurationSelectData<string>> FilteredData()
{
if(this.Component is not Tools.Components.NONE and not Tools.Components.APP_SETTINGS)
if(this.Component.SupportsAppDefaultProviderSelection())
{
yield return new(T("Use app default"), string.Empty);
yield return new(T("No provider"), SettingsProvider.NO_PROVIDER_PRESELECTION_ID);
}

// Get the minimum confidence level for this component, and/or the enforced global minimum confidence level:
var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(this.Component);
Expand Down Expand Up @@ -68,11 +72,11 @@ private IEnumerable<ConfigurationSelectData<string>> FilteredData()
{
case Event.CONFIGURATION_CHANGED:

if(string.IsNullOrWhiteSpace(this.SelectedValue()))
if(string.IsNullOrWhiteSpace(this.SelectedValue()) || SettingsProvider.IsNoProviderPreselection(this.SelectedValue()))
break;

// Check if the selected value is still valid:
if (this.Data.All(x => x.Value != this.SelectedValue()))
if (this.FilteredData().All(x => x.Value != this.SelectedValue()))
{
this.SelectedValue = () => string.Empty;
this.SelectionUpdate(string.Empty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2193,6 +2193,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T20906218
-- Use app default
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3672477670"] = "App-Standard verwenden"

-- No provider
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3740605451"] = "Kein Anbieter"

-- No shortcut configured
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONSHORTCUT::T3099115336"] = "Keinen Tastaturkurzbefehl konfiguriert"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2193,6 +2193,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T20906218
-- Use app default
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3672477670"] = "Use app default"

-- No provider
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3740605451"] = "No provider"

-- No shortcut configured
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONSHORTCUT::T3099115336"] = "No shortcut configured"

Expand Down
4 changes: 4 additions & 0 deletions app/MindWork AI Studio/Settings/Provider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public sealed record Provider(
{
private static readonly ILogger<Provider> LOGGER = Program.LOGGER_FACTORY.CreateLogger<Provider>();

public const string NO_PROVIDER_PRESELECTION_ID = "__NO_PROVIDER__";

public static readonly Provider NONE = new();

public Provider() : this(
Expand Down Expand Up @@ -66,6 +68,8 @@ public override string ToString()
}

#endregion

public static bool IsNoProviderPreselection(string? providerId) => providerId == NO_PROVIDER_PRESELECTION_ID;

#region Implementation of ISecretId

Expand Down
10 changes: 9 additions & 1 deletion app/MindWork AI Studio/Settings/SettingsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,10 @@ private static string GetPrimaryLanguage(string localeTag)
public Provider GetPreselectedProvider(Tools.Components component, string? currentProviderId = null, bool usePreselectionBeforeCurrentProvider = false)
{
var minimumLevel = this.GetMinimumConfidenceLevel(component);
var hasExplicitNoProviderPreselection = component.HasExplicitNoProviderPreselection(this);

// When there is only one provider, and it has a confidence level that is high enough, we return it:
if (this.ConfigurationData.Providers.Count == 1 && this.ConfigurationData.Providers[0].UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
if (!hasExplicitNoProviderPreselection && this.ConfigurationData.Providers.Count == 1 && this.ConfigurationData.Providers[0].UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
return this.ConfigurationData.Providers[0];

// Is there a current provider with a sufficiently high confidence level?
Expand Down Expand Up @@ -290,6 +291,9 @@ public Provider GetPreselectedProvider(Tools.Components component, string? curre
//
if(currentProvider != Provider.NONE)
return currentProvider;

if (hasExplicitNoProviderPreselection)
return Provider.NONE;

//
// Case: The current provider should be used before the preselected provider,
Expand All @@ -308,6 +312,7 @@ public Provider GetPreselectedProvider(Tools.Components component, string? curre
public Provider GetChatProviderForLoadedChat(string? chatProviderId = null)
{
var minimumLevel = this.GetMinimumConfidenceLevel(Tools.Components.CHAT);
var hasExplicitNoChatProviderPreselection = Tools.Components.CHAT.HasExplicitNoProviderPreselection(this);

bool IsSelectableProvider(Provider provider) =>
provider != Provider.NONE
Expand All @@ -333,6 +338,9 @@ bool IsSelectableProvider(Provider provider) =>
if (defaultChatProvider is not null)
return defaultChatProvider;

if (hasExplicitNoChatProviderPreselection)
return Provider.NONE;

var defaultAppProvider = FindProviderById(this.ConfigurationData.App.PreselectedProvider);
if (defaultAppProvider is not null)
return defaultAppProvider;
Expand Down
42 changes: 42 additions & 0 deletions app/MindWork AI Studio/Tools/ComponentsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ namespace AIStudio.Tools;
public static class ComponentsExtensions
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ComponentsExtensions).Namespace, nameof(ComponentsExtensions));

public static bool SupportsAppDefaultProviderSelection(this Components component) => component switch
{
Components.NONE => false,
Components.APP_SETTINGS => false,
Components.AGENT_TEXT_CONTENT_CLEANER => false,
Components.AGENT_DATA_SOURCE_SELECTION => false,
Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION => false,
Components.AGENT_ASSISTANT_PLUGIN_AUDIT => false,
_ => true,
};

public static bool AllowSendTo(this Components component) => component switch
{
Expand Down Expand Up @@ -103,9 +114,40 @@ public static class ComponentsExtensions
_ => default,
};

public static bool HasExplicitNoProviderPreselection(this Components component, SettingsManager settingsManager)
{
var preselectedProviderId = component switch
{
Components.GRAMMAR_SPELLING_ASSISTANT => settingsManager.ConfigurationData.GrammarSpelling.PreselectOptions ? settingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider : string.Empty,
Components.ICON_FINDER_ASSISTANT => settingsManager.ConfigurationData.IconFinder.PreselectOptions ? settingsManager.ConfigurationData.IconFinder.PreselectedProvider : string.Empty,
Components.REWRITE_ASSISTANT => settingsManager.ConfigurationData.RewriteImprove.PreselectOptions ? settingsManager.ConfigurationData.RewriteImprove.PreselectedProvider : string.Empty,
Components.PROMPT_OPTIMIZER_ASSISTANT => settingsManager.ConfigurationData.PromptOptimizer.PreselectOptions ? settingsManager.ConfigurationData.PromptOptimizer.PreselectedProvider : string.Empty,
Components.TRANSLATION_ASSISTANT => settingsManager.ConfigurationData.Translation.PreselectOptions ? settingsManager.ConfigurationData.Translation.PreselectedProvider : string.Empty,
Components.AGENDA_ASSISTANT => settingsManager.ConfigurationData.Agenda.PreselectOptions ? settingsManager.ConfigurationData.Agenda.PreselectedProvider : string.Empty,
Components.CODING_ASSISTANT => settingsManager.ConfigurationData.Coding.PreselectOptions ? settingsManager.ConfigurationData.Coding.PreselectedProvider : string.Empty,
Components.TEXT_SUMMARIZER_ASSISTANT => settingsManager.ConfigurationData.TextSummarizer.PreselectOptions ? settingsManager.ConfigurationData.TextSummarizer.PreselectedProvider : string.Empty,
Components.EMAIL_ASSISTANT => settingsManager.ConfigurationData.EMail.PreselectOptions ? settingsManager.ConfigurationData.EMail.PreselectedProvider : string.Empty,
Components.LEGAL_CHECK_ASSISTANT => settingsManager.ConfigurationData.LegalCheck.PreselectOptions ? settingsManager.ConfigurationData.LegalCheck.PreselectedProvider : string.Empty,
Components.SYNONYMS_ASSISTANT => settingsManager.ConfigurationData.Synonyms.PreselectOptions ? settingsManager.ConfigurationData.Synonyms.PreselectedProvider : string.Empty,
Components.MY_TASKS_ASSISTANT => settingsManager.ConfigurationData.MyTasks.PreselectOptions ? settingsManager.ConfigurationData.MyTasks.PreselectedProvider : string.Empty,
Components.JOB_POSTING_ASSISTANT => settingsManager.ConfigurationData.JobPostings.PreselectOptions ? settingsManager.ConfigurationData.JobPostings.PreselectedProvider : string.Empty,
Components.BIAS_DAY_ASSISTANT => settingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions ? settingsManager.ConfigurationData.BiasOfTheDay.PreselectedProvider : string.Empty,
Components.ERI_ASSISTANT => settingsManager.ConfigurationData.ERI.PreselectOptions ? settingsManager.ConfigurationData.ERI.PreselectedProvider : string.Empty,
Components.I18N_ASSISTANT => settingsManager.ConfigurationData.I18N.PreselectOptions ? settingsManager.ConfigurationData.I18N.PreselectedProvider : string.Empty,
Components.SLIDE_BUILDER_ASSISTANT => settingsManager.ConfigurationData.SlideBuilder.PreselectOptions ? settingsManager.ConfigurationData.SlideBuilder.PreselectedProvider : string.Empty,
Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.Chat.PreselectedProvider : string.Empty,
_ => string.Empty,
};

return Settings.Provider.IsNoProviderPreselection(preselectedProviderId);
}

[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
public static AIStudio.Settings.Provider PreselectedProvider(this Components component, SettingsManager settingsManager)
{
if (component.HasExplicitNoProviderPreselection(settingsManager))
return Settings.Provider.NONE;

var preselectedProvider = component switch
{
Components.GRAMMAR_SPELLING_ASSISTANT => settingsManager.ConfigurationData.GrammarSpelling.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider) : null,
Expand Down
1 change: 1 addition & 0 deletions app/MindWork AI Studio/wwwroot/changelog/v26.4.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Added pre-call validation to check if the selected model exists for the provider before making the request.
- Added math rendering in chats for LaTeX display formulas, including block formats such as `$$ ... $$` and `\[ ... \]`.
- Added support for mandatory information notices in configuration plugins. Organizations can now require users to read and confirm important information before continuing in AI Studio.
- Added "No provider" option in the internal settings of chat and assistants
- Released the document analysis assistant after an intense testing phase.
- Improved enterprise deployment for organizations: administrators can now provide up to 10 centrally managed enterprise configuration slots, use policy files on Linux and macOS, and continue using older configuration formats as a fallback during migration.
- Improved transparency on the information page by showing configured mandatory notices together with their source and confirmation status.
Expand Down