diff --git a/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor b/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor new file mode 100644 index 00000000..73c5caaa --- /dev/null +++ b/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor @@ -0,0 +1,5 @@ +@attribute [Route(Routes.ASSISTANT_BIAS)] +@inherits AssistantBaseCore + + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor.cs b/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor.cs new file mode 100644 index 00000000..469069d5 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor.cs @@ -0,0 +1,148 @@ +using System.Text; + +using AIStudio.Components; +using AIStudio.Settings.DataModel; + +namespace AIStudio.Assistants.BiasDay; + +public partial class BiasOfTheDayAssistant : AssistantBaseCore +{ + public override Tools.Components Component => Tools.Components.BIAS_DAY_ASSISTANT; + + protected override string Title => "Bias of the Day"; + + protected override string Description => + """ + Learn about a different cognitive bias every day. You have the opportunity to ask your questions to the LLM. + """; + + protected override string SystemPrompt => $""" + You are a friendly, helpful expert on cognitive bias. You studied psychology and + have a lot of experience. You explain a bias every day. Today's bias belongs to + the category: "{this.biasOfTheDay.Category.ToName()}". We have the following + thoughts on this category: + + {this.biasOfTheDay.Category.GetThoughts()} + + Today's bias is: + {this.biasOfTheDay.Description} + {this.SystemPromptSources()} + Important: you use the following language: {this.SystemPromptLanguage()}. Please + ask the user a personal question at the end to encourage them to think about + this bias. + """; + + protected override IReadOnlyList FooterButtons => []; + + protected override string SubmitText => "Show me the bias of the day"; + + protected override Func SubmitAction => this.TellBias; + + protected override bool ShowSendTo => false; + + protected override bool ShowCopyResult => false; + + protected override bool ShowReset => false; + + protected override void ResetFrom() + { + if (!this.MightPreselectValues()) + { + this.selectedTargetLanguage = CommonLanguages.AS_IS; + this.customTargetLanguage = string.Empty; + } + } + + protected override bool MightPreselectValues() + { + if (this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions) + { + this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedTargetLanguage; + this.customTargetLanguage = this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedOtherLanguage; + return true; + } + + return false; + } + + private Bias biasOfTheDay = BiasCatalog.NONE; + private CommonLanguages selectedTargetLanguage = CommonLanguages.AS_IS; + private string customTargetLanguage = string.Empty; + + private string? ValidateTargetLanguage(CommonLanguages language) + { + if(language is CommonLanguages.AS_IS) + return "Please select a target language for the bias."; + + return null; + } + + private string? ValidateCustomLanguage(string language) + { + if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language)) + return "Please provide a custom language."; + + return null; + } + + private string SystemPromptSources() + { + var sb = new StringBuilder(); + if (this.biasOfTheDay.Links.Count > 0) + { + sb.AppendLine(); + sb.AppendLine("Please share the following sources with the user as a Markdown list:"); + foreach (var link in this.biasOfTheDay.Links) + sb.AppendLine($"- {link}"); + + sb.AppendLine(); + } + + return sb.ToString(); + } + + private string SystemPromptLanguage() + { + if(this.selectedTargetLanguage is CommonLanguages.OTHER) + return this.customTargetLanguage; + + return this.selectedTargetLanguage.Name(); + } + + private async Task TellBias() + { + if(this.SettingsManager.ConfigurationData.BiasOfTheDay.RestrictOneBiasPerDay) + { + if(this.SettingsManager.ConfigurationData.BiasOfTheDay.DateLastBiasDrawn == DateOnly.FromDateTime(DateTime.Now)) + { + MessageBus.INSTANCE.DeferMessage(this, Event.LOAD_CHAT, + new LoadChat + { + WorkspaceId = Workspaces.WORKSPACE_ID_BIAS, + ChatId = this.SettingsManager.ConfigurationData.BiasOfTheDay.BiasOfTheDayChatId, + }); + + this.NavigationManager.NavigateTo(Routes.CHAT); + return; + } + } + + await this.form!.Validate(); + if (!this.inputIsValid) + return; + + this.biasOfTheDay = BiasCatalog.GetRandomBias(this.SettingsManager.ConfigurationData.BiasOfTheDay.UsedBias); + var chatId = this.CreateChatThread(Workspaces.WORKSPACE_ID_BIAS, this.biasOfTheDay.Name); + this.SettingsManager.ConfigurationData.BiasOfTheDay.BiasOfTheDayChatId = chatId; + this.SettingsManager.ConfigurationData.BiasOfTheDay.DateLastBiasDrawn = DateOnly.FromDateTime(DateTime.Now); + await this.SettingsManager.StoreSettings(); + var time = this.AddUserRequest( + """ + Please tell me about the bias of the day. + """, true); + + // Start the AI response without waiting for it to finish: + _ = this.AddAIResponseAsync(time); + await this.SendToAssistant(Tools.Components.CHAT, default); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/Data.cs b/app/MindWork AI Studio/Settings/DataModel/Data.cs index 720d0e0e..59ceaae9 100644 --- a/app/MindWork AI Studio/Settings/DataModel/Data.cs +++ b/app/MindWork AI Studio/Settings/DataModel/Data.cs @@ -67,4 +67,6 @@ public sealed class Data public DataMyTasks MyTasks { get; init; } = new(); public DataJobPostings JobPostings { get; init; } = new(); + + public DataBiasOfTheDay BiasOfTheDay { get; init; } = new(); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataBiasOfTheDay.cs b/app/MindWork AI Studio/Settings/DataModel/DataBiasOfTheDay.cs new file mode 100644 index 00000000..0b1315b7 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataBiasOfTheDay.cs @@ -0,0 +1,56 @@ +using AIStudio.Provider; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataBiasOfTheDay +{ + /// + /// A list of bias IDs that have been used. + /// + public List UsedBias { get; set; } = new(); + + /// + /// When was the last bias drawn? + /// + public DateOnly DateLastBiasDrawn { get; set; } = DateOnly.MinValue; + + /// + /// Which bias is the bias of the day? This isn't the bias id, but rather the chat id in the bias workspace. + /// + public Guid BiasOfTheDayChatId { get; set; } = Guid.Empty; + + /// + /// Restrict to one bias per day? + /// + public bool RestrictOneBiasPerDay { get; set; } = true; + + /// + /// Preselect any rewrite options? + /// + public bool PreselectOptions { get; set; } + + /// + /// Preselect the language? + /// + public CommonLanguages PreselectedTargetLanguage { get; set; } + + /// + /// Preselect any other language? + /// + public string PreselectedOtherLanguage { get; set; } = string.Empty; + + /// + /// The minimum confidence level required for a provider to be considered. + /// + public ConfidenceLevel MinimumProviderConfidence { get; set; } = ConfidenceLevel.NONE; + + /// + /// Preselect a profile? + /// + public string PreselectedProfile { get; set; } = string.Empty; + + /// + /// Preselect a provider? + /// + public string PreselectedProvider { get; set; } = string.Empty; +} \ No newline at end of file