From 10edb1ec54b1c73d56bb025060b1d4a9497da703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Sch=C3=BCtt?= <20603780+peerschuett@users.noreply.github.com> Date: Fri, 23 May 2025 15:32:20 +0200 Subject: [PATCH] Changes based on code review, changed the profile tooltip, added translation option for chat roles, and added the option to preselect a chat template for chats --- .../Assistants/AssistantBase.razor.cs | 2 ++ app/MindWork AI Studio/Chat/ChatRole.cs | 20 +++++++++++-------- .../Components/ChatComponent.razor | 2 +- .../Components/ChatComponent.razor.cs | 15 ++------------ .../Components/ProfileSelection.razor | 4 ++-- .../Components/ProfileSelection.razor.cs | 11 +++++++++- .../Settings/SettingsPanelChat.razor | 1 + .../SettingsPanelChatTemplates.razor.cs | 2 -- .../Dialogs/ChatTemplateDialog.razor | 12 +++++------ .../Dialogs/ChatTemplateDialog.razor.cs | 12 ----------- .../Settings/ChatTemplate.cs | 11 +--------- .../ConfigurationSelectDataFactory.cs | 6 ++++++ .../Settings/DataModel/DataApp.cs | 6 ++++++ .../Settings/DataModel/DataChat.cs | 5 +++++ .../Settings/SettingsManager.cs | 10 ++++++++++ .../Tools/ComponentsExtensions.cs | 8 +++++++- 16 files changed, 71 insertions(+), 56 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs index 7abc5824..723ae02a 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs @@ -89,6 +89,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher protected MudForm? form; protected bool inputIsValid; protected Profile currentProfile = Profile.NO_PROFILE; + protected ChatTemplate currentChatTemplate = ChatTemplate.NO_CHATTEMPLATE; protected ChatThread? chatThread; protected IContent? lastUserPrompt; protected CancellationTokenSource? cancellationTokenSource; @@ -115,6 +116,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher this.MightPreselectValues(); this.providerSettings = this.SettingsManager.GetPreselectedProvider(this.Component); this.currentProfile = this.SettingsManager.GetPreselectedProfile(this.Component); + this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component); } protected override async Task OnParametersSetAsync() diff --git a/app/MindWork AI Studio/Chat/ChatRole.cs b/app/MindWork AI Studio/Chat/ChatRole.cs index 3b6db234..d292b71b 100644 --- a/app/MindWork AI Studio/Chat/ChatRole.cs +++ b/app/MindWork AI Studio/Chat/ChatRole.cs @@ -1,3 +1,5 @@ +using AIStudio.Tools.PluginSystem; + namespace AIStudio.Chat; /// @@ -19,6 +21,8 @@ public enum ChatRole /// public static class ExtensionsChatRole { + private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ChatRole).Namespace, nameof(ChatRole)); + /// /// Returns the name of the role. /// @@ -26,11 +30,11 @@ public static class ExtensionsChatRole /// The name of the role. public static string ToName(this ChatRole role) => role switch { - ChatRole.SYSTEM => "System", - ChatRole.USER => "You", - ChatRole.AI => "AI", + ChatRole.SYSTEM => TB("System"), + ChatRole.USER => TB("You"), + ChatRole.AI => TB("AI"), - _ => "Unknown", + _ => TB("Unknown"), }; /// @@ -68,10 +72,10 @@ public static class ExtensionsChatRole /// The name of the role. public static string ToChatTemplateName(this ChatRole role) => role switch { - ChatRole.SYSTEM => "System", - ChatRole.USER => "User", - ChatRole.AI => "Assistant", + ChatRole.SYSTEM => TB("System"), + ChatRole.USER => TB("User"), + ChatRole.AI => TB("Assistant"), - _ => "Unknown", + _ => TB("Unknown"), }; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor b/app/MindWork AI Studio/Components/ChatComponent.razor index 7df154f1..9c6e387e 100644 --- a/app/MindWork AI Studio/Components/ChatComponent.razor +++ b/app/MindWork AI Studio/Components/ChatComponent.razor @@ -112,7 +112,7 @@ } - + @if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager)) { diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor.cs b/app/MindWork AI Studio/Components/ChatComponent.razor.cs index a6a156d3..8d12159b 100644 --- a/app/MindWork AI Studio/Components/ChatComponent.razor.cs +++ b/app/MindWork AI Studio/Components/ChatComponent.razor.cs @@ -60,8 +60,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable private string currentWorkspaceName = string.Empty; private Guid currentWorkspaceId = Guid.Empty; private CancellationTokenSource? cancellationTokenSource; - private bool disableProfile = false; // TODO - + // Unfortunately, we need the input field reference to blur the focus away. Without // this, we cannot clear the input field. private MudTextField inputField = null!; @@ -80,7 +79,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable this.currentProfile = this.SettingsManager.GetPreselectedProfile(Tools.Components.CHAT); // Get the preselected chat template: - // this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(Tools.Components.CHAT); // TODO + this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(Tools.Components.CHAT); // // Check for deferred messages of the kind 'SEND_TO_CHAT', @@ -329,18 +328,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable private async Task ChatTemplateWasChanged(ChatTemplate chatTemplate) { this.currentChatTemplate = chatTemplate; - this.disableProfile = !chatTemplate.AllowProfileUsage; if(this.ChatThread is null) return; - this.ChatThread = this.ChatThread with - { - SelectedChatTemplate = this.currentChatTemplate.Id, - Blocks = this.currentChatTemplate.AdditionalMessages.Select(x => x.DeepClone()).ToList(), - }; - - // await this.ChatThreadChanged.InvokeAsync(this.ChatThread); - await this.StartNewChat(true, false); } @@ -817,7 +807,6 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable this.currentChatTemplate = this.SettingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == chatChatTemplate); if(this.currentChatTemplate == default) this.currentChatTemplate = ChatTemplate.NO_CHATTEMPLATE; - this.disableProfile = !this.currentChatTemplate.AllowProfileUsage; } } diff --git a/app/MindWork AI Studio/Components/ProfileSelection.razor b/app/MindWork AI Studio/Components/ProfileSelection.razor index 2c355ff7..9a1e603b 100644 --- a/app/MindWork AI Studio/Components/ProfileSelection.razor +++ b/app/MindWork AI Studio/Components/ProfileSelection.razor @@ -1,6 +1,6 @@ @inherits MSGComponentBase - - + + @foreach (var profile in this.SettingsManager.ConfigurationData.Profiles.GetAllProfiles()) { diff --git a/app/MindWork AI Studio/Components/ProfileSelection.razor.cs b/app/MindWork AI Studio/Components/ProfileSelection.razor.cs index d72873dd..649e2140 100644 --- a/app/MindWork AI Studio/Components/ProfileSelection.razor.cs +++ b/app/MindWork AI Studio/Components/ProfileSelection.razor.cs @@ -1,11 +1,13 @@ using AIStudio.Settings; - +using AIStudio.Tools.PluginSystem; using Microsoft.AspNetCore.Components; namespace AIStudio.Components; public partial class ProfileSelection : MSGComponentBase { + private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ConfigurationProviderSelection).Namespace, nameof(ConfigurationProviderSelection)); + [Parameter] public Profile CurrentProfile { get; set; } = Profile.NO_PROFILE; @@ -21,6 +23,13 @@ public partial class ProfileSelection : MSGComponentBase [Parameter] public bool Disabled { get; set; } + [Parameter] + public string DisabledText { get; set; } = string.Empty; + + private readonly string defaultToolTipText = TB("You can switch between your profiles here"); + + private string ToolTipText => this.Disabled ? this.DisabledText : this.defaultToolTipText; + private string MarginClass => $"{this.MarginLeft} {this.MarginRight}"; private async Task SelectionChanged(Profile profile) diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelChat.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelChat.razor index 84b34e6a..ddb96cb3 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelChat.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelChat.razor @@ -12,6 +12,7 @@ + @if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager)) diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelChatTemplates.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelChatTemplates.razor.cs index 409111f7..4a293a78 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelChatTemplates.razor.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelChatTemplates.razor.cs @@ -30,14 +30,12 @@ public partial class SettingsPanelChatTemplates : SettingsPanelBase private async Task EditChatTemplate(ChatTemplate chatTemplate) { - // TODO: additionall messages übergeben var dialogParameters = new DialogParameters { { x => x.DataNum, chatTemplate.Num }, { x => x.DataId, chatTemplate.Id }, { x => x.DataName, chatTemplate.Name }, { x => x.DataSystemPrompt, chatTemplate.SystemPrompt }, - // { x => x.DataActions, chatTemplate.Actions }, { x => x.IsEditing, true }, {x => x.AdditionalMessages, chatTemplate.AdditionalMessages}, }; diff --git a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor index 30ee2955..05d4f6a8 100644 --- a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor +++ b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor @@ -66,16 +66,16 @@ @T("Add messages of an example conversation (user prompt followed by assistant prompt) to demonstrate the desired interaction pattern. These examples help the AI understand your expectations by showing it the correct format, style, and content of responses before it receives actual user inputs.") - + - Role - Entry - Actions + @T("Role") + @T("Entry") + @T("Actions") @context.Role.ToChatTemplateName() @@ -97,11 +97,11 @@ - + - + diff --git a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs index 56069cd5..47398fbe 100644 --- a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs @@ -81,7 +81,6 @@ public partial class ChatTemplateDialog : MSGComponentBase private void RemoveMessage(ContentBlock item) { this.AdditionalMessages.Remove(item); - // this.Snackbar.Add("Entry removed", Severity.Info); } private void AddNewMessageToEnd() @@ -96,7 +95,6 @@ public partial class ChatTemplateDialog : MSGComponentBase }; this.AdditionalMessages.Add(newEntry); - // this.Snackbar.Add("Initial entry added", Severity.Success); } private void AddNewMessageBelow(ContentBlock currentItem) @@ -118,12 +116,10 @@ public partial class ChatTemplateDialog : MSGComponentBase if (index >= 0) { this.AdditionalMessages.Insert(index + 1, newEntry); - // this.Snackbar.Add("New entry added", Severity.Success); } else { this.AdditionalMessages.Add(newEntry); - // this.Snackbar.Add("New entry added", Severity.Success); } } @@ -136,11 +132,6 @@ public partial class ChatTemplateDialog : MSGComponentBase }; } - private void ItemHasBeenCommitted(object element) - { - // this.Snackbar.Add("Changes saved", Severity.Success); - } - private void ResetItemToOriginalValues(object element) { ((ContentBlock)element).Role = this.messageEntryBeforeEdit.Role; @@ -200,9 +191,6 @@ public partial class ChatTemplateDialog : MSGComponentBase private string? ValidateSystemPrompt(string text) { - // if (string.IsNullOrWhiteSpace(this.DataSystemPrompt))// && string.IsNullOrWhiteSpace(this.DataActions)) - // return T("Please enter the system prompt."); - if(text.Length > 444) return T("The text must not exceed 444 characters."); diff --git a/app/MindWork AI Studio/Settings/ChatTemplate.cs b/app/MindWork AI Studio/Settings/ChatTemplate.cs index 4484b338..b56ca8e9 100644 --- a/app/MindWork AI Studio/Settings/ChatTemplate.cs +++ b/app/MindWork AI Studio/Settings/ChatTemplate.cs @@ -32,16 +32,7 @@ public readonly record struct ChatTemplate(uint Num, string Id, string Name, str if(this.Num == uint.MaxValue) return string.Empty; - var systemPrompt = - $""" - ``` - {this.SystemPrompt} - ``` - """; - - return $""" - {systemPrompt} - """; + return this.SystemPrompt; } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/ConfigurationSelectDataFactory.cs b/app/MindWork AI Studio/Settings/ConfigurationSelectDataFactory.cs index 9d066a7a..8b7d7366 100644 --- a/app/MindWork AI Studio/Settings/ConfigurationSelectDataFactory.cs +++ b/app/MindWork AI Studio/Settings/ConfigurationSelectDataFactory.cs @@ -198,6 +198,12 @@ public static class ConfigurationSelectDataFactory yield return new(profile.Name, profile.Id); } + public static IEnumerable> GetChatTemplatesData(IEnumerable chatTemplates) + { + foreach (var chatTemplate in chatTemplates.GetAllChatTemplates()) + yield return new(chatTemplate.Name, chatTemplate.Id); + } + public static IEnumerable> GetConfidenceSchemesData() { foreach (var scheme in Enum.GetValues()) diff --git a/app/MindWork AI Studio/Settings/DataModel/DataApp.cs b/app/MindWork AI Studio/Settings/DataModel/DataApp.cs index af76fa26..e189cbbd 100644 --- a/app/MindWork AI Studio/Settings/DataModel/DataApp.cs +++ b/app/MindWork AI Studio/Settings/DataModel/DataApp.cs @@ -57,4 +57,10 @@ public sealed class DataApp /// Should we preselect a profile for the entire app? /// public string PreselectedProfile { get; set; } = string.Empty; + + + /// + /// Should we preselect a chat template for the entire app? + /// + public string PreselectedChatTemplate { get; set; } = string.Empty; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataChat.cs b/app/MindWork AI Studio/Settings/DataModel/DataChat.cs index baf995fd..147bb7ac 100644 --- a/app/MindWork AI Studio/Settings/DataModel/DataChat.cs +++ b/app/MindWork AI Studio/Settings/DataModel/DataChat.cs @@ -37,6 +37,11 @@ public sealed class DataChat /// public string PreselectedProfile { get; set; } = string.Empty; + /// + /// Preselect a chat template? + /// + public string PreselectedChatTemplate { get; set; } = string.Empty; + /// /// Should we preselect data sources options for a created chat? /// diff --git a/app/MindWork AI Studio/Settings/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs index e34be596..e10e37bb 100644 --- a/app/MindWork AI Studio/Settings/SettingsManager.cs +++ b/app/MindWork AI Studio/Settings/SettingsManager.cs @@ -265,6 +265,16 @@ public sealed class SettingsManager preselection = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.App.PreselectedProfile); return preselection != default ? preselection : Profile.NO_PROFILE; } + + public ChatTemplate GetPreselectedChatTemplate(Tools.Components component) + { + var preselection = component.PreselectedChatTemplate(this); + if (preselection != default) + return preselection; + + preselection = this.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == this.ConfigurationData.App.PreselectedChatTemplate); + return preselection != default ? preselection : ChatTemplate.NO_CHATTEMPLATE; + } public ConfidenceLevel GetConfiguredConfidenceLevel(LLMProviders llmProvider) { diff --git a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs index f7e929c5..e4bd317c 100644 --- a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs +++ b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs @@ -1,5 +1,4 @@ using System.Diagnostics.CodeAnalysis; - using AIStudio.Provider; using AIStudio.Settings; using AIStudio.Tools.PluginSystem; @@ -131,4 +130,11 @@ public static class ComponentsExtensions _ => default, }; + + public static ChatTemplate PreselectedChatTemplate(this Components component, SettingsManager settingsManager) => component switch + { + Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Chat.PreselectedChatTemplate) : default, + + _ => default, + }; } \ No newline at end of file