Skip to content

Commit 6116c03

Browse files
Extension of the chat template (#521)
Co-authored-by: Thorsten Sommer <[email protected]> Co-authored-by: Thorsten Sommer <[email protected]>
1 parent 9c52812 commit 6116c03

File tree

14 files changed

+169
-13
lines changed

14 files changed

+169
-13
lines changed

app/MindWork AI Studio/Assistants/I18N/allTexts.lua

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T636393754"] = "Move the c
14141414
-- Show your workspaces
14151415
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T733672375"] = "Show your workspaces"
14161416

1417+
-- Create template from current chat
1418+
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATTEMPLATESELECTION::T1112722156"] = "Create template from current chat"
1419+
14171420
-- Start a new chat with a chat template
14181421
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATTEMPLATESELECTION::T1333844707"] = "Start a new chat with a chat template"
14191422

@@ -2197,18 +2200,30 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T1847791252"] = "Update"
21972200
-- The chat template name must not exceed 40 characters.
21982201
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T204496403"] = "The chat template name must not exceed 40 characters."
21992202

2203+
-- Profile Usage
2204+
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T2147062613"] = "Profile Usage"
2205+
22002206
-- 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.
22012207
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T2292424657"] = "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."
22022208

22032209
-- Role
22042210
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T2418769465"] = "Role"
22052211

2212+
-- What predefined user input do you want to use?
2213+
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T2501284417"] = "What predefined user input do you want to use?"
2214+
22062215
-- Tell the AI your system prompt.
22072216
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T2552381261"] = "Tell the AI your system prompt."
22082217

22092218
-- No, prohibit profile use for this template
22102219
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T2579080722"] = "No, prohibit profile use for this template"
22112220

2221+
-- You might want to predefine a first message that will be copied into the user prompt, when you use this chat template. This message could for example be a blueprint for a structured message that this chat template is defined to work with.
2222+
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T2579208700"] = "You might want to predefine a first message that will be copied into the user prompt, when you use this chat template. This message could for example be a blueprint for a structured message that this chat template is defined to work with."
2223+
2224+
-- Predefined User Input
2225+
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T2607897066"] = "Predefined User Input"
2226+
22122227
-- Entry
22132228
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T2629823795"] = "Entry"
22142229

@@ -2263,6 +2278,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3893704289"] = "Message
22632278
-- Use the default system prompt
22642279
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T4051106111"] = "Use the default system prompt"
22652280

2281+
-- Tell the AI your predefined user input.
2282+
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T4052406705"] = "Tell the AI your predefined user input."
2283+
22662284
-- Create your custom chat template to tailor the LLM's behavior for specific tasks or domains. Define a custom system prompt and provide an example conversation to design an AI experience perfectly suited to your requirements.
22672285
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T4199560726"] = "Create your custom chat template to tailor the LLM's behavior for specific tasks or domains. Define a custom system prompt and provide an example conversation to design an AI experience perfectly suited to your requirements."
22682286

app/MindWork AI Studio/Chat/ChatThread.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,11 @@ public string PrepareSystemPrompt(SettingsManager settingsManager, ChatThread ch
100100
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
101101
else
102102
{
103-
if(!Guid.TryParse(chatThread.SelectedChatTemplate, out var chatTeamplateId))
103+
if(!Guid.TryParse(chatThread.SelectedChatTemplate, out var chatTemplateId))
104104
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
105105
else
106106
{
107-
if(chatThread.SelectedChatTemplate == ChatTemplate.NO_CHAT_TEMPLATE.Id || chatTeamplateId == Guid.Empty)
107+
if(chatThread.SelectedChatTemplate == ChatTemplate.NO_CHAT_TEMPLATE.Id || chatTemplateId == Guid.Empty)
108108
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
109109
else
110110
{
@@ -121,6 +121,11 @@ public string PrepareSystemPrompt(SettingsManager settingsManager, ChatThread ch
121121
}
122122
}
123123

124+
// We need a way to save the changed system prompt in our chat thread.
125+
// Otherwise, the chat thread will always tell us that it is using the
126+
// default system prompt:
127+
chatThread = chatThread with { SystemPrompt = systemPromptTextWithChatTemplate };
128+
124129
logger.LogInformation(logMessage);
125130

126131
//

app/MindWork AI Studio/Chat/ContentBlock.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ public class ContentBlock
3030
/// </summary>
3131
public bool HideFromUser { get; init; }
3232

33-
public ContentBlock DeepClone() => new()
33+
public ContentBlock DeepClone(bool changeHideState = false, bool hideFromUser = true) => new()
3434
{
3535
Time = this.Time,
3636
ContentType = this.ContentType,
3737
Content = this.Content?.DeepClone(),
3838
Role = this.Role,
39-
HideFromUser = this.HideFromUser,
39+
HideFromUser = changeHideState ? hideFromUser : this.HideFromUser,
4040
};
4141
}

app/MindWork AI Studio/Components/ChatComponent.razor

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@
8181
</MudTooltip>
8282
}
8383

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

app/MindWork AI Studio/Components/ChatComponent.razor.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ protected override async Task OnInitializedAsync()
8080

8181
// Get the preselected chat template:
8282
this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(Tools.Components.CHAT);
83+
this.userInput = this.currentChatTemplate.PredefinedUserPrompt;
8384

8485
//
8586
// Check for deferred messages of the kind 'SEND_TO_CHAT',
@@ -272,7 +273,7 @@ private string InputLabel
272273
}
273274
}
274275

