diff --git a/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor
new file mode 100644
index 00000000..a7b8132d
--- /dev/null
+++ b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor
@@ -0,0 +1,68 @@
+@page "/assistant/icons"
+@using AIStudio.Chat
+@using AIStudio.Settings
+
+
+ Icon Finder
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+ @foreach (var source in Enum.GetValues())
+ {
+ @source.Name()
+ }
+
+ @if (this.selectedIconSource is not IconSources.GENERIC)
+ {
+ Open website
+ }
+
+
+
+ @foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
+ {
+
+ }
+
+
+
+ Find icons
+
+
+
+ @if (this.inputIssues.Any())
+ {
+
+ Issues
+
+ @foreach (var issue in this.inputIssues)
+ {
+
+ @issue
+
+ }
+
+
+ }
+
+ @if (this.resultingContentBlock is not null)
+ {
+
+ }
+
+
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs
new file mode 100644
index 00000000..4f173f7e
--- /dev/null
+++ b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs
@@ -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.
+ """;
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/Pages/IconFinder/IconSourceExtensions.cs b/app/MindWork AI Studio/Components/Pages/IconFinder/IconSourceExtensions.cs
new file mode 100644
index 00000000..42acf8cf
--- /dev/null
+++ b/app/MindWork AI Studio/Components/Pages/IconFinder/IconSourceExtensions.cs
@@ -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,
+ };
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/Pages/IconFinder/IconSources.cs b/app/MindWork AI Studio/Components/Pages/IconFinder/IconSources.cs
new file mode 100644
index 00000000..fe477f9f
--- /dev/null
+++ b/app/MindWork AI Studio/Components/Pages/IconFinder/IconSources.cs
@@ -0,0 +1,13 @@
+namespace AIStudio.Components.Pages.IconFinder;
+
+public enum IconSources
+{
+ GENERIC,
+
+ ICONS8,
+ FLAT_ICON,
+ FONT_AWESOME,
+ MATERIAL_ICONS,
+ FEATHER_ICONS,
+ BOOTSTRAP_ICONS,
+}
\ No newline at end of file