Added a rewrite and text improvement assistant

This commit is contained in:
Thorsten Sommer 2024-08-13 18:42:01 +02:00
parent 05a7e44de4
commit 0b224be8a7
Signed by: tsommer
GPG Key ID: 371BBA77A02C0108
9 changed files with 169 additions and 9 deletions

View File

@ -17,7 +17,7 @@
</MudForm> </MudForm>
<Issues IssuesData="@this.inputIssues"/> <Issues IssuesData="@this.inputIssues"/>
@if (this.isProcessing) @if (this.ShowDedicatedProgress && this.isProcessing)
{ {
<MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="mb-6" /> <MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="mb-6" />
} }

View File

@ -36,6 +36,8 @@ public abstract partial class AssistantBase : ComponentBase
private protected virtual RenderFragment? Body => null; private protected virtual RenderFragment? Body => null;
protected virtual bool ShowResult => true; protected virtual bool ShowResult => true;
protected virtual bool ShowDedicatedProgress => false;
protected virtual IReadOnlyList<ButtonData> FooterButtons => []; protected virtual IReadOnlyList<ButtonData> FooterButtons => [];
@ -143,6 +145,11 @@ public abstract partial class AssistantBase : ComponentBase
return aiText.Text; return aiText.Text;
} }
protected async Task CopyToClipboard(string text)
{
await this.Rust.CopyText2Clipboard(this.JsRuntime, this.Snackbar, text);
}
private static string? GetButtonIcon(string icon) private static string? GetButtonIcon(string icon)
{ {
if(string.IsNullOrWhiteSpace(icon)) if(string.IsNullOrWhiteSpace(icon))

View File

@ -13,6 +13,7 @@
<AssistantBlock Name="Text Summarizer" Description="Using a LLM to summarize a given text." Icon="@Icons.Material.Filled.TextSnippet" Link="/assistant/summarizer"/> <AssistantBlock Name="Text Summarizer" Description="Using a LLM to summarize a given text." Icon="@Icons.Material.Filled.TextSnippet" Link="/assistant/summarizer"/>
<AssistantBlock Name="Translation" Description="Translate text into another language." Icon="@Icons.Material.Filled.Translate" Link="/assistant/translation"/> <AssistantBlock Name="Translation" Description="Translate text into another language." Icon="@Icons.Material.Filled.Translate" Link="/assistant/translation"/>
<AssistantBlock Name="Grammar & Spelling" Description="Check grammar and spelling of a given text." Icon="@Icons.Material.Filled.Edit" Link="/assistant/grammar-spelling"/> <AssistantBlock Name="Grammar & Spelling" Description="Check grammar and spelling of a given text." Icon="@Icons.Material.Filled.Edit" Link="/assistant/grammar-spelling"/>
<AssistantBlock Name="Rewrite & Improve" Description="Rewrite and improve a given text for a chosen style." Icon="@Icons.Material.Filled.Edit" Link="/assistant/rewrite-improve"/>
</MudStack> </MudStack>
<MudText Typo="Typo.h4" Class="mb-2 mr-3 mt-6"> <MudText Typo="Typo.h4" Class="mb-2 mr-3 mt-6">

View File

@ -4,7 +4,7 @@ namespace AIStudio.Components.Pages.GrammarSpelling;
public partial class AssistantGrammarSpelling : AssistantBaseCore public partial class AssistantGrammarSpelling : AssistantBaseCore
{ {
protected override string Title => "Grammar and Spelling Checker"; protected override string Title => "Grammar & Spelling Checker";
protected override string Description => protected override string Description =>
""" """
@ -23,9 +23,11 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore
protected override bool ShowResult => false; protected override bool ShowResult => false;
protected override bool ShowDedicatedProgress => true;
protected override IReadOnlyList<ButtonData> FooterButtons => new[] protected override IReadOnlyList<ButtonData> 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)),
}; };
private string inputText = string.Empty; private string inputText = string.Empty;
@ -76,9 +78,4 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore
this.correctedText = await this.AddAIResponseAsync(time); this.correctedText = await this.AddAIResponseAsync(time);
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.correctedText); await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.correctedText);
} }
private async Task CopyToClipboard()
{
await this.Rust.CopyText2Clipboard(this.JsRuntime, this.Snackbar, this.correctedText);
}
} }

View File

@ -0,0 +1,12 @@
@using AIStudio.Tools
@page "/assistant/rewrite-improve"
@inherits AssistantBaseCore
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input to improve" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom language" />
<EnumSelection T="WritingStyles" NameFunc="@(style => style.Name())" @bind-Value="@this.selectedWritingStyle" Icon="@Icons.Material.Filled.Edit" Label="Writing style" AllowOther="@false" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.RewriteText()">
Improve
</MudButton>

View File

@ -0,0 +1,87 @@
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 errors. 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<ButtonData> FooterButtons => new[]
{
new ButtonData("Copy result", Icons.Material.Filled.ContentCopy, Color.Default, string.Empty, () => this.CopyToClipboard(this.rewrittenText)),
};
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()
{
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);
}
}

View File

@ -0,0 +1,16 @@
namespace AIStudio.Components.Pages.RewriteImprove;
public enum WritingStyles
{
NOT_SPECIFIED = 0,
EVERYDAY,
BUSINESS,
SCIENTIFIC,
JOURNALISTIC,
LITERARY,
TECHNICAL,
MARKETING,
ACADEMIC,
LEGAL,
}

View File

@ -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.",
};
}
}

View File

@ -1,4 +1,4 @@
# v0.8.8, build 170 # v0.8.8, build 170
- Added a grammar and spell checker assistant - Added a grammar and spell checker assistant
- Improved all assistants by showing a progress bar while processing - Added a rewrite and text improvement assistant
- Upgraded MudBlazor to v7.6.0 - Upgraded MudBlazor to v7.6.0