275-
private bool CanThreadBeSaved => this.ChatThread is not null && this.ChatThread.Blocks.Count > 0;
276+
private bool CanThreadBeSaved => this.ChatThread is not null && this.ChatThread.Blocks.Any(b => !b.HideFromUser);
276277

277278
private string TooltipAddChatToWorkspace => string.Format(T("Start new chat in workspace '{0}'"), this.currentWorkspaceName);
278279

@@ -326,6 +327,7 @@ private async Task ProfileWasChanged(Profile profile)
326327
private async Task ChatTemplateWasChanged(ChatTemplate chatTemplate)
327328
{
328329
this.currentChatTemplate = chatTemplate;
330+
this.userInput = this.currentChatTemplate.PredefinedUserPrompt;
329331
if(this.ChatThread is null)
330332
return;
331333

@@ -675,6 +677,8 @@ private async Task StartNewChat(bool useSameWorkspace = false, bool deletePrevio
675677
};
676678
}
677679

680+
this.userInput = this.currentChatTemplate.PredefinedUserPrompt;
681+
678682
// Now, we have to reset the data source options as well:
679683
this.ApplyStandardDataSourceOptions();
680684

app/MindWork AI Studio/Components/ChatTemplateSelection.razor

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
<ChildContent>
1919
<MudMenuItem Icon="@Icons.Material.Filled.Settings" Label="@T("Manage your templates")" OnClick="async () => await this.OpenSettingsDialog()" />
2020
<MudDivider/>
21+
<MudMenuItem Icon="@Icons.Material.Filled.AddComment" Label="@T("Create template from current chat")" OnClick="async () => await this.CreateNewChatTemplateFromChat()" Disabled="@(!this.CanChatThreadBeUsedForTemplate)"/>
22+
<MudDivider/>
2123
@foreach (var chatTemplate in this.SettingsManager.ConfigurationData.ChatTemplates.GetAllChatTemplates())
2224
{
2325
<MudMenuItem Icon="@Icons.Material.Filled.RateReview" OnClick="async () => await this.SelectionChanged(chatTemplate)">

app/MindWork AI Studio/Components/ChatTemplateSelection.razor.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using AIStudio.Chat;
12
using AIStudio.Dialogs.Settings;
23
using AIStudio.Settings;
34

@@ -11,6 +12,12 @@ public partial class ChatTemplateSelection : MSGComponentBase
1112
[Parameter]
1213
public ChatTemplate CurrentChatTemplate { get; set; } = ChatTemplate.NO_CHAT_TEMPLATE;
1314

15+
[Parameter]
16+
public bool CanChatThreadBeUsedForTemplate { get; set; }
17+
18+
[Parameter]
19+
public ChatThread? CurrentChatThread { get; set; }
20+
1421
[Parameter]
1522
public EventCallback<ChatTemplate> CurrentChatTemplateChanged { get; set; }
1623

@@ -36,4 +43,14 @@ private async Task OpenSettingsDialog()
3643
var dialogParameters = new DialogParameters();
3744
await this.DialogService.ShowAsync<SettingsDialogChatTemplate>(T("Open Chat Template Options"), dialogParameters, DialogOptions.FULLSCREEN);
3845
}
46+
47+
private async Task CreateNewChatTemplateFromChat()
48+
{
49+
var dialogParameters = new DialogParameters<SettingsDialogChatTemplate>
50+
{
51+
{ x => x.CreateTemplateFromExistingChatThread, true },
52+
{ x => x.ExistingChatThread, this.CurrentChatThread }
53+
};
54+
await this.DialogService.ShowAsync<SettingsDialogChatTemplate>(T("Open Chat Template Options"), dialogParameters, DialogOptions.FULLSCREEN);
55+
}
3956
}

