mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-04 20:27:21 +00:00
Added profile, provider, and workspace preselection to chat templates (#1099)
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
1 parent
ab9df99cf0
commit
24c4c31035
34 files changed
+2084
-142
No files matched your search
@@ -1,4 +1,5 @@
|
||||
@using AIStudio.Chat
|
||||
@using AIStudio.Settings
|
||||
@using AIStudio.Settings.DataModel
|
||||
@inherits MSGComponentBase
|
||||
|
||||
@@ -136,6 +137,73 @@
|
||||
@T("Using some chat templates in tandem with profiles might cause issues. Therefore, you might prohibit the usage of profiles here.")
|
||||
</MudJustifiedText>
|
||||
<MudTextSwitch @bind-Value="@this.AllowProfileUsage" Color="Color.Primary" Label="@T("Allow the use of profiles together with this chat template?")" LabelOn="@T("Yes, allow profiles when using this template")" LabelOff="@T("No, prohibit profile use for this template")" Disabled="@this.IsReadOnly" />
|
||||
@if (this.AllowProfileUsage)
|
||||
{
|
||||
<MudJustifiedText Class="mb-3 mt-3" Typo="Typo.body1">
|
||||
@T("A chat template may also decide which profile a chat starts with, including starting without one. Without such a decision, those chats start with the profile they would start with anyway. The profile stays changeable in the chat.")
|
||||
</MudJustifiedText>
|
||||
<MudTextSwitch @bind-Value="@this.preselectProfile" Color="Color.Primary" Label="@T("Does this chat template preselect a profile?")" LabelOn="@T("Yes, this template decides which profile a chat starts with")" LabelOff="@T("No, chats keep their usual profile")" Disabled="@this.IsReadOnly"/>
|
||||
@if (this.preselectProfile)
|
||||
{
|
||||
<MudSelect T="string" @bind-Value="@this.selectedProfileId" Label="@T("Preselected profile")" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3 mt-3 rounded-lg" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person" Disabled="@this.IsReadOnly">
|
||||
<MudSelectItem T="string" Value="@Profile.NO_PROFILE.Id">@T("Use no profile")</MudSelectItem>
|
||||
@foreach (var profile in this.SettingsManager.ConfigurationData.Profiles)
|
||||
{
|
||||
<MudSelectItem T="string" Value="@profile.Id">@profile.GetSafeName()</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.IsPreselectedProfileMissing)
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning" Class="mb-3">
|
||||
@T("The profile this chat template preselects does not exist on this computer. Chats started with it keep their usual profile.")
|
||||
</MudAlert>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<MudText Typo="Typo.h6" Class="mb-3 mt-6">
|
||||
@T("Provider")
|
||||
</MudText>
|
||||
<MudJustifiedText Class="mb-3" Typo="Typo.body1">
|
||||
@T("A chat template may decide which provider, and with it which model, a chat starts with. Without such a decision, those chats start with the provider they would start with anyway. The provider stays changeable in the chat, and it must meet the confidence level required for chats.")
|
||||
</MudJustifiedText>
|
||||
<MudTextSwitch @bind-Value="@this.preselectProvider" Color="Color.Primary" Label="@T("Does this chat template preselect a provider?")" LabelOn="@T("Yes, this template decides which provider a chat starts with")" LabelOff="@T("No, chats keep their usual provider")" Disabled="@this.IsReadOnly"/>
|
||||
@if (this.preselectProvider)
|
||||
{
|
||||
<MudSelect T="string" @bind-Value="@this.selectedProviderId" Label="@T("Preselected provider")" Validation="@this.ValidatePreselectedProvider" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3 mt-3 rounded-lg" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.SmartToy" Disabled="@this.IsReadOnly">
|
||||
@foreach (var provider in this.SettingsManager.GetConfidentProviders(Components.CHAT))
|
||||
{
|
||||
<MudSelectItem T="string" Value="@provider.Id">
|
||||
<ProviderLabel ProviderSettings="@provider" Text="@provider.InstanceName"/>
|
||||
</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.IsPreselectedProviderUnusable)
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning" Class="mb-3">
|
||||
@T("The provider this chat template preselects does not exist on this computer or does not meet the confidence level required for chats. Chats started with it keep their usual provider.")
|
||||
</MudAlert>
|
||||
}
|
||||
}
|
||||
|
||||
<MudText Typo="Typo.h6" Class="mb-3 mt-6">
|
||||
@T("Workspace")
|
||||
</MudText>
|
||||
<MudJustifiedText Class="mb-3" Typo="Typo.body1">
|
||||
@T("A chat template may keep its chats in a workspace of its own, which is created when it does not exist yet. This applies whenever a chat would otherwise be a disappearing chat, for example, when you start a new chat outside the workspaces or pick this template in a new chat. A chat you start in a workspace on purpose, for example, from the workspace list, stays in that workspace.")
|
||||
</MudJustifiedText>
|
||||
@* While workspaces are off, nothing goes into a workspace, so choosing one here would promise what no chat does: *@
|
||||
@if (this.AreWorkspacesDisabled)
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning" Class="mb-3">
|
||||
@T("Workspaces are switched off in your workspace settings. While they are off, chats with this template belong to no workspace, and they do not move into a workspace when you switch workspaces on again. You can change this choice once workspaces are on.")
|
||||
</MudAlert>
|
||||
}
|
||||
<MudTextSwitch @bind-Value="@this.preselectWorkspace" Color="Color.Primary" Label="@T("Does this chat template keep its chats in a workspace?")" LabelOn="@T("Yes, chats with this template go into a workspace")" LabelOff="@T("No, chats go where they would go anyway")" Disabled="@this.IsWorkspaceChoiceLocked"/>
|
||||
@if (this.preselectWorkspace)
|
||||
{
|
||||
<WorkspaceNameField @bind-WorkspaceName="@this.selectedWorkspaceName" SelectLabel="@T("Existing workspace (Optional)")" Label="@T("Workspace name")" HelperText="@T("Choose an existing workspace or enter a name that should be created when a chat with this template starts.")" Validation="@this.ValidateWorkspaceName" Immediate="@true" ReadOnly="@this.IsWorkspaceChoiceLocked" SelectClass="mb-3 mt-3 rounded-lg" TextFieldClass="mb-3 mt-3"/>
|
||||
}
|
||||
|
||||
<MudText Typo="Typo.h6" Class="mb-3 mt-6">
|
||||
@T("Tools")
|
||||
|
||||
@@ -79,6 +79,25 @@ public partial class ChatTemplateDialog : MSGComponentBase
|
||||
[Parameter]
|
||||
public DataSourceOptions? DataSourceOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The profile this template preselects, the ID of the no-profile entry to start without one,
|
||||
/// or null when it says nothing about profiles.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? ProfileId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The provider this template preselects, or null when it says nothing about providers.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? ProviderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the workspace this template keeps its chats in, or null when it says nothing about workspaces.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? WorkspaceName { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool CreateFromExistingChatThread { get; set; }
|
||||
|
||||
@@ -105,6 +124,12 @@ public partial class ChatTemplateDialog : MSGComponentBase
|
||||
private HashSet<string> selectedToolIds = new(StringComparer.Ordinal);
|
||||
private bool preselectDataSources;
|
||||
private DataSourceOptions templateDataSourceOptions = new();
|
||||
private bool preselectProfile;
|
||||
private string selectedProfileId = Profile.NO_PROFILE.Id;
|
||||
private bool preselectProvider;
|
||||
private string selectedProviderId = string.Empty;
|
||||
private bool preselectWorkspace;
|
||||
private string selectedWorkspaceName = string.Empty;
|
||||
private string[] dataIssues = [];
|
||||
private string dataEditingPreviousName = string.Empty;
|
||||
private bool isInlineEditOnGoing;
|
||||
@@ -138,6 +163,14 @@ public partial class ChatTemplateDialog : MSGComponentBase
|
||||
// them, so the switch inside the selection starts on instead of at its usual default:
|
||||
this.templateDataSourceOptions = this.DataSourceOptions?.CreateCopy() ?? new DataSourceOptions { DisableDataSources = false };
|
||||
|
||||
// The profile and the provider follow the same pattern, with a switch each:
|
||||
this.preselectProfile = this.ProfileId is not null;
|
||||
this.selectedProfileId = this.ProfileId ?? Profile.NO_PROFILE.Id;
|
||||
this.preselectProvider = this.ProviderId is not null;
|
||||
this.selectedProviderId = this.ProviderId ?? string.Empty;
|
||||
this.preselectWorkspace = this.WorkspaceName is not null;
|
||||
this.selectedWorkspaceName = this.WorkspaceName ?? string.Empty;
|
||||
|
||||
// When editing, we need to load the data:
|
||||
if(this.IsEditing)
|
||||
this.dataEditingPreviousName = this.DataName.ToLowerInvariant();
|
||||
@@ -183,6 +216,11 @@ public partial class ChatTemplateDialog : MSGComponentBase
|
||||
ToolIds = this.preselectTools ? new HashSet<string>(this.selectedToolIds, StringComparer.Ordinal) : null,
|
||||
DataSourceOptions = this.preselectDataSources ? this.templateDataSourceOptions.CreateCopy() : null,
|
||||
|
||||
// A template which forbids profiles has no use for a profile, so none is kept for it:
|
||||
ProfileId = this.AllowProfileUsage && this.preselectProfile ? this.selectedProfileId : null,
|
||||
ProviderId = this.preselectProvider && !string.IsNullOrWhiteSpace(this.selectedProviderId) ? this.selectedProviderId : null,
|
||||
WorkspaceName = this.preselectWorkspace && !string.IsNullOrWhiteSpace(this.selectedWorkspaceName) ? this.selectedWorkspaceName.Trim() : null,
|
||||
|
||||
EnterpriseConfigurationPluginId = Guid.Empty,
|
||||
IsEnterpriseConfiguration = false,
|
||||
};
|
||||
@@ -205,6 +243,57 @@ public partial class ChatTemplateDialog : MSGComponentBase
|
||||
|
||||
private void SetSelectedToolIds(HashSet<string> toolIds) => this.selectedToolIds = toolIds;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the preselected profile is gone, so that chats started with this template keep their usual profile.
|
||||
/// </summary>
|
||||
private bool IsPreselectedProfileMissing => this.preselectProfile
|
||||
&& this.selectedProfileId != Profile.NO_PROFILE.Id
|
||||
&& this.SettingsManager.GetProfileById(this.selectedProfileId) == Profile.NO_PROFILE;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the preselected provider is gone or may not be used for chats, so that chats started
|
||||
/// with this template keep their usual provider.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The list to pick from holds only the providers which may be used for chats. A template from
|
||||
/// another machine or from a configuration plugin may name another one, though, and the list
|
||||
/// alone would then show nothing about it.
|
||||
/// </remarks>
|
||||
private bool IsPreselectedProviderUnusable => this.preselectProvider
|
||||
&& !string.IsNullOrWhiteSpace(this.selectedProviderId)
|
||||
&& this.SettingsManager.GetChatTemplateProvider(this.selectedProviderId) == AIStudio.Settings.Provider.NONE;
|
||||
|
||||
/// <summary>
|
||||
/// Whether workspaces are switched off, so that a workspace of this template has no effect for now.
|
||||
/// </summary>
|
||||
private bool AreWorkspacesDisabled => this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.DISABLE_WORKSPACES;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the workspace of this template can be changed right now.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Not while workspaces are switched off: a choice made then would take effect for no chat,
|
||||
/// and nothing in the chat would say so. A workspace the template already names stays as it
|
||||
/// is, so it applies again once workspaces are back.
|
||||
/// </remarks>
|
||||
private bool IsWorkspaceChoiceLocked => this.IsReadOnly || this.AreWorkspacesDisabled;
|
||||
|
||||
private string? ValidateWorkspaceName(string workspaceName)
|
||||
{
|
||||
if (this.preselectWorkspace && string.IsNullOrWhiteSpace(workspaceName))
|
||||
return T("Please enter the workspace for the chats of this template, or switch the preselection off.");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidatePreselectedProvider(string providerId)
|
||||
{
|
||||
if (this.preselectProvider && string.IsNullOrWhiteSpace(providerId))
|
||||
return T("Please choose the provider this chat template preselects, or switch the preselection off.");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void RemoveMessage(ContentBlock item)
|
||||
{
|
||||
if (this.IsReadOnly)
|
||||
|
||||
@@ -114,6 +114,9 @@ public partial class SettingsDialogChatTemplate : SettingsDialogBase
|
||||
{ x => x.AllowProfileUsage, chatTemplate.AllowProfileUsage },
|
||||
{ x => x.ToolIds, chatTemplate.ToolIds },
|
||||
{ x => x.DataSourceOptions, chatTemplate.DataSourceOptions },
|
||||
{ x => x.ProfileId, chatTemplate.ProfileId },
|
||||
{ x => x.ProviderId, chatTemplate.ProviderId },
|
||||
{ x => x.WorkspaceName, chatTemplate.WorkspaceName },
|
||||
};
|
||||
|
||||
private async Task DeleteChatTemplate(ChatTemplate chatTemplate)
|
||||
|
||||
Reference in new issue
Block a user