mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-02-05 11:29:06 +00:00
Add assistants (#33)
This commit is contained in:
parent
88aefe1c4e
commit
58c9d8ac33
@ -1,7 +1,7 @@
|
||||
@using AIStudio.Tools
|
||||
@using MudBlazor
|
||||
|
||||
<MudCard Class="my-2 rounded-lg" Outlined="@true">
|
||||
<MudCard Class="@this.CardClasses" Outlined="@true">
|
||||
<MudCardHeader>
|
||||
<CardHeaderAvatar>
|
||||
<MudAvatar Color="@this.Role.ToColor()">
|
||||
|
@ -33,6 +33,12 @@ public partial class ContentBlockComponent : ComponentBase
|
||||
[Parameter]
|
||||
public DateTimeOffset Time { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional CSS classes.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Class { get; set; } = string.Empty;
|
||||
|
||||
[Inject]
|
||||
private Rust Rust { get; init; } = null!;
|
||||
|
||||
@ -107,4 +113,6 @@ public partial class ContentBlockComponent : ComponentBase
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private string CardClasses => $"my-2 rounded-lg {this.Class}";
|
||||
}
|
39
app/MindWork AI Studio/Components/AssistantBase.razor
Normal file
39
app/MindWork AI Studio/Components/AssistantBase.razor
Normal file
@ -0,0 +1,39 @@
|
||||
@using AIStudio.Chat
|
||||
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
|
||||
@this.Title
|
||||
</MudText>
|
||||
|
||||
<InnerScrolling HeaderHeight="12.3em">
|
||||
<ChildContent>
|
||||
<MudForm @ref="@this.form" @bind-IsValid="@this.inputIsValid" @bind-Errors="@this.inputIssues" Class="pr-2">
|
||||
<MudText Typo="Typo.body1" Align="Align.Justify" Class="mb-6">
|
||||
@this.Description
|
||||
</MudText>
|
||||
|
||||
@if (this.Body is not null)
|
||||
{
|
||||
@this.Body
|
||||
}
|
||||
</MudForm>
|
||||
|
||||
@if (this.inputIssues.Any())
|
||||
{
|
||||
<MudPaper Class="pr-2 mt-3" Outlined="@true">
|
||||
<MudText Typo="Typo.h6">Issues</MudText>
|
||||
<MudList Clickable="@true">
|
||||
@foreach (var issue in this.inputIssues)
|
||||
{
|
||||
<MudListItem Icon="@Icons.Material.Filled.Error" IconColor="Color.Error">
|
||||
@issue
|
||||
</MudListItem>
|
||||
}
|
||||
</MudList>
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
@if (this.resultingContentBlock is not null)
|
||||
{
|
||||
<ContentBlockComponent Role="@this.resultingContentBlock.Role" Type="@this.resultingContentBlock.ContentType" Time="@this.resultingContentBlock.Time" Content="@this.resultingContentBlock.Content" Class="mr-2"/>
|
||||
}
|
||||
</ChildContent>
|
||||
</InnerScrolling>
|
104
app/MindWork AI Studio/Components/AssistantBase.razor.cs
Normal file
104
app/MindWork AI Studio/Components/AssistantBase.razor.cs
Normal file
@ -0,0 +1,104 @@
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
|
||||
public abstract partial class AssistantBase : ComponentBase
|
||||
{
|
||||
[Inject]
|
||||
protected SettingsManager SettingsManager { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JsRuntime { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected Random RNG { get; set; } = null!;
|
||||
|
||||
protected abstract string Title { get; }
|
||||
|
||||
protected abstract string Description { get; }
|
||||
|
||||
protected abstract string SystemPrompt { get; }
|
||||
|
||||
private protected virtual RenderFragment? Body => null;
|
||||
|
||||
protected AIStudio.Settings.Provider selectedProvider;
|
||||
protected MudForm? form;
|
||||
protected bool inputIsValid;
|
||||
|
||||
private ChatThread? chatThread;
|
||||
private ContentBlock? resultingContentBlock;
|
||||
private string[] inputIssues = [];
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
// Reset the validation when not editing and on the first render.
|
||||
// We don't want to show validation errors when the user opens the dialog.
|
||||
if(firstRender)
|
||||
this.form?.ResetValidation();
|
||||
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected void CreateChatThread()
|
||||
{
|
||||
this.chatThread = new()
|
||||
{
|
||||
WorkspaceId = Guid.Empty,
|
||||
ChatId = Guid.NewGuid(),
|
||||
Name = string.Empty,
|
||||
Seed = this.RNG.Next(),
|
||||
SystemPrompt = this.SystemPrompt,
|
||||
Blocks = [],
|
||||
};
|
||||
}
|
||||
|
||||
protected DateTimeOffset AddUserRequest(string request)
|
||||
{
|
||||
var time = DateTimeOffset.Now;
|
||||
this.chatThread!.Blocks.Add(new ContentBlock
|
||||
{
|
||||
Time = time,
|
||||
ContentType = ContentType.TEXT,
|
||||
Role = ChatRole.USER,
|
||||
Content = new ContentText
|
||||
{
|
||||
Text = request,
|
||||
},
|
||||
});
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
protected async Task AddAIResponseAsync(DateTimeOffset time)
|
||||
{
|
||||
var aiText = new ContentText
|
||||
{
|
||||
// We have to wait for the remote
|
||||
// for the content stream:
|
||||
InitialRemoteWait = true,
|
||||
};
|
||||
|
||||
this.resultingContentBlock = new ContentBlock
|
||||
{
|
||||
Time = time,
|
||||
ContentType = ContentType.TEXT,
|
||||
Role = ChatRole.AI,
|
||||
Content = aiText,
|
||||
};
|
||||
|
||||
this.chatThread?.Blocks.Add(this.resultingContentBlock);
|
||||
|
||||
// Use the selected provider to get the AI response.
|
||||
// By awaiting this line, we wait for the entire
|
||||
// content to be streamed.
|
||||
await aiText.CreateFromProviderAsync(this.selectedProvider.UsedProvider.CreateProvider(this.selectedProvider.InstanceName, this.selectedProvider.Hostname), this.JsRuntime, this.SettingsManager, this.selectedProvider.Model, this.chatThread);
|
||||
}
|
||||
}
|
19
app/MindWork AI Studio/Components/AssistantBaseCore.cs
Normal file
19
app/MindWork AI Studio/Components/AssistantBaseCore.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
|
||||
//
|
||||
// See https://stackoverflow.com/a/77300384/2258393 for why this class is needed
|
||||
//
|
||||
|
||||
public abstract class AssistantBaseCore : AssistantBase
|
||||
{
|
||||
private protected sealed override RenderFragment Body => this.BuildRenderTree;
|
||||
|
||||
// Allow content to be provided by a .razor file but without
|
||||
// overriding the content of the base class
|
||||
protected new virtual void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<MudItem xs="3">
|
||||
<MudCard Outlined="@true" Style="border-width: 2px; border-color: #0d47a1; border-radius: 12px; border-style: solid;">
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudStack AlignItems="AlignItems.Center" Row="@true">
|
||||
<MudIcon Icon="@this.Icon" Size="Size.Large" Color="Color.Primary"/>
|
||||
<MudText Typo="Typo.h6">
|
||||
@this.Name
|
||||
</MudText>
|
||||
</MudStack>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudStack>
|
||||
<MudText>
|
||||
@this.Description
|
||||
</MudText>
|
||||
</MudStack>
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudButton Size="Size.Large" Variant="Variant.Filled" StartIcon="@this.Icon" Color="Color.Default" Href="@this.Link">
|
||||
@this.ButtonText
|
||||
</MudButton>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
</MudItem>
|
@ -0,0 +1,21 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class AssistantBlock : ComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public string Icon { get; set; } = Icons.Material.Filled.DisabledByDefault;
|
||||
|
||||
[Parameter]
|
||||
public string ButtonText { get; set; } = "Start";
|
||||
|
||||
[Parameter]
|
||||
public string Link { get; set; } = string.Empty;
|
||||
}
|
@ -13,7 +13,8 @@ public partial class Changelog
|
||||
|
||||
public static readonly Log[] LOGS =
|
||||
[
|
||||
new (161, "v0.7.1, build 161 (2024-07-13 12:44 UTC)", "v0.7.1.md"),
|
||||
new (162, "v0.8.0, build 162 (2024-07-14 19:39 UTC)", "v0.8.0.md"),
|
||||
new (161, "v0.7.1, build 161 (2024-07-13 11:42 UTC)", "v0.7.1.md"),
|
||||
new (160, "v0.7.0, build 160 (2024-07-13 08:21 UTC)", "v0.7.0.md"),
|
||||
new (159, "v0.6.3, build 159 (2024-07-03 18:26 UTC)", "v0.6.3.md"),
|
||||
new (158, "v0.6.2, build 158 (2024-07-01 18:03 UTC)", "v0.6.2.md"),
|
||||
|
@ -1,4 +1,4 @@
|
||||
@inherits AIStudio.Tools.MSGComponentBase
|
||||
@inherits MSGComponentBase
|
||||
|
||||
<div class="d-flex flex-column" style="@this.Height">
|
||||
<div class="flex-auto overflow-auto">
|
||||
|
@ -13,6 +13,9 @@
|
||||
<MudTooltip Text="Chat" Placement="Placement.Right">
|
||||
<MudNavLink Href="/chat" Icon="@Icons.Material.Filled.Chat">Chat</MudNavLink>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Assistants" Placement="Placement.Right">
|
||||
<MudNavLink Href="/assistants" Icon="@Icons.Material.Filled.Apps">Assistants</MudNavLink>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Supporters" Placement="Placement.Right">
|
||||
<MudNavLink Href="/supporters" Icon="@Icons.Material.Filled.Favorite" IconColor="Color.Error">Supporters</MudNavLink>
|
||||
</MudTooltip>
|
||||
|
@ -1,6 +1,8 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Tools;
|
||||
namespace AIStudio.Components;
|
||||
|
||||
public abstract class MSGComponentBase : ComponentBase, IDisposable, IMessageBusReceiver
|
||||
{
|
11
app/MindWork AI Studio/Components/Pages/Assistants.razor
Normal file
11
app/MindWork AI Studio/Components/Pages/Assistants.razor
Normal file
@ -0,0 +1,11 @@
|
||||
@page "/assistants"
|
||||
|
||||
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
|
||||
Assistants
|
||||
</MudText>
|
||||
|
||||
<MudGrid>
|
||||
<AssistantBlock Name="Icon Finder" Description="Using a LLM to find an icon for a given context." Icon="@Icons.Material.Filled.FindInPage" Link="/assistant/icons"/>
|
||||
<AssistantBlock Name="Text Summarizer" Description="Using a LLM to summarize a given text." Icon="@Icons.Material.Filled.TextSnippet" Link="/assistant/summarizer"/>
|
||||
<AssistantBlock Name="Translator" Description="Translate text into another language." Icon="@Icons.Material.Filled.Translate" Link="/assistant/translator"/>
|
||||
</MudGrid>
|
@ -0,0 +1,5 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Pages;
|
||||
|
||||
public partial class Assistants : ComponentBase;
|
@ -2,7 +2,7 @@
|
||||
@using AIStudio.Chat
|
||||
@using AIStudio.Settings
|
||||
|
||||
@inherits AIStudio.Tools.MSGComponentBase
|
||||
@inherits MSGComponentBase
|
||||
|
||||
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
|
||||
@if (this.chatThread is not null && this.chatThread.WorkspaceId != Guid.Empty)
|
||||
|
@ -0,0 +1,29 @@
|
||||
@page "/assistant/icons"
|
||||
@using AIStudio.Settings
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.inputContext" Validation="@this.ValidatingContext" AdornmentIcon="@Icons.Material.Filled.Description" Adornment="Adornment.Start" Label="Your context" Variant="Variant.Outlined" Lines="3" AutoGrow="@true" MaxLines="12" Class="mb-3"/>
|
||||
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
|
||||
<MudSelect T="IconSources" @bind-Value="@this.selectedIconSource" AdornmentIcon="@Icons.Material.Filled.Source" Adornment="Adornment.Start" Label="Your icon source" Variant="Variant.Outlined" Margin="Margin.Dense">
|
||||
@foreach (var source in Enum.GetValues<IconSources>())
|
||||
{
|
||||
<MudSelectItem Value="@source">@source.Name()</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.selectedIconSource is not IconSources.GENERIC)
|
||||
{
|
||||
<MudButton Href="@this.selectedIconSource.URL()" Target="_blank" Variant="Variant.Filled" Size="Size.Medium">Open website</MudButton>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
<MudSelect T="Provider" @bind-Value="@this.selectedProvider" Validation="@this.ValidatingProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-3 rounded-lg" Variant="Variant.Outlined">
|
||||
@foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
{
|
||||
<MudSelectItem Value="@provider"/>
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.FindIcon()">
|
||||
Find icon
|
||||
</MudButton>
|
@ -0,0 +1,65 @@
|
||||
using AIStudio.Provider;
|
||||
|
||||
namespace AIStudio.Components.Pages.IconFinder;
|
||||
|
||||
public partial class AssistantIconFinder : AssistantBaseCore
|
||||
{
|
||||
private string inputContext = string.Empty;
|
||||
private IconSources selectedIconSource;
|
||||
|
||||
protected override string Title => "Icon Finder";
|
||||
|
||||
protected override string Description =>
|
||||
"""
|
||||
Finding the right icon for a context, such as for a piece of text, is not easy. The first challenge:
|
||||
You need to extract a concept from your context, such as from a text. Let's take an example where
|
||||
your text contains statements about multiple departments. The sought-after concept could be "departments."
|
||||
The next challenge is that we need to anticipate the bias of the icon designers: under the search term
|
||||
"departments," there may be no relevant icons or only unsuitable ones. Depending on the icon source,
|
||||
it might be more effective to search for "buildings," for instance. LLMs assist you with both steps.
|
||||
""";
|
||||
|
||||
protected override string SystemPrompt =>
|
||||
"""
|
||||
I can search for icons using US English keywords. Please help me come up with the right search queries.
|
||||
I don't want you to translate my requests word-for-word into US English. Instead, you should provide keywords
|
||||
that are likely to yield suitable icons. For example, I might ask for an icon about departments, but icons
|
||||
related to the keyword "buildings" might be the best match. Provide your keywords in a Markdown list without
|
||||
quotation marks.
|
||||
""";
|
||||
|
||||
private string? ValidatingContext(string context)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(context))
|
||||
return "Please provide a context. This will help the AI to find the right icon. You might type just a keyword or copy a sentence from your text, e.g., from a slide where you want to use the icon.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidatingProvider(AIStudio.Settings.Provider provider)
|
||||
{
|
||||
if(provider.UsedProvider == Providers.NONE)
|
||||
return "Please select a provider.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task FindIcon()
|
||||
{
|
||||
await this.form!.Validate();
|
||||
if (!this.inputIsValid)
|
||||
return;
|
||||
|
||||
this.CreateChatThread();
|
||||
var time = this.AddUserRequest(
|
||||
$"""
|
||||
{this.selectedIconSource.Prompt()} I search for an icon for the following context:
|
||||
|
||||
```
|
||||
{this.inputContext}
|
||||
```
|
||||
""");
|
||||
|
||||
await this.AddAIResponseAsync(time);
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
namespace AIStudio.Components.Pages.IconFinder;
|
||||
|
||||
public static class IconSourceExtensions
|
||||
{
|
||||
public static string Name(this IconSources iconSource) => iconSource switch
|
||||
{
|
||||
IconSources.FLAT_ICON => "Flaticon",
|
||||
IconSources.FONT_AWESOME => "Font Awesome",
|
||||
IconSources.MATERIAL_ICONS => "Material Icons",
|
||||
IconSources.FEATHER_ICONS => "Feather Icons",
|
||||
IconSources.BOOTSTRAP_ICONS => "Bootstrap Icons",
|
||||
IconSources.ICONS8 => "Icons8",
|
||||
|
||||
_ => "Generic",
|
||||
};
|
||||
|
||||
public static string Prompt(this IconSources iconSource) => iconSource switch
|
||||
{
|
||||
IconSources.FLAT_ICON => "My icon source is Flaticon.",
|
||||
IconSources.FONT_AWESOME => "I look for an icon on Font Awesome. Please provide just valid icon names. Valid icon names are using the format `fa-icon-name`.",
|
||||
IconSources.MATERIAL_ICONS => "I look for a Material icon. Please provide just valid icon names. Valid icon names are using the format `IconName`.",
|
||||
IconSources.FEATHER_ICONS => "My icon source is Feather Icons. Please provide just valid icon names. Valid icon names usiing the format `icon-name`.",
|
||||
IconSources.BOOTSTRAP_ICONS => "I look for an icon for Bootstrap. Please provide just valid icon names. Valid icon names are using the format `bi-icon-name`.",
|
||||
IconSources.ICONS8 => "I look for an icon on Icons8.",
|
||||
|
||||
_ => string.Empty,
|
||||
};
|
||||
|
||||
public static string URL(this IconSources iconSource) => iconSource switch
|
||||
{
|
||||
IconSources.FLAT_ICON => "https://www.flaticon.com/",
|
||||
IconSources.FONT_AWESOME => "https://fontawesome.com/",
|
||||
IconSources.MATERIAL_ICONS => "https://material.io/resources/icons/",
|
||||
IconSources.FEATHER_ICONS => "https://feathericons.com/",
|
||||
IconSources.BOOTSTRAP_ICONS => "https://icons.getbootstrap.com/",
|
||||
IconSources.ICONS8 => "https://icons8.com/",
|
||||
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
namespace AIStudio.Components.Pages.IconFinder;
|
||||
|
||||
public enum IconSources
|
||||
{
|
||||
GENERIC,
|
||||
|
||||
ICONS8,
|
||||
FLAT_ICON,
|
||||
FONT_AWESOME,
|
||||
MATERIAL_ICONS,
|
||||
FEATHER_ICONS,
|
||||
BOOTSTRAP_ICONS,
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
@page "/assistant/summarizer"
|
||||
@using AIStudio.Settings
|
||||
@using AIStudio.Tools
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3"/>
|
||||
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
|
||||
<MudSelect T="CommonLanguages" @bind-Value="@this.selectedTargetLanguage" AdornmentIcon="@Icons.Material.Filled.Translate" Adornment="Adornment.Start" Label="Target language" Variant="Variant.Outlined" Margin="Margin.Dense">
|
||||
@foreach (var targetLanguage in Enum.GetValues<CommonLanguages>())
|
||||
{
|
||||
<MudSelectItem Value="@targetLanguage">@targetLanguage.Name()</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.selectedTargetLanguage is CommonLanguages.OTHER)
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.customTargetLanguage" Validation="@this.ValidateCustomLanguage" Label="Custom target language" Variant="Variant.Outlined" Margin="Margin.Dense"/>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
|
||||
<MudSelect T="Complexity" @bind-Value="@this.selectedComplexity" AdornmentIcon="@Icons.Material.Filled.Layers" Adornment="Adornment.Start" Label="Target complexity" Variant="Variant.Outlined" Margin="Margin.Dense">
|
||||
@foreach (var targetComplexity in Enum.GetValues<Complexity>())
|
||||
{
|
||||
<MudSelectItem Value="@targetComplexity">@targetComplexity.Name()</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.selectedComplexity is Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS)
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.expertInField" Validation="@this.ValidateExpertInField" Label="Your expertise" Variant="Variant.Outlined" Margin="Margin.Dense"/>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
<MudSelect T="Provider" @bind-Value="@this.selectedProvider" Validation="@this.ValidatingProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-3 rounded-lg" Variant="Variant.Outlined">
|
||||
@foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
{
|
||||
<MudSelectItem Value="@provider"/>
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.SummarizeText()">
|
||||
Summarize
|
||||
</MudButton>
|
@ -0,0 +1,86 @@
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.TextSummarizer;
|
||||
|
||||
public partial class AssistantTextSummarizer : AssistantBaseCore
|
||||
{
|
||||
protected override string Title => "Text Summarizer";
|
||||
|
||||
protected override string Description =>
|
||||
"""
|
||||
Summarize long text into a shorter version while retaining the main points.
|
||||
You might want to change the language of the summary to make it more readable.
|
||||
It is also possible to change the complexity of the summary to make it
|
||||
easy to understand.
|
||||
""";
|
||||
|
||||
protected override string SystemPrompt =>
|
||||
"""
|
||||
You get a long text as input. The user wants to get a summary of the text.
|
||||
The user might want to change the language of the summary. In this case,
|
||||
you should provide a summary in the requested language. Eventually, the user
|
||||
want to change the complexity of the text. In this case, you should provide
|
||||
a summary with the requested complexity. In any case, do not add any information.
|
||||
""";
|
||||
|
||||
private string inputText = string.Empty;
|
||||
private CommonLanguages selectedTargetLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private Complexity selectedComplexity;
|
||||
private string expertInField = string.Empty;
|
||||
|
||||
private string? ValidatingText(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? ValidatingProvider(AIStudio.Settings.Provider provider)
|
||||
{
|
||||
if(provider.UsedProvider == Providers.NONE)
|
||||
return "Please select a provider.";
|
||||
|
||||
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? ValidateExpertInField(string field)
|
||||
{
|
||||
if(this.selectedComplexity == Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS && string.IsNullOrWhiteSpace(field))
|
||||
return "Please provide your field of expertise.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task SummarizeText()
|
||||
{
|
||||
await this.form!.Validate();
|
||||
if (!this.inputIsValid)
|
||||
return;
|
||||
|
||||
this.CreateChatThread();
|
||||
var time = this.AddUserRequest(
|
||||
$"""
|
||||
{this.selectedTargetLanguage.Prompt(this.customTargetLanguage)}
|
||||
{this.selectedComplexity.Prompt(this.expertInField)}
|
||||
|
||||
Please summarize the following text:
|
||||
|
||||
```
|
||||
{this.inputText}
|
||||
```
|
||||
""");
|
||||
|
||||
await this.AddAIResponseAsync(time);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.TextSummarizer;
|
||||
|
||||
public static class CommonLanguagePrompts
|
||||
{
|
||||
public static string Prompt(this CommonLanguages language, string customLanguage) => language switch
|
||||
{
|
||||
CommonLanguages.AS_IS => "Do not change the language of the text.",
|
||||
CommonLanguages.OTHER => $"Output you summary in {customLanguage}.",
|
||||
|
||||
_ => $"Output your summary in {language.Name()} ({language}).",
|
||||
};
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
namespace AIStudio.Components.Pages.TextSummarizer;
|
||||
|
||||
public enum Complexity
|
||||
{
|
||||
NO_CHANGE,
|
||||
|
||||
SIMPLE_LANGUAGE,
|
||||
TEEN_LANGUAGE,
|
||||
EVERYDAY_LANGUAGE,
|
||||
POPULAR_SCIENCE_LANGUAGE,
|
||||
SCIENTIFIC_LANGUAGE_FIELD_EXPERTS,
|
||||
SCIENTIFIC_LANGUAGE_OTHER_EXPERTS,
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
namespace AIStudio.Components.Pages.TextSummarizer;
|
||||
|
||||
public static class ComplexityExtensions
|
||||
{
|
||||
public static string Name(this Complexity complexity) => complexity switch
|
||||
{
|
||||
Complexity.NO_CHANGE => "No change in complexity",
|
||||
|
||||
Complexity.SIMPLE_LANGUAGE => "Simple language, e.g., for children",
|
||||
Complexity.TEEN_LANGUAGE => "Teen language, e.g., for teenagers",
|
||||
Complexity.EVERYDAY_LANGUAGE => "Everyday language, e.g., for adults",
|
||||
Complexity.POPULAR_SCIENCE_LANGUAGE => "Popular science language, e.g., for people interested in science",
|
||||
Complexity.SCIENTIFIC_LANGUAGE_FIELD_EXPERTS => "Scientific language for experts in this field",
|
||||
Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS => "Scientific language for experts from other fields (interdisciplinary)",
|
||||
|
||||
_ => "No change in complexity",
|
||||
};
|
||||
|
||||
public static string Prompt(this Complexity complexity, string expertInField) => complexity switch
|
||||
{
|
||||
Complexity.NO_CHANGE => "Do not change the complexity of the text.",
|
||||
|
||||
Complexity.SIMPLE_LANGUAGE => "Simplify the language, e.g., for 8 to 12-year-old children. Might use short sentences and simple words. You could use analogies to explain complex terms.",
|
||||
Complexity.TEEN_LANGUAGE => "Use a language suitable for teenagers, e.g., 16 to 19 years old. Might use teenage slang and analogies to explain complex terms.",
|
||||
Complexity.EVERYDAY_LANGUAGE => "Use everyday language suitable for adults. Avoid specific scientific terms. Use everday analogies to explain complex terms.",
|
||||
Complexity.POPULAR_SCIENCE_LANGUAGE => "Use popular science language, e.g., for people interested in science. The text should be easy to understand, though. Use analogies to explain complex terms.",
|
||||
Complexity.SCIENTIFIC_LANGUAGE_FIELD_EXPERTS => "Use scientific language for experts in the field of the texts subject. Use specific terms for this field.",
|
||||
Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS => $"The reader is an expert in {expertInField}. Change the language so that it is suitable. Explain specific terms, so that the reader within his field can understand the text. You might use analogies to explain complex terms.",
|
||||
|
||||
_ => "Do not change the complexity of the text.",
|
||||
};
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
@page "/assistant/translator"
|
||||
@using AIStudio.Settings
|
||||
@using AIStudio.Tools
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudField Label="Live translation" Variant="Variant.Outlined" Class="mb-3">
|
||||
<MudSwitch T="bool" @bind-Value="@this.liveTranslation">
|
||||
@(this.liveTranslation ? "Live translation" : "No live translation")
|
||||
</MudSwitch>
|
||||
</MudField>
|
||||
|
||||
@if (this.liveTranslation)
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" Immediate="@true" DebounceInterval="1_000" OnDebounceIntervalElapsed="() => this.TranslateText(force: false)"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" />
|
||||
}
|
||||
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
|
||||
<MudSelect T="CommonLanguages" @bind-Value="@this.selectedTargetLanguage" Validation="@this.ValidatingTargetLanguage" AdornmentIcon="@Icons.Material.Filled.Translate" Adornment="Adornment.Start" Label="Target language" Variant="Variant.Outlined" Margin="Margin.Dense">
|
||||
@foreach (var targetLanguage in Enum.GetValues<CommonLanguages>())
|
||||
{
|
||||
if (targetLanguage is CommonLanguages.AS_IS)
|
||||
{
|
||||
<MudSelectItem Value="@targetLanguage">Please select the target language</MudSelectItem>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudSelectItem Value="@targetLanguage">@targetLanguage.Name()</MudSelectItem>
|
||||
}
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.selectedTargetLanguage is CommonLanguages.OTHER)
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.customTargetLanguage" Validation="@this.ValidateCustomLanguage" Label="Custom target language" Variant="Variant.Outlined" Margin="Margin.Dense"/>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
<MudSelect T="Provider" @bind-Value="@this.selectedProvider" Validation="@this.ValidatingProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-3 rounded-lg" Variant="Variant.Outlined">
|
||||
@foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
{
|
||||
<MudSelectItem Value="@provider"/>
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.TranslateText(force: true)">
|
||||
Translate
|
||||
</MudButton>
|
@ -0,0 +1,83 @@
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.Translator;
|
||||
|
||||
public partial class AssistantTranslator : AssistantBaseCore
|
||||
{
|
||||
protected override string Title => "Translator";
|
||||
|
||||
protected override string Description =>
|
||||
"""
|
||||
Translate text from one language to another.
|
||||
""";
|
||||
|
||||
protected override string SystemPrompt =>
|
||||
"""
|
||||
You get text in a source language as input. The user wants to get the text translated into a target language.
|
||||
Provide the translation in the requested language. Do not add any information. Correct any spelling or grammar mistakes.
|
||||
Do not ask for additional information. Do not mirror the user's language. Do not mirror the task. When the target
|
||||
language requires, e.g., shorter sentences, you should split the text into shorter sentences.
|
||||
""";
|
||||
|
||||
private bool liveTranslation;
|
||||
private string inputText = string.Empty;
|
||||
private string inputTextLastTranslation = string.Empty;
|
||||
private CommonLanguages selectedTargetLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
|
||||
private string? ValidatingText(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? ValidatingProvider(AIStudio.Settings.Provider provider)
|
||||
{
|
||||
if(provider.UsedProvider == Providers.NONE)
|
||||
return "Please select a provider.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidatingTargetLanguage(CommonLanguages language)
|
||||
{
|
||||
if(language == CommonLanguages.AS_IS)
|
||||
return "Please select a target language.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateCustomLanguage(string language)
|
||||
{
|
||||
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
|
||||
return "Please provide a custom language.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task TranslateText(bool force)
|
||||
{
|
||||
if (!this.inputIsValid)
|
||||
return;
|
||||
|
||||
if(!force && this.inputText == this.inputTextLastTranslation)
|
||||
return;
|
||||
|
||||
this.inputTextLastTranslation = this.inputText;
|
||||
this.CreateChatThread();
|
||||
var time = this.AddUserRequest(
|
||||
$"""
|
||||
{this.selectedTargetLanguage.Prompt(this.customTargetLanguage)}
|
||||
|
||||
The given text is:
|
||||
|
||||
---
|
||||
{this.inputText}
|
||||
""");
|
||||
|
||||
await this.AddAIResponseAsync(time);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.Translator;
|
||||
|
||||
public static class CommonLanguageExtension
|
||||
{
|
||||
public static string Prompt(this CommonLanguages language, string customLanguage) => language switch
|
||||
{
|
||||
CommonLanguages.OTHER => $"Translate the text in {customLanguage}.",
|
||||
|
||||
_ => $"Translate the given text in {language.Name()} ({language}).",
|
||||
};
|
||||
}
|
22
app/MindWork AI Studio/Tools/CommonLanguageExtensions.cs
Normal file
22
app/MindWork AI Studio/Tools/CommonLanguageExtensions.cs
Normal file
@ -0,0 +1,22 @@
|
||||
namespace AIStudio.Tools;
|
||||
|
||||
public static class CommonLanguageExtensions
|
||||
{
|
||||
public static string Name(this CommonLanguages language) => language switch
|
||||
{
|
||||
CommonLanguages.AS_IS => "Do not change the language",
|
||||
|
||||
CommonLanguages.EN_US => "English (US)",
|
||||
CommonLanguages.EN_GB => "English (UK)",
|
||||
CommonLanguages.ZH_CN => "Chinese (Simplified)",
|
||||
CommonLanguages.HI_IN => "Hindi (India)",
|
||||
CommonLanguages.ES_ES => "Spanish (Spain)",
|
||||
CommonLanguages.FR_FR => "French (France)",
|
||||
CommonLanguages.DE_DE => "German (Germany)",
|
||||
CommonLanguages.DE_AT => "German (Austria)",
|
||||
CommonLanguages.DE_CH => "German (Switzerland)",
|
||||
CommonLanguages.JA_JP => "Japanese (Japan)",
|
||||
|
||||
_ => "Other",
|
||||
};
|
||||
}
|
19
app/MindWork AI Studio/Tools/CommonLanguages.cs
Normal file
19
app/MindWork AI Studio/Tools/CommonLanguages.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace AIStudio.Tools;
|
||||
|
||||
public enum CommonLanguages
|
||||
{
|
||||
AS_IS,
|
||||
|
||||
EN_US,
|
||||
EN_GB,
|
||||
ZH_CN,
|
||||
HI_IN,
|
||||
ES_ES,
|
||||
FR_FR,
|
||||
DE_DE,
|
||||
DE_CH,
|
||||
DE_AT,
|
||||
JA_JP,
|
||||
|
||||
OTHER,
|
||||
}
|
5
app/MindWork AI Studio/wwwroot/changelog/v0.8.0.md
Normal file
5
app/MindWork AI Studio/wwwroot/changelog/v0.8.0.md
Normal file
@ -0,0 +1,5 @@
|
||||
# v0.8.0, build 162 (2024-07-14 19:39 UTC)
|
||||
- Added overview of assistants
|
||||
- Added icon finder assistant
|
||||
- Added text summarization assistant
|
||||
- Added translation assistant
|
@ -1,9 +1,9 @@
|
||||
0.7.1
|
||||
2024-07-13 11:42:46 UTC
|
||||
161
|
||||
0.8.0
|
||||
2024-07-14 19:39:09 UTC
|
||||
162
|
||||
8.0.107 (commit 1bdaef7265)
|
||||
8.0.7 (commit 2aade6beb0)
|
||||
1.79.0 (commit 129f3b996)
|
||||
6.20.0
|
||||
1.6.1
|
||||
d781e48ae66, release
|
||||
ba6610bd964, release
|
||||
|
2
runtime/Cargo.lock
generated
2
runtime/Cargo.lock
generated
@ -2313,7 +2313,7 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "mindwork-ai-studio"
|
||||
version = "0.7.1"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"arboard",
|
||||
"flexi_logger",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mindwork-ai-studio"
|
||||
version = "0.7.1"
|
||||
version = "0.8.0"
|
||||
edition = "2021"
|
||||
description = "MindWork AI Studio"
|
||||
authors = ["Thorsten Sommer"]
|
||||
|
@ -6,7 +6,7 @@
|
||||
},
|
||||
"package": {
|
||||
"productName": "MindWork AI Studio",
|
||||
"version": "0.7.1"
|
||||
"version": "0.8.0"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
|
Loading…
Reference in New Issue
Block a user