AI-Studio/app/MindWork AI Studio/Settings/SettingsManager.cs

217 lines
11 KiB
C#
Raw Normal View History

2024-04-19 19:19:13 +00:00
using System.Text.Json;
2024-07-28 19:18:17 +00:00
using System.Text.Json.Serialization;
2024-09-11 21:08:02 +00:00
using AIStudio.Provider;
using AIStudio.Settings.DataModel;
2024-04-19 19:19:13 +00:00
2024-04-20 15:06:50 +00:00
// ReSharper disable NotAccessedPositionalProperty.Local
2024-04-19 19:19:13 +00:00
namespace AIStudio.Settings;
2024-05-04 08:55:00 +00:00
/// <summary>
/// The settings manager.
/// </summary>
2024-09-01 18:10:03 +00:00
public sealed class SettingsManager(ILogger<SettingsManager> logger)
2024-04-19 19:19:13 +00:00
{
private const string SETTINGS_FILENAME = "settings.json";
2024-07-28 19:18:17 +00:00
private static readonly JsonSerializerOptions JSON_OPTIONS = new()
{
WriteIndented = true,
Converters = { new JsonStringEnumConverter() },
};
2024-09-01 18:10:03 +00:00
private ILogger<SettingsManager> logger = logger;
2024-07-28 19:18:17 +00:00
2024-05-04 08:55:00 +00:00
/// <summary>
/// The directory where the configuration files are stored.
/// </summary>
2024-04-19 19:19:13 +00:00
public static string? ConfigDirectory { get; set; }
2024-05-04 08:55:00 +00:00
/// <summary>
/// The directory where the data files are stored.
/// </summary>
2024-04-19 19:19:13 +00:00
public static string? DataDirectory { get; set; }
2024-05-04 08:55:00 +00:00
/// <summary>
/// The configuration data.
/// </summary>
2024-04-20 15:06:50 +00:00
public Data ConfigurationData { get; private set; } = new();
private bool IsSetUp => !string.IsNullOrWhiteSpace(ConfigDirectory) && !string.IsNullOrWhiteSpace(DataDirectory);
2024-05-04 08:55:00 +00:00
/// <summary>
/// Loads the settings from the file system.
/// </summary>
2024-04-20 15:06:50 +00:00
public async Task LoadSettings()
2024-04-19 19:19:13 +00:00
{
if(!this.IsSetUp)
2024-09-01 18:10:03 +00:00
{
this.logger.LogWarning("Cannot load settings, because the configuration is not set up yet.");
2024-04-20 15:06:50 +00:00
return;
2024-09-01 18:10:03 +00:00
}
2024-04-19 19:19:13 +00:00
var settingsPath = Path.Combine(ConfigDirectory!, SETTINGS_FILENAME);
if(!File.Exists(settingsPath))
2024-09-01 18:10:03 +00:00
{
this.logger.LogWarning("Cannot load settings, because the settings file does not exist.");
2024-04-20 15:06:50 +00:00
return;
2024-09-01 18:10:03 +00:00
}
2024-08-05 19:12:52 +00:00
// We read the `"Version": "V3"` line to determine the version of the settings file:
await foreach (var line in File.ReadLinesAsync(settingsPath))
{
if (!line.Contains("""
"Version":
"""))
continue;
// Extract the version from the line:
var settingsVersionText = line.Split('"')[3];
// Parse the version:
Enum.TryParse(settingsVersionText, out Version settingsVersion);
if(settingsVersion is Version.UNKNOWN)
{
2024-09-01 18:10:03 +00:00
this.logger.LogError("Unknown version of the settings file found.");
2024-08-05 19:12:52 +00:00
this.ConfigurationData = new();
return;
}
2024-09-01 18:10:03 +00:00
this.ConfigurationData = SettingsMigrations.Migrate(this.logger, settingsVersion, await File.ReadAllTextAsync(settingsPath), JSON_OPTIONS);
2024-04-20 15:06:50 +00:00
return;
2024-08-05 19:12:52 +00:00
}
2024-04-20 15:06:50 +00:00
2024-09-01 18:10:03 +00:00
this.logger.LogError("Failed to read the version of the settings file.");
2024-08-05 19:12:52 +00:00
this.ConfigurationData = new();
2024-04-19 19:19:13 +00:00
}
2024-04-20 15:06:50 +00:00
2024-05-04 08:55:00 +00:00
/// <summary>
/// Stores the settings to the file system.
/// </summary>
2024-04-20 15:06:50 +00:00
public async Task StoreSettings()
2024-04-19 19:19:13 +00:00
{
if(!this.IsSetUp)
2024-09-01 18:10:03 +00:00
{
this.logger.LogWarning("Cannot store settings, because the configuration is not set up yet.");
2024-04-19 19:19:13 +00:00
return;
2024-09-01 18:10:03 +00:00
}
2024-04-19 19:19:13 +00:00
var settingsPath = Path.Combine(ConfigDirectory!, SETTINGS_FILENAME);
2024-04-20 15:06:50 +00:00
if(!Directory.Exists(ConfigDirectory))
2024-09-01 18:10:03 +00:00
{
this.logger.LogInformation("Creating the configuration directory.");
2024-04-20 15:06:50 +00:00
Directory.CreateDirectory(ConfigDirectory!);
2024-09-01 18:10:03 +00:00
}
2024-07-28 19:18:17 +00:00
var settingsJson = JsonSerializer.Serialize(this.ConfigurationData, JSON_OPTIONS);
2024-04-19 19:19:13 +00:00
await File.WriteAllTextAsync(settingsPath, settingsJson);
2024-09-01 18:10:03 +00:00
this.logger.LogInformation("Stored the settings to the file system.");
2024-04-19 19:19:13 +00:00
}
2024-06-01 17:55:12 +00:00
2024-08-05 19:12:52 +00:00
public void InjectSpellchecking(Dictionary<string, object?> attributes) => attributes["spellcheck"] = this.ConfigurationData.App.EnableSpellchecking ? "true" : "false";
2024-09-04 13:44:23 +00:00
public Provider GetPreselectedProvider(Tools.Components component)
{
if(this.ConfigurationData.Providers.Count == 1)
return this.ConfigurationData.Providers[0];
var preselection = component switch
{
Tools.Components.CHAT => this.ConfigurationData.Chat.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.Chat.PreselectedProvider) : default,
Tools.Components.GRAMMAR_SPELLING_ASSISTANT => this.ConfigurationData.GrammarSpelling.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.GrammarSpelling.PreselectedProvider) : default,
Tools.Components.ICON_FINDER_ASSISTANT => this.ConfigurationData.IconFinder.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.IconFinder.PreselectedProvider) : default,
Tools.Components.REWRITE_ASSISTANT => this.ConfigurationData.RewriteImprove.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.RewriteImprove.PreselectedProvider) : default,
Tools.Components.TRANSLATION_ASSISTANT => this.ConfigurationData.Translation.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.Translation.PreselectedProvider) : default,
Tools.Components.AGENDA_ASSISTANT => this.ConfigurationData.Agenda.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.Agenda.PreselectedProvider) : default,
Tools.Components.CODING_ASSISTANT => this.ConfigurationData.Coding.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.Coding.PreselectedProvider) : default,
Tools.Components.TEXT_SUMMARIZER_ASSISTANT => this.ConfigurationData.TextSummarizer.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.TextSummarizer.PreselectedProvider) : default,
Tools.Components.EMAIL_ASSISTANT => this.ConfigurationData.EMail.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.EMail.PreselectedProvider) : default,
Tools.Components.LEGAL_CHECK_ASSISTANT => this.ConfigurationData.LegalCheck.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.LegalCheck.PreselectedProvider) : default,
2024-09-06 20:02:20 +00:00
Tools.Components.SYNONYMS_ASSISTANT => this.ConfigurationData.Synonyms.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.Synonyms.PreselectedProvider) : default,
Tools.Components.MY_TASKS_ASSISTANT => this.ConfigurationData.MyTasks.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.MyTasks.PreselectedProvider) : default,
2024-09-04 13:44:23 +00:00
_ => default,
};
if (preselection != default)
return preselection;
return this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.App.PreselectedProvider);
}
2024-09-08 19:01:51 +00:00
public Profile GetPreselectedProfile(Tools.Components component)
{
var preselection = component switch
{
Tools.Components.CHAT => this.ConfigurationData.Chat.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.Chat.PreselectedProfile) : default,
Tools.Components.AGENDA_ASSISTANT => this.ConfigurationData.Agenda.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.Agenda.PreselectedProfile) : default,
Tools.Components.CODING_ASSISTANT => this.ConfigurationData.Coding.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.Coding.PreselectedProfile) : default,
Tools.Components.EMAIL_ASSISTANT => this.ConfigurationData.EMail.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.EMail.PreselectedProfile) : default,
Tools.Components.LEGAL_CHECK_ASSISTANT => this.ConfigurationData.LegalCheck.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.LegalCheck.PreselectedProfile) : default,
Tools.Components.MY_TASKS_ASSISTANT => this.ConfigurationData.MyTasks.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.MyTasks.PreselectedProfile) : default,
2024-09-08 19:01:51 +00:00
_ => default,
};
if (preselection != default)
return preselection;
preselection = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.App.PreselectedProfile);
return preselection != default ? preselection : Profile.NO_PROFILE;
}
2024-09-11 21:08:02 +00:00
public ConfidenceLevel GetConfiguredConfidenceLevel(Providers provider)
{
if(provider is Providers.NONE)
return ConfidenceLevel.NONE;
switch (this.ConfigurationData.LLMProviders.ConfidenceScheme)
{
case ConfidenceSchemes.TRUST_USA_EUROPE:
return provider switch
{
Providers.SELF_HOSTED => ConfidenceLevel.HIGH,
Providers.FIREWORKS => ConfidenceLevel.UNTRUSTED,
_ => ConfidenceLevel.MEDIUM,
};
case ConfidenceSchemes.TRUST_USA:
return provider switch
{
Providers.SELF_HOSTED => ConfidenceLevel.HIGH,
Providers.FIREWORKS => ConfidenceLevel.UNTRUSTED,
Providers.MISTRAL => ConfidenceLevel.LOW,
_ => ConfidenceLevel.MEDIUM,
};
case ConfidenceSchemes.TRUST_EUROPE:
return provider switch
{
Providers.SELF_HOSTED => ConfidenceLevel.HIGH,
Providers.FIREWORKS => ConfidenceLevel.UNTRUSTED,
Providers.MISTRAL => ConfidenceLevel.MEDIUM,
_ => ConfidenceLevel.LOW,
};
case ConfidenceSchemes.LOCAL_TRUST_ONLY:
return provider switch
{
Providers.SELF_HOSTED => ConfidenceLevel.HIGH,
Providers.FIREWORKS => ConfidenceLevel.UNTRUSTED,
_ => ConfidenceLevel.VERY_LOW,
};
case ConfidenceSchemes.CUSTOM:
return this.ConfigurationData.LLMProviders.CustomConfidenceScheme.GetValueOrDefault(provider, ConfidenceLevel.UNKNOWN);
default:
return ConfidenceLevel.UNKNOWN;
}
}
2024-04-19 19:19:13 +00:00
}