app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,42 @@
5656
@T("Use the default system prompt")
5757
</MudButton>
5858

59-
<MudJustifiedText Class="mt-6" Typo="Typo.body1">
59+
<MudText Typo="Typo.h6" Class="mb-3 mt-6">
60+
@T("Predefined User Input")
61+
</MudText>
62+
<MudJustifiedText Class="mb-3" Typo="Typo.body1">
63+
@T("You might want to predefine a first message that will be copied into the user prompt, when you use this chat template. This message could for example be a blueprint for a structured message that this chat template is defined to work with.")
64+
</MudJustifiedText>
65+
<MudTextField
66+
T="string"
67+
@bind-Text="@this.PredefinedUserPrompt"
68+
AdornmentIcon="@Icons.Material.Filled.ListAlt"
69+
Adornment="Adornment.Start"
70+
Immediate="@true"
71+
Label="@T("What predefined user input do you want to use?")"
72+
Variant="Variant.Outlined"
73+
Lines="4"
74+
MaxLines="12"
75+
AutoGrow="@true"
76+
Class="mb-3"
77+
UserAttributes="@SPELLCHECK_ATTRIBUTES"
78+
HelperText="@T("Tell the AI your predefined user input.")"
79+
/>
80+
81+
<MudText Typo="Typo.h6" Class="mb-3 mt-6">
82+
@T("Profile Usage")
83+
</MudText>
84+
<MudJustifiedText Class="mb-3" Typo="Typo.body1">
6085
@T("Using some chat templates in tandem with profiles might cause issues. Therefore, you might prohibit the usage of profiles here.")
6186
</MudJustifiedText>
6287
<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")" />
6388

6489
<MudText Typo="Typo.h6" Class="mb-3 mt-6">
6590
@T("Example Conversation")
6691
</MudText>
67-
6892
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
6993
@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.")
7094
</MudJustifiedText>
71-
7295
<MudTable Items="@this.dataExampleConversation" FixedHeader="true" Hover="true" Class="mt-3 mb-3" CanCancelEdit="true" CancelEditTooltip="@T("Cancel")" CommitEditTooltip="@T("Commit Changes")" Outlined="true" RowEditCancel="@this.ResetItem" RowEditPreview="@this.BackupItem" EditTrigger="TableEditTrigger.RowClick" IsEditRowSwitchingBlocked="false" RowEditCommit="@this.CommitInlineEdit">
7396
<ColGroup>
7497
<col style="width: 10em;" />

app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ public partial class ChatTemplateDialog : MSGComponentBase
3535
[Parameter]
3636
public string DataSystemPrompt { get; set; } = string.Empty;
3737

