Added chat templates (#474)

This commit is contained in:
Peer Schütt authored and GitHub committed 2025-05-24 12:27:00 +02:00
1 parent 35eebc08a5
commit df062ae6e6
27 files changed
+799 -21

No files matched your search

+22 -4
View File
@@ -1,3 +1,5 @@
using AIStudio.Tools.PluginSystem;
namespace AIStudio.Chat;
/// <summary>
@@ -19,6 +21,8 @@ public enum ChatRole
/// </summary>
public static class ExtensionsChatRole
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ChatRole).Namespace, nameof(ChatRole));
/// <summary>
/// Returns the name of the role.
/// </summary>
@@ -26,11 +30,11 @@ public static class ExtensionsChatRole
/// <returns>The name of the role.</returns>
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"),
};
/// <summary>
@@ -60,4 +64,18 @@ public static class ExtensionsChatRole
_ => Icons.Material.Filled.Help,
};
/// <summary>
/// Returns the specific name of the role for the chat template.
/// </summary>
/// <param name="role">The role.</param>
/// <returns>The name of the role.</returns>
public static string ToChatTemplateName(this ChatRole role) => role switch
{
ChatRole.SYSTEM => TB("System"),
ChatRole.USER => TB("User"),
ChatRole.AI => TB("Assistant"),
_ => TB("Unknown"),
};
}
+10
View File
@@ -0,0 +1,10 @@
namespace AIStudio.Chat;
public static class ChatRoles
{
public static IEnumerable<ChatRole> ChatTemplateRoles()
{
yield return ChatRole.USER;
yield return ChatRole.AI;
}
}
+49 -5
View File
@@ -29,6 +29,11 @@ public sealed record ChatThread
/// Specifies the profile selected for the chat thread.
/// </summary>
public string SelectedProfile { get; set; } = string.Empty;
/// <summary>
/// Specifies the profile selected for the chat thread.
/// </summary>
public string SelectedChatTemplate { get; set; } = string.Empty;
/// <summary>
/// The data source options for this chat thread.
@@ -69,6 +74,8 @@ public sealed record ChatThread
/// The content blocks of the chat thread.
/// </summary>
public List<ContentBlock> Blocks { get; init; } = [];
private bool allowProfile = true;
/// <summary>
/// Prepares the system prompt for the chat thread.
@@ -84,16 +91,52 @@ public sealed record ChatThread
/// <returns>The prepared system prompt.</returns>
public string PrepareSystemPrompt(SettingsManager settingsManager, ChatThread chatThread, ILogger logger)
{
//
// Use the information from the chat template, if provided. Otherwise, use the default system prompt
//
string systemPromptTextWithChatTemplate;
var logMessage = $"Using no chat template for chat thread '{chatThread.Name}'.";
if (string.IsNullOrWhiteSpace(chatThread.SelectedChatTemplate))
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
else
{
if(!Guid.TryParse(chatThread.SelectedChatTemplate, out var chatTeamplateId))
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
else
{
if(chatThread.SelectedChatTemplate == ChatTemplate.NO_CHATTEMPLATE.Id || chatTeamplateId == Guid.Empty)
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
else
{
var chatTemplate = settingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == chatThread.SelectedChatTemplate);
if(chatTemplate == default)
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
else
{
logMessage = $"Using chat template '{chatTemplate.Name}' for chat thread '{chatThread.Name}'.";
this.allowProfile = chatTemplate.AllowProfileUsage;
systemPromptTextWithChatTemplate = $"""
{chatTemplate.ToSystemPrompt()}
""";
}
}
}
}
logger.LogInformation(logMessage);
//
// Add augmented data, if available:
//
var isAugmentedDataAvailable = !string.IsNullOrWhiteSpace(chatThread.AugmentedData);
var systemPromptWithAugmentedData = isAugmentedDataAvailable switch
{
true => $"""
{chatThread.SystemPrompt}
{systemPromptTextWithChatTemplate}
{chatThread.AugmentedData}
""",
false => chatThread.SystemPrompt,
false => systemPromptTextWithChatTemplate,
};
if(isAugmentedDataAvailable)
@@ -101,12 +144,13 @@ public sealed record ChatThread
else
logger.LogInformation("No augmented data is available for the chat thread.");
//
// Prepare the system prompt:
// Add information from profile if available and allowed:
//
string systemPromptText;
var logMessage = $"Using no profile for chat thread '{chatThread.Name}'.";
if (string.IsNullOrWhiteSpace(chatThread.SelectedProfile))
logMessage = $"Using no profile for chat thread '{chatThread.Name}'.";
if ((string.IsNullOrWhiteSpace(chatThread.SelectedProfile)) || (this.allowProfile is false))
systemPromptText = systemPromptWithAugmentedData;
else
{
+14 -2
View File
@@ -18,15 +18,27 @@ public class ContentBlock
/// <summary>
/// The content of the block.
/// </summary>
public IContent? Content { get; init; }
public IContent? Content { get; set; }
/// <summary>
/// The role of the content block in the chat thread, e.g., user, AI, etc.
/// </summary>
public ChatRole Role { get; init; } = ChatRole.NONE;
public ChatRole Role { get; set; } = ChatRole.NONE;
/// <summary>
/// Should the content block be hidden from the user?
/// </summary>
public bool HideFromUser { get; set; }
public ContentBlock DeepClone()
{
return new()
{
Time = this.Time,
ContentType = this.ContentType,
Content = this.Content?.DeepClone(),
Role = this.Role,
HideFromUser = this.HideFromUser,
};
}
}
@@ -32,6 +32,18 @@ public sealed class ContentImage : IContent, IImageSource
{
throw new NotImplementedException();
}
/// <inheritdoc />
public IContent DeepClone()
{
return new ContentImage
{
Source = this.Source,
InitialRemoteWait = this.InitialRemoteWait,
IsStreaming = this.IsStreaming,
SourceType = this.SourceType,
};
}
#endregion
@@ -125,6 +125,17 @@ public sealed class ContentText : IContent
return chatThread;
}
/// <inheritdoc />
public IContent DeepClone()
{
return new ContentText
{
Text = this.Text,
InitialRemoteWait = this.InitialRemoteWait,
IsStreaming = this.IsStreaming,
};
}
#endregion
/// <summary>
+6
View File
@@ -43,6 +43,12 @@ public interface IContent
/// </summary>
public Task<ChatThread> CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default);
/// <summary>
/// Creates a deep copy
/// </summary>
/// <returns>The copy</returns>
public IContent DeepClone();
/// <summary>
/// Returns the corresponding ERI content type.
/// </summary>