The template can now be created from an existing thread

This commit is contained in:
Peer Schütt 2025-07-09 16:17:17 +02:00
parent 30777337dd
commit 7e29999bfb
7 changed files with 75 additions and 4 deletions

View File

@ -68,7 +68,7 @@ public sealed record ChatThread
/// <summary>
/// The current system prompt for the chat thread.
/// </summary>
public string SystemPrompt { get; init; } = string.Empty;
public string SystemPrompt { get; set; } = string.Empty;
/// <summary>
/// The content blocks of the chat thread.
@ -121,6 +121,10 @@ public sealed record ChatThread
}
}
// We need a way to save the changed system prompt in our chatThread.
// Otherwise, the chatThread will always tell us that it is using the default system prompt.
chatThread.SystemPrompt = systemPromptTextWithChatTemplate;
logger.LogInformation(logMessage);
//

View File

@ -28,7 +28,7 @@ public class ContentBlock
/// <summary>
/// Should the content block be hidden from the user?
/// </summary>
public bool HideFromUser { get; init; }
public bool HideFromUser { get; set; }
public ContentBlock DeepClone() => new()
{

View File

@ -81,7 +81,8 @@
</MudTooltip>
}
<ChatTemplateSelection CurrentChatTemplate="@this.currentChatTemplate" CurrentChatTemplateChanged="@this.ChatTemplateWasChanged"/>
<ChatTemplateSelection CanChatThreadBeUsedForTemplate="@this.CanThreadBeSaved" CurrentChatThread="@this.ChatThread" CurrentChatTemplate="@this.currentChatTemplate" CurrentChatTemplateChanged="@this.ChatTemplateWasChanged"/>
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
{
<MudTooltip Text="@T("Delete this chat & start a new one.")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">

View File

@ -18,6 +18,8 @@
<ChildContent>
<MudMenuItem Icon="@Icons.Material.Filled.Settings" Label="@T("Manage your templates")" OnClick="async () => await this.OpenSettingsDialog()" />
<MudDivider/>
<MudMenuItem Icon="@Icons.Material.Filled.AddComment" Label="@T("Create template from current chat")" OnClick="async () => await this.CreateNewChatTemplateFromChat()" Disabled="@(!this.CanChatThreadBeUsedForTemplate)"/>
<MudDivider/>
@foreach (var chatTemplate in this.SettingsManager.ConfigurationData.ChatTemplates.GetAllChatTemplates())
{
<MudMenuItem Icon="@Icons.Material.Filled.RateReview" OnClick="async () => await this.SelectionChanged(chatTemplate)">

View File

@ -1,3 +1,4 @@
using AIStudio.Chat;
using AIStudio.Dialogs.Settings;
using AIStudio.Settings;
@ -11,6 +12,12 @@ public partial class ChatTemplateSelection : MSGComponentBase
[Parameter]
public ChatTemplate CurrentChatTemplate { get; set; } = ChatTemplate.NO_CHAT_TEMPLATE;
[Parameter]
public bool CanChatThreadBeUsedForTemplate { get; set; }
[Parameter]
public ChatThread? CurrentChatThread { get; set; }
[Parameter]
public EventCallback<ChatTemplate> CurrentChatTemplateChanged { get; set; }
@ -36,4 +43,14 @@ public partial class ChatTemplateSelection : MSGComponentBase
var dialogParameters = new DialogParameters();
await this.DialogService.ShowAsync<SettingsDialogChatTemplate>(T("Open Chat Template Options"), dialogParameters, DialogOptions.FULLSCREEN);
}
private async Task CreateNewChatTemplateFromChat()
{
var dialogParameters = new DialogParameters<SettingsDialogChatTemplate>
{
{ x => x.CreateTemplateFromExistingChatThread, true },
{ x => x.ExistingChatThread, this.CurrentChatThread }
};
await this.DialogService.ShowAsync<SettingsDialogChatTemplate>(T("Open Chat Template Options"), dialogParameters, DialogOptions.FULLSCREEN);
}
}

View File

@ -53,6 +53,12 @@ public partial class ChatTemplateDialog : MSGComponentBase
[Parameter]
public bool AllowProfileUsage { get; set; } = true;
[Parameter]
public bool CreateFromExistingChatThread { get; set; }
[Parameter]
public ChatThread? ExistingChatThread { get; set; }
[Inject]
private ILogger<ChatTemplateDialog> Logger { get; init; } = null!;
@ -90,6 +96,20 @@ public partial class ChatTemplateDialog : MSGComponentBase
this.dataEditingPreviousName = this.DataName.ToLowerInvariant();
this.dataExampleConversation = this.ExampleConversation.Select(n => n.DeepClone()).ToList();
}
if (this.CreateFromExistingChatThread)
{
this.DataSystemPrompt = this.ExistingChatThread!.SystemPrompt;
this.dataExampleConversation = this.ExistingChatThread!.Blocks.Select(n => n.DeepClone()).ToList();
this.DataName = this.ExistingChatThread!.Name;
// the contentblocks that we copy are visible to the user, and we don't want to show them while using the template
foreach (var item in this.dataExampleConversation)
{
item.HideFromUser = true;
}
}
await base.OnInitializedAsync();
}

View File

@ -1,16 +1,43 @@
using AIStudio.Chat;
using AIStudio.Settings;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Dialogs.Settings;
public partial class SettingsDialogChatTemplate : SettingsDialogBase
{
[Parameter]
public bool CreateTemplateFromExistingChatThread { get; set; }
[Parameter]
public ChatThread? ExistingChatThread { get; set; }
#region Overrides of ComponentBase
/// <inheritdoc />
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
if (this.CreateTemplateFromExistingChatThread)
await this.AddChatTemplate();
}
#endregion
private async Task AddChatTemplate()
{
var dialogParameters = new DialogParameters<ChatTemplateDialog>
{
{ x => x.IsEditing, false },
};
if (this.CreateTemplateFromExistingChatThread)
{
dialogParameters.Add(x => x.CreateFromExistingChatThread, this.CreateTemplateFromExistingChatThread);
dialogParameters.Add(x => x.ExistingChatThread, this.ExistingChatThread);
}
var dialogReference = await this.DialogService.ShowAsync<ChatTemplateDialog>(T("Add Chat Template"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)