diff --git a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor index c20f3ae8..89446fbc 100644 --- a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor +++ b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor @@ -1,4 +1,5 @@ @attribute [Route(Routes.ASSISTANT_ERI)] +@using AIStudio.Settings.DataModel @using MudExtensions @inherits AssistantBaseCore @@ -21,7 +22,50 @@
- Auto Save + ERI server presets + + + + Here you have the option to save different configurations for various ERI servers and switch between them. This is useful if + you are responsible for multiple ERI servers. + + +@if(this.SettingsManager.ConfigurationData.ERI.ERIServers.Count is 0) +{ + + You have not yet added any ERI server presets. + +} +else +{ + + @foreach (var server in this.SettingsManager.ConfigurationData.ERI.ERIServers) + { + + @server.ServerName + + } + +} + + + + Add ERI server preset + + + Delete this server preset + + + +@if(this.AreServerPresetsBlocked) +{ + + Hint: to allow this assistant to manage multiple presets, you must enable the preselection of values in the settings. + +} + + + Auto save @@ -30,23 +74,25 @@ automatically saved. Would you like this? -@if(!this.SettingsManager.ConfigurationData.ERI.PreselectOptions) +@if(this.AreServerPresetsBlocked) { Hint: to allow this assistant to automatically save your changes, you must enable the preselection of values in the settings. } - + + +
Common ERI server settings - - + + - + @foreach (var language in Enum.GetValues()) { @language.Name() @@ -54,18 +100,18 @@ @if (this.selectedProgrammingLanguage is ProgrammingLanguages.OTHER) { - + } - + @foreach (var version in Enum.GetValues()) { @version } - + Download specification @@ -75,7 +121,7 @@ - + @foreach (var dataSource in Enum.GetValues()) { @dataSource.Name() @@ -83,21 +129,21 @@ @if (this.selectedDataSource is DataSources.CUSTOM) { - + } @if(this.selectedDataSource > DataSources.FILE_SYSTEM) { - + } @if (this.NeedHostnamePort()) {
- - + + @if (this.dataSourcePort < 1024) { @@ -115,6 +161,7 @@ @authMethod.Name() } - + @if (this.selectedAuthenticationMethods.Contains(Auth.KERBEROS)) { - + @foreach (var os in Enum.GetValues()) { @os.Name() @@ -146,7 +193,7 @@ Data protection settings - + @foreach (var option in Enum.GetValues()) { @option.Name() @@ -170,37 +217,40 @@ or data types. For example, one embedding for texts, another for images, and a third for videos, etc. - - - - - - - - Name - Type - Actions - - - @context.EmbeddingName - @context.EmbeddingType - - - Edit - - - Delete - - - - - -@if(this.embeddings.Count == 0) +@if (!this.IsNoneERIServerSelected) { - No embedding methods configured yet. + + + + + + + + Name + Type + Actions + + + @context.EmbeddingName + @context.EmbeddingType + + + Edit + + + Delete + + + + + + @if (this.embeddings.Count == 0) + { + No embedding methods configured yet. + } } - + Add Embedding Method @@ -215,34 +265,37 @@ the process that best suits their circumstances. - - - - - - - Name - Actions - - - @context.Name - - - Edit - - - Delete - - - - - -@if(this.retrievalProcesses.Count == 0) +@if (!this.IsNoneERIServerSelected) { - No retrieval process configured yet. + + + + + + + Name + Actions + + + @context.Name + + + Edit + + + Delete + + + + + + @if (this.retrievalProcesses.Count == 0) + { + No retrieval process configured yet. + } } - + Add Retrieval Process @@ -254,7 +307,7 @@ the intended use. The LLM can then attempt to choose suitable libraries. However, hallucinations can occur, and fictional libraries might be selected. - + Provider selection for generation diff --git a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor.cs b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor.cs index 312a63b5..a6036c29 100644 --- a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor.cs +++ b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor.cs @@ -1,5 +1,6 @@ using AIStudio.Chat; using AIStudio.Dialogs; +using AIStudio.Settings.DataModel; using Microsoft.AspNetCore.Components; @@ -38,7 +39,9 @@ public partial class AssistantERI : AssistantBaseCore protected override string SubmitText => "Create the ERI server"; protected override Func SubmitAction => this.GenerateServer; - + + protected override bool SubmitDisabled => this.IsNoneERIServerSelected; + protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with { SystemPrompt = SystemPrompts.DEFAULT, @@ -72,29 +75,29 @@ public partial class AssistantERI : AssistantBaseCore protected override bool MightPreselectValues() { this.autoSave = this.SettingsManager.ConfigurationData.ERI.AutoSaveChanges; - if (this.SettingsManager.ConfigurationData.ERI.PreselectOptions) + if (this.SettingsManager.ConfigurationData.ERI.PreselectOptions && this.selectedERIServer is not null) { - this.serverName = this.SettingsManager.ConfigurationData.ERI.PreselectedServerName; - this.serverDescription = this.SettingsManager.ConfigurationData.ERI.PreselectedServerDescription; - this.selectedERIVersion = this.SettingsManager.ConfigurationData.ERI.PreselectedERIVersion; - this.selectedProgrammingLanguage = this.SettingsManager.ConfigurationData.ERI.PreselectedProgrammingLanguage; - this.otherProgrammingLanguage = this.SettingsManager.ConfigurationData.ERI.PreselectedOtherProgrammingLanguage; - this.selectedDataSource = this.SettingsManager.ConfigurationData.ERI.PreselectedDataSource; - this.dataSourceProductName = this.SettingsManager.ConfigurationData.ERI.PreselectedDataSourceProductName; - this.otherDataSource = this.SettingsManager.ConfigurationData.ERI.PreselectedOtherDataSource; - this.dataSourceHostname = this.SettingsManager.ConfigurationData.ERI.PreselectedDataSourceHostname; - this.dataSourcePort = this.SettingsManager.ConfigurationData.ERI.PreselectedDataSourcePort; - this.userTypedPort = this.SettingsManager.ConfigurationData.ERI.UserTypedPort; + this.serverName = this.selectedERIServer.ServerName; + this.serverDescription = this.selectedERIServer.ServerDescription; + this.selectedERIVersion = this.selectedERIServer.ERIVersion; + this.selectedProgrammingLanguage = this.selectedERIServer.ProgrammingLanguage; + this.otherProgrammingLanguage = this.selectedERIServer.OtherProgrammingLanguage; + this.selectedDataSource = this.selectedERIServer.DataSource; + this.dataSourceProductName = this.selectedERIServer.DataSourceProductName; + this.otherDataSource = this.selectedERIServer.OtherDataSource; + this.dataSourceHostname = this.selectedERIServer.DataSourceHostname; + this.dataSourcePort = this.selectedERIServer.DataSourcePort; + this.userTypedPort = this.selectedERIServer.UserTypedPort; - var authMethods = new HashSet(this.SettingsManager.ConfigurationData.ERI.PreselectedAuthMethods); + var authMethods = new HashSet(this.selectedERIServer.AuthMethods); this.selectedAuthenticationMethods = authMethods; - this.authDescription = this.SettingsManager.ConfigurationData.ERI.PreselectedAuthDescription; - this.selectedOperatingSystem = this.SettingsManager.ConfigurationData.ERI.PreselectedOperatingSystem; - this.allowedLLMProviders = this.SettingsManager.ConfigurationData.ERI.PreselectedAllowedLLMProviders; - this.embeddings = this.SettingsManager.ConfigurationData.ERI.PreselectedEmbeddingInfos; - this.retrievalProcesses = this.SettingsManager.ConfigurationData.ERI.PreselectedRetrievalInfos; - this.additionalLibraries = this.SettingsManager.ConfigurationData.ERI.PreselectedAdditionalLibraries; + this.authDescription = this.selectedERIServer.AuthDescription; + this.selectedOperatingSystem = this.selectedERIServer.OperatingSystem; + this.allowedLLMProviders = this.selectedERIServer.AllowedLLMProviders; + this.embeddings = this.selectedERIServer.EmbeddingInfos; + this.retrievalProcesses = this.selectedERIServer.RetrievalInfos; + this.additionalLibraries = this.selectedERIServer.AdditionalLibraries; return true; } @@ -106,32 +109,52 @@ public partial class AssistantERI : AssistantBaseCore await this.AutoSave(); } + #region Overrides of AssistantBase + + protected override async Task OnInitializedAsync() + { + this.selectedERIServer = this.SettingsManager.ConfigurationData.ERI.ERIServers.FirstOrDefault(); + if(this.selectedERIServer is null) + { + await this.AddERIServer(); + this.selectedERIServer = this.SettingsManager.ConfigurationData.ERI.ERIServers.First(); + } + + await base.OnInitializedAsync(); + } + + #endregion + private async Task AutoSave() { if(!this.autoSave || !this.SettingsManager.ConfigurationData.ERI.PreselectOptions) return; - this.SettingsManager.ConfigurationData.ERI.PreselectedServerName = this.serverName; - this.SettingsManager.ConfigurationData.ERI.PreselectedServerDescription = this.serverDescription; - this.SettingsManager.ConfigurationData.ERI.PreselectedERIVersion = this.selectedERIVersion; - this.SettingsManager.ConfigurationData.ERI.PreselectedProgrammingLanguage = this.selectedProgrammingLanguage; - this.SettingsManager.ConfigurationData.ERI.PreselectedOtherProgrammingLanguage = this.otherProgrammingLanguage; - this.SettingsManager.ConfigurationData.ERI.PreselectedDataSource = this.selectedDataSource; - this.SettingsManager.ConfigurationData.ERI.PreselectedDataSourceProductName = this.dataSourceProductName; - this.SettingsManager.ConfigurationData.ERI.PreselectedOtherDataSource = this.otherDataSource; - this.SettingsManager.ConfigurationData.ERI.PreselectedDataSourceHostname = this.dataSourceHostname; - this.SettingsManager.ConfigurationData.ERI.PreselectedDataSourcePort = this.dataSourcePort; - this.SettingsManager.ConfigurationData.ERI.UserTypedPort = this.userTypedPort; - this.SettingsManager.ConfigurationData.ERI.PreselectedAuthMethods = [..this.selectedAuthenticationMethods]; - this.SettingsManager.ConfigurationData.ERI.PreselectedAuthDescription = this.authDescription; - this.SettingsManager.ConfigurationData.ERI.PreselectedOperatingSystem = this.selectedOperatingSystem; - this.SettingsManager.ConfigurationData.ERI.PreselectedAllowedLLMProviders = this.allowedLLMProviders; - this.SettingsManager.ConfigurationData.ERI.PreselectedEmbeddingInfos = this.embeddings; - this.SettingsManager.ConfigurationData.ERI.PreselectedRetrievalInfos = this.retrievalProcesses; - this.SettingsManager.ConfigurationData.ERI.PreselectedAdditionalLibraries = this.additionalLibraries; + if(this.selectedERIServer is null) + return; + + this.selectedERIServer.ServerName = this.serverName; + this.selectedERIServer.ServerDescription = this.serverDescription; + this.selectedERIServer.ERIVersion = this.selectedERIVersion; + this.selectedERIServer.ProgrammingLanguage = this.selectedProgrammingLanguage; + this.selectedERIServer.OtherProgrammingLanguage = this.otherProgrammingLanguage; + this.selectedERIServer.DataSource = this.selectedDataSource; + this.selectedERIServer.DataSourceProductName = this.dataSourceProductName; + this.selectedERIServer.OtherDataSource = this.otherDataSource; + this.selectedERIServer.DataSourceHostname = this.dataSourceHostname; + this.selectedERIServer.DataSourcePort = this.dataSourcePort; + this.selectedERIServer.UserTypedPort = this.userTypedPort; + this.selectedERIServer.AuthMethods = [..this.selectedAuthenticationMethods]; + this.selectedERIServer.AuthDescription = this.authDescription; + this.selectedERIServer.OperatingSystem = this.selectedOperatingSystem; + this.selectedERIServer.AllowedLLMProviders = this.allowedLLMProviders; + this.selectedERIServer.EmbeddingInfos = this.embeddings; + this.selectedERIServer.RetrievalInfos = this.retrievalProcesses; + this.selectedERIServer.AdditionalLibraries = this.additionalLibraries; await this.SettingsManager.StoreSettings(); } - + + private DataERIServer? selectedERIServer; private bool autoSave; private string serverName = string.Empty; private string serverDescription = string.Empty; @@ -151,6 +174,54 @@ public partial class AssistantERI : AssistantBaseCore private List embeddings = new(); private List retrievalProcesses = new(); private string additionalLibraries = string.Empty; + + private bool AreServerPresetsBlocked => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions; + + private void SelectedERIServerChanged(DataERIServer? server) + { + this.selectedERIServer = server; + this.ResetForm(); + } + + private async Task AddERIServer() + { + this.SettingsManager.ConfigurationData.ERI.ERIServers.Add(new () + { + ServerName = $"ERI Server {DateTimeOffset.UtcNow}", + }); + + await this.SettingsManager.StoreSettings(); + } + + private async Task RemoveERIServer() + { + if(this.selectedERIServer is null) + return; + + this.SettingsManager.ConfigurationData.ERI.ERIServers.Remove(this.selectedERIServer); + this.selectedERIServer = null; + this.ResetForm(); + + await this.SettingsManager.StoreSettings(); + this.form?.ResetValidation(); + } + + private bool IsNoneERIServerSelected => this.selectedERIServer is null; + + /// + /// Gets called when the server name was changed by typing. + /// + /// + /// This method is used to update the server name in the selected ERI server preset. + /// Otherwise, the users would be confused when they change the server name and the changes are not reflected in the UI. + /// + private void ServerNameWasChanged() + { + if(this.selectedERIServer is null) + return; + + this.selectedERIServer.ServerName = this.serverName; + } private string? ValidateServerName(string name) { @@ -160,6 +231,9 @@ public partial class AssistantERI : AssistantBaseCore if(name.Length is > 60 or < 6) return "The name of your ERI server must be between 6 and 60 characters long."; + if(this.SettingsManager.ConfigurationData.ERI.ERIServers.Where(n => n != this.selectedERIServer).Any(n => n.ServerName == name)) + return "An ERI server preset with this name already exists. Please choose a different name."; + return null; } @@ -280,9 +354,12 @@ public partial class AssistantERI : AssistantBaseCore private void DataSourceWasChanged() { + if(this.selectedERIServer is null) + return; + if (this.selectedDataSource is DataSources.NONE) { - this.SettingsManager.ConfigurationData.ERI.PreselectedDataSourcePort = null; + this.selectedERIServer.DataSourcePort = null; this.dataSourcePort = null; this.userTypedPort = false; return; @@ -537,6 +614,9 @@ public partial class AssistantERI : AssistantBaseCore private async Task GenerateServer() { + if(this.IsNoneERIServerSelected) + return; + await this.AutoSave(); await this.form!.Validate(); if (!this.inputIsValid) diff --git a/app/MindWork AI Studio/Settings/DataModel/DataERI.cs b/app/MindWork AI Studio/Settings/DataModel/DataERI.cs index 4949ab14..20596a63 100644 --- a/app/MindWork AI Studio/Settings/DataModel/DataERI.cs +++ b/app/MindWork AI Studio/Settings/DataModel/DataERI.cs @@ -1,8 +1,5 @@ -using AIStudio.Assistants.ERI; using AIStudio.Provider; -using OperatingSystem = AIStudio.Assistants.ERI.OperatingSystem; - namespace AIStudio.Settings.DataModel; public sealed class DataERI @@ -18,94 +15,9 @@ public sealed class DataERI public bool PreselectOptions { get; set; } = true; /// - /// Preselect the server name? + /// Data for the ERI servers. /// - public string PreselectedServerName { get; set; } = string.Empty; - - /// - /// Preselect the server description? - /// - public string PreselectedServerDescription { get; set; } = string.Empty; - - /// - /// Preselect the ERI version? - /// - public ERIVersion PreselectedERIVersion { get; set; } = ERIVersion.NONE; - - /// - /// Preselect the language for implementing the ERI? - /// - public ProgrammingLanguages PreselectedProgrammingLanguage { get; set; } - - /// - /// Do you want to preselect any other language? - /// - public string PreselectedOtherProgrammingLanguage { get; set; } = string.Empty; - - /// - /// Preselect a data source? - /// - public DataSources PreselectedDataSource { get; set; } - - /// - /// Do you want to preselect a product name for the data source? - /// - public string PreselectedDataSourceProductName { get; set; } = string.Empty; - - /// - /// Do you want to preselect any other data source? - /// - public string PreselectedOtherDataSource { get; set; } = string.Empty; - - /// - /// Do you want to preselect a hostname for the data source? - /// - public string PreselectedDataSourceHostname { get; set; } = string.Empty; - - /// - /// Do you want to preselect a port for the data source? - /// - public int? PreselectedDataSourcePort { get; set; } - - /// - /// Did the user type the port number? - /// - public bool UserTypedPort { get; set; } = false; - - /// - /// Preselect any authentication methods? - /// - public HashSet PreselectedAuthMethods { get; set; } = []; - - /// - /// Do you want to preselect any authentication description? - /// - public string PreselectedAuthDescription { get; set; } = string.Empty; - - /// - /// Do you want to preselect an operating system? This is necessary when SSO with Kerberos is used. - /// - public OperatingSystem PreselectedOperatingSystem { get; set; } = OperatingSystem.NONE; - - /// - /// Do you want to preselect which LLM providers are allowed? - /// - public AllowedLLMProviders PreselectedAllowedLLMProviders { get; set; } = AllowedLLMProviders.NONE; - - /// - /// Do you want to predefine any embedding information? - /// - public List PreselectedEmbeddingInfos { get; set; } = new(); - - /// - /// Do you want to predefine any retrieval information? - /// - public List PreselectedRetrievalInfos { get; set; } = new(); - - /// - /// Do you want to preselect any additional libraries? - /// - public string PreselectedAdditionalLibraries { get; set; } = string.Empty; + public List ERIServers { get; set; } = new(); /// /// The minimum confidence level required for a provider to be considered. diff --git a/app/MindWork AI Studio/Settings/DataModel/DataERIServer.cs b/app/MindWork AI Studio/Settings/DataModel/DataERIServer.cs new file mode 100644 index 00000000..c6179df4 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataERIServer.cs @@ -0,0 +1,98 @@ +using AIStudio.Assistants.ERI; + +using OperatingSystem = AIStudio.Assistants.ERI.OperatingSystem; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataERIServer +{ + /// + /// Preselect the server name? + /// + public string ServerName { get; set; } = string.Empty; + + /// + /// Preselect the server description? + /// + public string ServerDescription { get; set; } = string.Empty; + + /// + /// Preselect the ERI version? + /// + public ERIVersion ERIVersion { get; set; } = ERIVersion.NONE; + + /// + /// Preselect the language for implementing the ERI? + /// + public ProgrammingLanguages ProgrammingLanguage { get; set; } + + /// + /// Do you want to preselect any other language? + /// + public string OtherProgrammingLanguage { get; set; } = string.Empty; + + /// + /// Preselect a data source? + /// + public DataSources DataSource { get; set; } + + /// + /// Do you want to preselect a product name for the data source? + /// + public string DataSourceProductName { get; set; } = string.Empty; + + /// + /// Do you want to preselect any other data source? + /// + public string OtherDataSource { get; set; } = string.Empty; + + /// + /// Do you want to preselect a hostname for the data source? + /// + public string DataSourceHostname { get; set; } = string.Empty; + + /// + /// Do you want to preselect a port for the data source? + /// + public int? DataSourcePort { get; set; } + + /// + /// Did the user type the port number? + /// + public bool UserTypedPort { get; set; } = false; + + /// + /// Preselect any authentication methods? + /// + public HashSet AuthMethods { get; set; } = []; + + /// + /// Do you want to preselect any authentication description? + /// + public string AuthDescription { get; set; } = string.Empty; + + /// + /// Do you want to preselect an operating system? This is necessary when SSO with Kerberos is used. + /// + public OperatingSystem OperatingSystem { get; set; } = OperatingSystem.NONE; + + /// + /// Do you want to preselect which LLM providers are allowed? + /// + public AllowedLLMProviders AllowedLLMProviders { get; set; } = AllowedLLMProviders.NONE; + + /// + /// Do you want to predefine any embedding information? + /// + public List EmbeddingInfos { get; set; } = new(); + + /// + /// Do you want to predefine any retrieval information? + /// + public List RetrievalInfos { get; set; } = new(); + + /// + /// Do you want to preselect any additional libraries? + /// + public string AdditionalLibraries { get; set; } = string.Empty; +} \ No newline at end of file