mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-04-28 15:39:46 +00:00
Implemented the icon finder assistant
This commit is contained in:
parent
1f31dc70a0
commit
a5ebce4815
@ -0,0 +1,68 @@
|
|||||||
|
@page "/assistant/icons"
|
||||||
|
@using AIStudio.Chat
|
||||||
|
@using AIStudio.Settings
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
|
||||||
|
Icon Finder
|
||||||
|
</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">
|
||||||
|
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.
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudTextField T="string" @bind-Text="@this.inputContext" Validation="@this.ValidatingContext" AdornmentIcon="@Icons.Material.Filled.TextFields" Adornment="Adornment.Start" Label="Yout 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 icons
|
||||||
|
</MudButton>
|
||||||
|
</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>
|
@ -0,0 +1,134 @@
|
|||||||
|
using AIStudio.Chat;
|
||||||
|
using AIStudio.Provider;
|
||||||
|
using AIStudio.Settings;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Components.Pages.IconFinder;
|
||||||
|
|
||||||
|
public partial class AssistantIconFinder : ComponentBase
|
||||||
|
{
|
||||||
|
[Inject]
|
||||||
|
private SettingsManager SettingsManager { get; set; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public IJSRuntime JsRuntime { get; init; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public Random RNG { get; set; } = null!;
|
||||||
|
|
||||||
|
private ChatThread? chatThread;
|
||||||
|
private ContentBlock? resultingContentBlock;
|
||||||
|
private AIStudio.Settings.Provider selectedProvider;
|
||||||
|
private MudForm form = null!;
|
||||||
|
private bool inputIsValid;
|
||||||
|
private string[] inputIssues = [];
|
||||||
|
private string inputContext = string.Empty;
|
||||||
|
private IconSources selectedIconSource;
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create a new chat thread:
|
||||||
|
//
|
||||||
|
this.chatThread = new()
|
||||||
|
{
|
||||||
|
WorkspaceId = Guid.Empty,
|
||||||
|
ChatId = Guid.NewGuid(),
|
||||||
|
Name = string.Empty,
|
||||||
|
Seed = this.RNG.Next(),
|
||||||
|
SystemPrompt = SYSTEM_PROMPT,
|
||||||
|
Blocks = [],
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add the user's request to the thread:
|
||||||
|
//
|
||||||
|
var time = DateTimeOffset.Now;
|
||||||
|
this.chatThread.Blocks.Add(new ContentBlock
|
||||||
|
{
|
||||||
|
Time = time,
|
||||||
|
ContentType = ContentType.TEXT,
|
||||||
|
Role = ChatRole.USER,
|
||||||
|
Content = new ContentText
|
||||||
|
{
|
||||||
|
Text =
|
||||||
|
$"""
|
||||||
|
{this.selectedIconSource.Prompt()} I search for an icon for the following context:
|
||||||
|
|
||||||
|
```
|
||||||
|
{this.inputContext}
|
||||||
|
```
|
||||||
|
""",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add the AI response to the thread:
|
||||||
|
//
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string SYSTEM_PROMPT =
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
""";
|
||||||
|
}
|
@ -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,
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user