38+
/// <summary>
39+
/// What is the predefined user prompt?
40+
/// </summary>
41+
[Parameter]
42+
public string PredefinedUserPrompt { get; set; } = string.Empty;
43+
3844
/// <summary>
3945
/// Should the dialog be in editing mode?
4046
/// </summary>
@@ -47,6 +53,12 @@ public partial class ChatTemplateDialog : MSGComponentBase
4753
[Parameter]
4854
public bool AllowProfileUsage { get; set; } = true;
4955

56+
[Parameter]
57+
public bool CreateFromExistingChatThread { get; set; }
58+
59+
[Parameter]
60+
public ChatThread? ExistingChatThread { get; set; }
61+
5062
[Inject]
5163
private ILogger<ChatTemplateDialog> Logger { get; init; } = null!;
5264

@@ -84,6 +96,13 @@ protected override async Task OnInitializedAsync()
8496
this.dataEditingPreviousName = this.DataName.ToLowerInvariant();
8597
this.dataExampleConversation = this.ExampleConversation.Select(n => n.DeepClone()).ToList();
8698
}
99+
100+
if (this.CreateFromExistingChatThread && this.ExistingChatThread is not null)
101+
{
102+
this.DataSystemPrompt = this.ExistingChatThread.SystemPrompt;
103+
this.dataExampleConversation = this.ExistingChatThread.Blocks.Select(n => n.DeepClone(true)).ToList();
104+
this.DataName = this.ExistingChatThread.Name;
105+
}
87106

88107
await base.OnInitializedAsync();
89108
}
@@ -107,6 +126,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
107126

108127
Name = this.DataName,
109128
SystemPrompt = this.DataSystemPrompt,
129+
PredefinedUserPrompt = this.PredefinedUserPrompt,
110130
ExampleConversation = this.dataExampleConversation,
111131
AllowProfileUsage = this.AllowProfileUsage,
112132
};

app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,42 @@
1+
using AIStudio.Chat;
12
using AIStudio.Settings;
3+
using Microsoft.AspNetCore.Components;
24

35
namespace AIStudio.Dialogs.Settings;
46

57
public partial class SettingsDialogChatTemplate : SettingsDialogBase
68
{
9+
[Parameter]
10+
public bool CreateTemplateFromExistingChatThread { get; set; }
11+
12+
[Parameter]
13+
public ChatThread? ExistingChatThread { get; set; }
14+
15+
#region Overrides of ComponentBase
16+
17+
/// <inheritdoc />
18+
protected override async Task OnInitializedAsync()
19+
{
20+
await base.OnInitializedAsync();
21+
if (this.CreateTemplateFromExistingChatThread)
22+
await this.AddChatTemplate();
23+
}
24+
25+
#endregion
26+
727
private async Task AddChatTemplate()
828
{
929
var dialogParameters = new DialogParameters<ChatTemplateDialog>
1030
{
1131
{ x => x.IsEditing, false },
1232
};
13-
33+
34+
if (this.CreateTemplateFromExistingChatThread)
35+
{
36+
dialogParameters.Add(x => x.CreateFromExistingChatThread, this.CreateTemplateFromExistingChatThread);
37+
dialogParameters.Add(x => x.ExistingChatThread, this.ExistingChatThread);
38+
}
39+
1440
var dialogReference = await this.DialogService.ShowAsync<ChatTemplateDialog>(T("Add Chat Template"), dialogParameters, DialogOptions.FULLSCREEN);
1541
var dialogResult = await dialogReference.Result;
1642
if (dialogResult is null || dialogResult.Canceled)
@@ -33,6 +59,7 @@ private async Task EditChatTemplate(ChatTemplate chatTemplate)
3359
{ x => x.DataId, chatTemplate.Id },
3460
{ x => x.DataName, chatTemplate.Name },
3561
{ x => x.DataSystemPrompt, chatTemplate.SystemPrompt },
62+
{ x => x.PredefinedUserPrompt, chatTemplate.PredefinedUserPrompt },
3663
{ x => x.IsEditing, true },
3764
{ x => x.ExampleConversation, chatTemplate.ExampleConversation },
3865
{ x => x.AllowProfileUsage, chatTemplate.AllowProfileUsage },

0 commit comments

Comments
 (0)