From 3e59f23193af232eae6691100e5b646810c0ea55 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 13 Aug 2024 20:53:09 +0200 Subject: [PATCH] Added a rewrite and text improvement assistant (#73) --- .../Components/AssistantBase.razor | 2 +- .../Components/AssistantBase.razor.cs | 7 ++ .../Components/Pages/Assistants.razor | 1 + .../AssistantGrammarSpelling.razor.cs | 28 +++-- .../AssistantRewriteImprove.razor | 12 ++ .../AssistantRewriteImprove.razor.cs | 105 ++++++++++++++++++ .../Pages/RewriteImprove/WritingStyles.cs | 16 +++ .../RewriteImprove/WritingStylesExtensions.cs | 40 +++++++ .../Components/Pages/Settings.razor | 29 ++++- .../Translation/AssistantTranslation.razor.cs | 1 + .../Settings/ConfigurationSelectData.cs | 7 ++ .../Settings/DataModel/Data.cs | 4 + .../Settings/DataModel/DataGrammarSpelling.cs | 26 +++++ .../Settings/DataModel/DataRewriteImprove.cs | 32 ++++++ .../wwwroot/changelog/v0.8.8.md | 3 +- 15 files changed, 302 insertions(+), 11 deletions(-) create mode 100644 app/MindWork AI Studio/Components/Pages/RewriteImprove/AssistantRewriteImprove.razor create mode 100644 app/MindWork AI Studio/Components/Pages/RewriteImprove/AssistantRewriteImprove.razor.cs create mode 100644 app/MindWork AI Studio/Components/Pages/RewriteImprove/WritingStyles.cs create mode 100644 app/MindWork AI Studio/Components/Pages/RewriteImprove/WritingStylesExtensions.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataGrammarSpelling.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataRewriteImprove.cs diff --git a/app/MindWork AI Studio/Components/AssistantBase.razor b/app/MindWork AI Studio/Components/AssistantBase.razor index 61bf2ce..9a2968a 100644 --- a/app/MindWork AI Studio/Components/AssistantBase.razor +++ b/app/MindWork AI Studio/Components/AssistantBase.razor @@ -17,7 +17,7 @@ - @if (this.isProcessing) + @if (this.ShowDedicatedProgress && this.isProcessing) { } diff --git a/app/MindWork AI Studio/Components/AssistantBase.razor.cs b/app/MindWork AI Studio/Components/AssistantBase.razor.cs index 5e3154f..5c98934 100644 --- a/app/MindWork AI Studio/Components/AssistantBase.razor.cs +++ b/app/MindWork AI Studio/Components/AssistantBase.razor.cs @@ -36,6 +36,8 @@ public abstract partial class AssistantBase : ComponentBase private protected virtual RenderFragment? Body => null; protected virtual bool ShowResult => true; + + protected virtual bool ShowDedicatedProgress => false; protected virtual IReadOnlyList FooterButtons => []; @@ -143,6 +145,11 @@ public abstract partial class AssistantBase : ComponentBase return aiText.Text; } + protected async Task CopyToClipboard(string text) + { + await this.Rust.CopyText2Clipboard(this.JsRuntime, this.Snackbar, text); + } + private static string? GetButtonIcon(string icon) { if(string.IsNullOrWhiteSpace(icon)) diff --git a/app/MindWork AI Studio/Components/Pages/Assistants.razor b/app/MindWork AI Studio/Components/Pages/Assistants.razor index 8565631..b57af18 100644 --- a/app/MindWork AI Studio/Components/Pages/Assistants.razor +++ b/app/MindWork AI Studio/Components/Pages/Assistants.razor @@ -13,6 +13,7 @@ + diff --git a/app/MindWork AI Studio/Components/Pages/GrammarSpelling/AssistantGrammarSpelling.razor.cs b/app/MindWork AI Studio/Components/Pages/GrammarSpelling/AssistantGrammarSpelling.razor.cs index 1332630..323a883 100644 --- a/app/MindWork AI Studio/Components/Pages/GrammarSpelling/AssistantGrammarSpelling.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/GrammarSpelling/AssistantGrammarSpelling.razor.cs @@ -4,7 +4,7 @@ namespace AIStudio.Components.Pages.GrammarSpelling; public partial class AssistantGrammarSpelling : AssistantBaseCore { - protected override string Title => "Grammar and Spelling Checker"; + protected override string Title => "Grammar & Spelling Checker"; protected override string Description => """ @@ -23,10 +23,28 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore protected override bool ShowResult => false; + protected override bool ShowDedicatedProgress => true; + protected override IReadOnlyList FooterButtons => new[] { - new ButtonData("Copy corrected text", Icons.Material.Filled.ContentCopy, Color.Default, string.Empty, this.CopyToClipboard), + new ButtonData("Copy result", Icons.Material.Filled.ContentCopy, Color.Default, string.Empty, () => this.CopyToClipboard(this.correctedText)), }; + + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + if (this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions) + { + this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage; + this.customTargetLanguage = this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage; + this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider); + } + + await base.OnInitializedAsync(); + } + + #endregion private string inputText = string.Empty; private CommonLanguages selectedTargetLanguage; @@ -67,6 +85,7 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore private async Task ProofreadText() { + await this.form!.Validate(); if (!this.inputIsValid) return; @@ -76,9 +95,4 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore this.correctedText = await this.AddAIResponseAsync(time); await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.correctedText); } - - private async Task CopyToClipboard() - { - await this.Rust.CopyText2Clipboard(this.JsRuntime, this.Snackbar, this.correctedText); - } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/RewriteImprove/AssistantRewriteImprove.razor b/app/MindWork AI Studio/Components/Pages/RewriteImprove/AssistantRewriteImprove.razor new file mode 100644 index 0000000..ba6c211 --- /dev/null +++ b/app/MindWork AI Studio/Components/Pages/RewriteImprove/AssistantRewriteImprove.razor @@ -0,0 +1,12 @@ +@using AIStudio.Tools +@page "/assistant/rewrite-improve" +@inherits AssistantBaseCore + + + + + + + + Improve + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/RewriteImprove/AssistantRewriteImprove.razor.cs b/app/MindWork AI Studio/Components/Pages/RewriteImprove/AssistantRewriteImprove.razor.cs new file mode 100644 index 0000000..8bbfb0b --- /dev/null +++ b/app/MindWork AI Studio/Components/Pages/RewriteImprove/AssistantRewriteImprove.razor.cs @@ -0,0 +1,105 @@ +using AIStudio.Tools; + +namespace AIStudio.Components.Pages.RewriteImprove; + +public partial class AssistantRewriteImprove : AssistantBaseCore +{ + protected override string Title => "Rewrite & Improve Text"; + + protected override string Description => + """ + Rewrite and improve your text. Please note, that the capabilities of the different LLM providers will vary. + """; + + protected override string SystemPrompt => + $""" + You are an expert in language and style. You receive a text as input. First, you review the text. If no + changes are needed, you return the text without modifications. If a change is necessary, you improve the + text. You can also correct spelling and grammar issues. You never add additional information. You never + ask the user for additional information. Your response only contains the improved text. You do not explain + your changes. If no changes are needed, you return the text unchanged. + The style of the text: {this.selectedWritingStyle.Prompt()}. You follow the rules according + to {this.SystemPromptLanguage()} in all your changes. + """; + + protected override bool ShowResult => false; + + #region Overrides of AssistantBase + + protected override bool ShowDedicatedProgress => true; + + #endregion + + protected override IReadOnlyList FooterButtons => new[] + { + new ButtonData("Copy result", Icons.Material.Filled.ContentCopy, Color.Default, string.Empty, () => this.CopyToClipboard(this.rewrittenText)), + }; + + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + if (this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions) + { + this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage; + this.customTargetLanguage = this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage; + this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider); + this.selectedWritingStyle = this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle; + } + + await base.OnInitializedAsync(); + } + + #endregion + + private string inputText = string.Empty; + private CommonLanguages selectedTargetLanguage; + private string customTargetLanguage = string.Empty; + private string rewrittenText = string.Empty; + private WritingStyles selectedWritingStyle; + + private string? ValidateText(string text) + { + if(string.IsNullOrWhiteSpace(text)) + return "Please provide a text as input. You might copy the desired text from a document or a website."; + + 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 SystemPromptLanguage() + { + var lang = this.selectedTargetLanguage switch + { + CommonLanguages.AS_IS => "the source language", + CommonLanguages.OTHER => this.customTargetLanguage, + + _ => $"{this.selectedTargetLanguage.Name()}", + }; + + if (string.IsNullOrWhiteSpace(lang)) + return "the source language"; + + return lang; + } + + private async Task RewriteText() + { + await this.form!.Validate(); + if (!this.inputIsValid) + return; + + this.CreateChatThread(); + var time = this.AddUserRequest(this.inputText); + + this.rewrittenText = await this.AddAIResponseAsync(time); + await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.rewrittenText); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/RewriteImprove/WritingStyles.cs b/app/MindWork AI Studio/Components/Pages/RewriteImprove/WritingStyles.cs new file mode 100644 index 0000000..62d82bd --- /dev/null +++ b/app/MindWork AI Studio/Components/Pages/RewriteImprove/WritingStyles.cs @@ -0,0 +1,16 @@ +namespace AIStudio.Components.Pages.RewriteImprove; + +public enum WritingStyles +{ + NOT_SPECIFIED = 0, + + EVERYDAY, + BUSINESS, + SCIENTIFIC, + JOURNALISTIC, + LITERARY, + TECHNICAL, + MARKETING, + ACADEMIC, + LEGAL, +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/RewriteImprove/WritingStylesExtensions.cs b/app/MindWork AI Studio/Components/Pages/RewriteImprove/WritingStylesExtensions.cs new file mode 100644 index 0000000..ab2027c --- /dev/null +++ b/app/MindWork AI Studio/Components/Pages/RewriteImprove/WritingStylesExtensions.cs @@ -0,0 +1,40 @@ +namespace AIStudio.Components.Pages.RewriteImprove; + +public static class WritingStylesExtensions +{ + public static string Name(this WritingStyles style) + { + return style switch + { + WritingStyles.EVERYDAY => "Everyday (personal texts, social media)", + WritingStyles.BUSINESS => "Business (business emails, reports, presentations)", + WritingStyles.SCIENTIFIC => "Scientific (scientific papers, research reports)", + WritingStyles.JOURNALISTIC => "Journalistic (magazines, newspapers, news)", + WritingStyles.LITERARY => "Literary (fiction, poetry)", + WritingStyles.TECHNICAL => "Technical (manuals, documentation)", + WritingStyles.MARKETING => "Marketing (advertisements, sales texts)", + WritingStyles.ACADEMIC => "Academic (essays, seminar papers)", + WritingStyles.LEGAL => "Legal (legal texts, contracts)", + + _ => "Not specified", + }; + } + + public static string Prompt(this WritingStyles style) + { + return style switch + { + WritingStyles.EVERYDAY => "Use a everyday style like for personal texts, social media, and informal communication.", + WritingStyles.BUSINESS => "Use a business style like for business emails, reports, and presentations. Most important is clarity and professionalism.", + WritingStyles.SCIENTIFIC => "Use a scientific style like for scientific papers, research reports, and academic writing. Most important is precision and objectivity.", + WritingStyles.JOURNALISTIC => "Use a journalistic style like for magazines, newspapers, and news. Most important is readability and engaging content.", + WritingStyles.LITERARY => "Use a literary style like for fiction, poetry, and creative writing. Most important is creativity and emotional impact.", + WritingStyles.TECHNICAL => "Use a technical style like for manuals, documentation, and technical writing. Most important is clarity and precision.", + WritingStyles.MARKETING => "Use a marketing style like for advertisements, sales texts, and promotional content. Most important is persuasiveness and engagement.", + WritingStyles.ACADEMIC => "Use a academic style like for essays, seminar papers, and academic writing. Most important is clarity and objectivity.", + WritingStyles.LEGAL => "Use a legal style like for legal texts, contracts, and official documents. Most important is precision and legal correctness. Use formal legal language.", + + _ => "Keep the style of the text as it is.", + }; + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/Settings.razor b/app/MindWork AI Studio/Components/Pages/Settings.razor index 4a3be0b..55789d6 100644 --- a/app/MindWork AI Studio/Components/Pages/Settings.razor +++ b/app/MindWork AI Studio/Components/Pages/Settings.razor @@ -106,7 +106,7 @@ @if (this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage is CommonLanguages.OTHER) { - + } @@ -168,12 +168,37 @@ @if (this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage is CommonLanguages.OTHER) { - + } + + + + + @if (this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage is CommonLanguages.OTHER) + { + + } + + + + + + + + + @if (this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage is CommonLanguages.OTHER) + { + + } + + + + + diff --git a/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor.cs b/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor.cs index 20fe8fe..e4f4970 100644 --- a/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor.cs @@ -69,6 +69,7 @@ public partial class AssistantTranslation : AssistantBaseCore private async Task TranslateText(bool force) { + await this.form!.Validate(); if (!this.inputIsValid) return; diff --git a/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs b/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs index e802a7f..6293844 100644 --- a/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs +++ b/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs @@ -1,6 +1,7 @@ using AIStudio.Components.Pages.Agenda; using AIStudio.Components.Pages.Coding; using AIStudio.Components.Pages.IconFinder; +using AIStudio.Components.Pages.RewriteImprove; using AIStudio.Components.Pages.TextSummarizer; using AIStudio.Settings.DataModel; using AIStudio.Tools; @@ -99,4 +100,10 @@ public static class ConfigurationSelectDataFactory foreach (var number in Enum.GetValues()) yield return new(number.Name(), number); } + + public static IEnumerable> GetWritingStylesData() + { + foreach (var style in Enum.GetValues()) + yield return new(style.Name(), style); + } } \ 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 36c5c32..1a39c2f 100644 --- a/app/MindWork AI Studio/Settings/DataModel/Data.cs +++ b/app/MindWork AI Studio/Settings/DataModel/Data.cs @@ -38,4 +38,8 @@ public sealed class Data public DataTextContentCleaner TextContentCleaner { get; init; } = new(); public DataAgenda Agenda { get; init; } = new(); + + public DataGrammarSpelling GrammarSpelling { get; init; } = new(); + + public DataRewriteImprove RewriteImprove { get; init; } = new(); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataGrammarSpelling.cs b/app/MindWork AI Studio/Settings/DataModel/DataGrammarSpelling.cs new file mode 100644 index 0000000..cd74c0b --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataGrammarSpelling.cs @@ -0,0 +1,26 @@ +using AIStudio.Tools; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataGrammarSpelling +{ + /// + /// Preselect any rewrite options? + /// + public bool PreselectOptions { get; set; } + + /// + /// Preselect the target language? + /// + public CommonLanguages PreselectedTargetLanguage { get; set; } + + /// + /// Preselect any other language? + /// + public string PreselectedOtherLanguage { get; set; } = string.Empty; + + /// + /// Preselect a provider? + /// + public string PreselectedProvider { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataRewriteImprove.cs b/app/MindWork AI Studio/Settings/DataModel/DataRewriteImprove.cs new file mode 100644 index 0000000..19fe925 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataRewriteImprove.cs @@ -0,0 +1,32 @@ +using AIStudio.Components.Pages.RewriteImprove; +using AIStudio.Tools; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataRewriteImprove +{ + /// + /// Preselect any rewrite options? + /// + public bool PreselectOptions { get; set; } + + /// + /// Preselect the target language? + /// + public CommonLanguages PreselectedTargetLanguage { get; set; } + + /// + /// Preselect any other language? + /// + public string PreselectedOtherLanguage { get; set; } = string.Empty; + + /// + /// Preselect any writing style? + /// + public WritingStyles PreselectedWritingStyle { get; set; } + + /// + /// Preselect a provider? + /// + public string PreselectedProvider { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.8.8.md b/app/MindWork AI Studio/wwwroot/changelog/v0.8.8.md index 3ce6a96..f0d67f9 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.8.8.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.8.8.md @@ -1,4 +1,5 @@ # v0.8.8, build 170 - Added a grammar and spell checker assistant -- Improved all assistants by showing a progress bar while processing +- Added a rewrite and text improvement assistant +- Fixed validation for the translation assistant - Upgraded MudBlazor to v7.6.0 \ No newline at end of file