Added the current date and time to the system prompt. (#628)
Some checks are pending
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage deb updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions

Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
Peer Schütt 2026-01-18 20:36:04 +01:00 committed by GitHub
parent 85af3ed651
commit cc3560fdd2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 73 additions and 42 deletions

View File

@ -190,6 +190,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
{
this.chatThread = new()
{
IncludeDateTime = false,
SelectedProvider = this.providerSettings.Id,
SelectedProfile = this.AllowProfiles ? this.currentProfile.Id : Profile.NO_PROFILE.Id,
SystemPrompt = this.SystemPrompt,
@ -205,6 +206,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
var chatId = Guid.NewGuid();
this.chatThread = new()
{
IncludeDateTime = false,
SelectedProvider = this.providerSettings.Id,
SelectedProfile = this.AllowProfiles ? this.currentProfile.Id : Profile.NO_PROFILE.Id,
SystemPrompt = this.SystemPrompt,

View File

@ -457,6 +457,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialo
return;
this.CreateChatThread();
this.chatThread!.IncludeDateTime = true;
var userRequest = this.AddUserRequest(
await this.PromptLoadDocumentsContent(),

View File

@ -1,3 +1,5 @@
using System.Globalization;
using AIStudio.Components;
using AIStudio.Settings;
using AIStudio.Settings.DataModel;
@ -37,6 +39,12 @@ public sealed record ChatThread
/// </summary>
public string SelectedChatTemplate { get; set; } = string.Empty;
/// <summary>
/// Indicates whether to include the current date and time in the system prompt.
/// False by default for backward compatibility.
/// </summary>
public bool IncludeDateTime { get; set; } = false;
/// <summary>
/// The data source options for this chat thread.
/// </summary>
@ -65,7 +73,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.
@ -83,33 +91,32 @@ public sealed record ChatThread
/// is extended with the profile chosen.
/// </remarks>
/// <param name="settingsManager">The settings manager instance to use.</param>
/// <param name="chatThread">The chat thread to prepare the system prompt for.</param>
/// <returns>The prepared system prompt.</returns>
public string PrepareSystemPrompt(SettingsManager settingsManager, ChatThread chatThread)
public string PrepareSystemPrompt(SettingsManager settingsManager)
{
//
// 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;
var logMessage = $"Using no chat template for chat thread '{this.Name}'.";
if (string.IsNullOrWhiteSpace(this.SelectedChatTemplate))
systemPromptTextWithChatTemplate = this.SystemPrompt;
else
{
if(!Guid.TryParse(chatThread.SelectedChatTemplate, out var chatTemplateId))
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
if(!Guid.TryParse(this.SelectedChatTemplate, out var chatTemplateId))
systemPromptTextWithChatTemplate = this.SystemPrompt;
else
{
if(chatThread.SelectedChatTemplate == ChatTemplate.NO_CHAT_TEMPLATE.Id || chatTemplateId == Guid.Empty)
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
if(this.SelectedChatTemplate == ChatTemplate.NO_CHAT_TEMPLATE.Id || chatTemplateId == Guid.Empty)
systemPromptTextWithChatTemplate = this.SystemPrompt;
else
{
var chatTemplate = settingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == chatThread.SelectedChatTemplate);
var chatTemplate = settingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == this.SelectedChatTemplate);
if(chatTemplate == null)
systemPromptTextWithChatTemplate = chatThread.SystemPrompt;
systemPromptTextWithChatTemplate = this.SystemPrompt;
else
{
logMessage = $"Using chat template '{chatTemplate.Name}' for chat thread '{chatThread.Name}'.";
logMessage = $"Using chat template '{chatTemplate.Name}' for chat thread '{this.Name}'.";
this.allowProfile = chatTemplate.AllowProfileUsage;
systemPromptTextWithChatTemplate = chatTemplate.ToSystemPrompt();
}
@ -120,20 +127,19 @@ public sealed record ChatThread
// We need a way to save the changed system prompt in our chat thread.
// Otherwise, the chat thread will always tell us that it is using the
// default system prompt:
chatThread = chatThread with { SystemPrompt = systemPromptTextWithChatTemplate };
this.SystemPrompt = systemPromptTextWithChatTemplate;
LOGGER.LogInformation(logMessage);
//
// Add augmented data, if available:
//
var isAugmentedDataAvailable = !string.IsNullOrWhiteSpace(chatThread.AugmentedData);
var isAugmentedDataAvailable = !string.IsNullOrWhiteSpace(this.AugmentedData);
var systemPromptWithAugmentedData = isAugmentedDataAvailable switch
{
true => $"""
{systemPromptTextWithChatTemplate}
{chatThread.AugmentedData}
{this.AugmentedData}
""",
false => systemPromptTextWithChatTemplate,
@ -149,25 +155,25 @@ public sealed record ChatThread
// Add information from the profile if available and allowed:
//
string systemPromptText;
logMessage = $"Using no profile for chat thread '{chatThread.Name}'.";
if (string.IsNullOrWhiteSpace(chatThread.SelectedProfile) || this.allowProfile is false)
logMessage = $"Using no profile for chat thread '{this.Name}'.";
if (string.IsNullOrWhiteSpace(this.SelectedProfile) || !this.allowProfile)
systemPromptText = systemPromptWithAugmentedData;
else
{
if(!Guid.TryParse(chatThread.SelectedProfile, out var profileId))
if(!Guid.TryParse(this.SelectedProfile, out var profileId))
systemPromptText = systemPromptWithAugmentedData;
else
{
if(chatThread.SelectedProfile == Profile.NO_PROFILE.Id || profileId == Guid.Empty)
if(this.SelectedProfile == Profile.NO_PROFILE.Id || profileId == Guid.Empty)
systemPromptText = systemPromptWithAugmentedData;
else
{
var profile = settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == chatThread.SelectedProfile);
if(profile == default)
var profile = settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.SelectedProfile);
if(profile is null)
systemPromptText = systemPromptWithAugmentedData;
else
{
logMessage = $"Using profile '{profile.Name}' for chat thread '{chatThread.Name}'.";
logMessage = $"Using profile '{profile.Name}' for chat thread '{this.Name}'.";
systemPromptText = $"""
{systemPromptWithAugmentedData}
@ -179,7 +185,24 @@ public sealed record ChatThread
}
LOGGER.LogInformation(logMessage);
return systemPromptText;
if(!this.IncludeDateTime)
return systemPromptText;
//
// Prepend the current date and time to the system prompt:
//
var nowUtc = DateTime.UtcNow;
var nowLocal = DateTime.Now;
var currentDateTime = string.Create(
new CultureInfo("en-US"),
$"Today is {nowUtc:dddd, MMMM d, yyyy h:mm tt} (UTC) and {nowLocal:dddd, MMMM d, yyyy h:mm tt} (local time)."
);
return $"""
{currentDateTime}
{systemPromptText}
""";
}
/// <summary>

View File

@ -2,5 +2,5 @@ namespace AIStudio.Chat;
public static class SystemPrompts
{
public const string DEFAULT = "You are a helpful assistant!";
public const string DEFAULT = "You are a helpful assistant.";
}

View File

@ -97,6 +97,8 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// Use chat thread sent by the user:
this.ChatThread = deferredContent;
this.ChatThread.IncludeDateTime = true;
this.Logger.LogInformation($"The chat '{this.ChatThread.ChatId}' with {this.ChatThread.Blocks.Count} messages was deferred and will be rendered now.");
await this.ChatThreadChanged.InvokeAsync(this.ChatThread);
@ -435,6 +437,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
{
this.ChatThread = new()
{
IncludeDateTime = true,
SelectedProvider = this.Provider.Id,
SelectedProfile = this.currentProfile.Id,
SelectedChatTemplate = this.currentChatTemplate.Id,
@ -675,6 +678,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
//
this.ChatThread = new()
{
IncludeDateTime = true,
SelectedProvider = this.Provider.Id,
SelectedProfile = this.currentProfile.Id,
SelectedChatTemplate = this.currentChatTemplate.Id,

View File

@ -33,7 +33,7 @@ public sealed class ProviderAlibabaCloud() : BaseProvider(LLMProviders.ALIBABA_C
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -72,7 +72,7 @@ public sealed class ProviderAnthropic() : BaseProvider(LLMProviders.ANTHROPIC, "
// Build the messages:
Messages = [..messages],
System = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
System = chatThread.PrepareSystemPrompt(settingsManager),
MaxTokens = apiParameters.TryGetValue("max_tokens", out var value) && value is int intValue ? intValue : 4_096,
// Right now, we only support streaming completions:

View File

@ -33,7 +33,7 @@ public sealed class ProviderDeepSeek() : BaseProvider(LLMProviders.DEEP_SEEK, "h
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -33,7 +33,7 @@ public class ProviderFireworks() : BaseProvider(LLMProviders.FIREWORKS, "https:/
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -33,7 +33,7 @@ public sealed class ProviderGWDG() : BaseProvider(LLMProviders.GWDG, "https://ch
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -33,7 +33,7 @@ public class ProviderGoogle() : BaseProvider(LLMProviders.GOOGLE, "https://gener
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -33,7 +33,7 @@ public class ProviderGroq() : BaseProvider(LLMProviders.GROQ, "https://api.groq.
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -33,7 +33,7 @@ public sealed class ProviderHelmholtz() : BaseProvider(LLMProviders.HELMHOLTZ, "
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -38,7 +38,7 @@ public sealed class ProviderHuggingFace : BaseProvider
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -31,7 +31,7 @@ public sealed class ProviderMistral() : BaseProvider(LLMProviders.MISTRAL, "http
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -73,7 +73,7 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, "https
var systemPrompt = new TextMessage
{
Role = systemPromptRole,
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
//

View File

@ -36,7 +36,7 @@ public sealed class ProviderOpenRouter() : BaseProvider(LLMProviders.OPEN_ROUTER
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -42,7 +42,7 @@ public sealed class ProviderPerplexity() : BaseProvider(LLMProviders.PERPLEXITY,
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -32,7 +32,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -33,7 +33,7 @@ public sealed class ProviderX() : BaseProvider(LLMProviders.X, "https://api.x.ai
var systemPrompt = new TextMessage
{
Role = "system",
Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
Content = chatThread.PrepareSystemPrompt(settingsManager),
};
// Parse the API parameters:

View File

@ -1,5 +1,6 @@
# v26.1.2, build 232 (2026-01-xx xx:xx UTC)
- Added the option to hide specific assistants by configuration plugins. This is useful for enterprise environments in organizations.
- Added the current date and time to the system prompt for better context in conversations. Thanks Peer `peerschuett` for the contribution.
- Improved error handling for model loading in provider dialogs (LLMs, embeddings, transcriptions).
- Improved the microphone handling (transcription preview) so that all sound effects and the voice recording are processed without interruption.
- Improved the handling of self-hosted providers in the configuration dialogs (LLMs, embeddings, and transcriptions) when the host cannot provide a list of models.