From 146cf8380dcef080cb2ac3c6e45a8a25710c83ea Mon Sep 17 00:00:00 2001 From: Peer Hogeterp Date: Tue, 22 Sep 2026 20:03:08 +0200 Subject: [PATCH] Added iterative prompt refinement action (#994) Co-authored-by: Thorsten Sommer --- .../Assistants/AssistantBase.razor.cs | 4 +-- .../Assistants/AssistantLowerBase.cs | 14 +++++++++ .../Assistants/I18N/allTexts.lua | 6 ++++ .../AssistantPromptOptimizer.razor.cs | 31 +++++++++++++++++++ .../plugin.lua | 6 ++++ .../plugin.lua | 6 ++++ .../wwwroot/changelog/v26.9.1.md | 1 + 7 files changed, 65 insertions(+), 3 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs index 4d6fde09..f655ea77 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs @@ -753,9 +753,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher await this.AssistantSessionService.ClearAsync(this.assistantSessionKey); this.MediaTranscriptionService.ClearOwnerState(this.CurrentMediaImportOwner); this.assistantSessionId = null; - this.ChatThread = null; - this.LastUserPrompt = null; - this.ResultingContentBlock = null; + this.ClearConversationState(); this.ProviderSettings = Settings.Provider.NONE; await this.JsRuntime.ClearDiv(BEFORE_RESULT_DIV_ID); diff --git a/app/MindWork AI Studio/Assistants/AssistantLowerBase.cs b/app/MindWork AI Studio/Assistants/AssistantLowerBase.cs index fff83be6..bfde4c2d 100644 --- a/app/MindWork AI Studio/Assistants/AssistantLowerBase.cs +++ b/app/MindWork AI Studio/Assistants/AssistantLowerBase.cs @@ -34,4 +34,18 @@ public abstract class AssistantLowerBase : MSGComponentBase protected ContentBlock? ResultingContentBlock; protected string[] InputIssues = []; protected bool IsProcessing; + + /// + /// Clears everything one assistant run has produced. + /// + /// + /// Assistants call this whenever the previous run must not carry over: a follow-up run would + /// otherwise append to the old chat thread, and the old result would stay on screen. + /// + protected void ClearConversationState() + { + this.ChatThread = null; + this.LastUserPrompt = null; + this.ResultingContentBlock = null; + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 1b2d074f..f09f9d56 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -2191,6 +2191,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER -- View UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1582017048"] = "View" +-- Improve further +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1582753277"] = "Improve further" + -- Separate context, task, constraints, and output format with headings or markers. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1626024580"] = "Separate context, task, constraints, and output format with headings or markers." @@ -2287,6 +2290,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER -- Use sequential steps UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T487578804"] = "Use sequential steps" +-- Moves the optimized prompt into the prompt field so you can optimize it again. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T502438377"] = "Moves the optimized prompt into the prompt field so you can optimize it again." + -- Use clear, explicit instructions and directly state quality expectations. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T596557540"] = "Use clear, explicit instructions and directly state quality expectations." diff --git a/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor.cs b/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor.cs index 63238103..ae86f9d0 100644 --- a/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor.cs +++ b/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor.cs @@ -101,6 +101,15 @@ public partial class AssistantPromptOptimizer : AssistantBaseCore FooterButtons => [ + new ButtonData + { + Text = T("Improve further"), + Tooltip = T("Moves the optimized prompt into the prompt field so you can optimize it again."), + Icon = Icons.Material.Filled.Input, + Color = Color.Default, + AsyncAction = this.UseOptimizedPromptAsInput, + DisabledActionParam = () => !this.CanImproveFurther, + }, new SendToButton { Self = Tools.Components.PROMPT_OPTIMIZER_ASSISTANT, @@ -245,6 +254,7 @@ public partial class AssistantPromptOptimizer : AssistantBaseCore !this.useCustomPromptGuide && this.hasUpdatedDefaultRecommendations; private bool CanPreviewCustomPromptGuide => this.useCustomPromptGuide && this.customPromptGuideFiles.Count > 0; + private bool CanImproveFurther => !this.IsProcessing && !string.IsNullOrWhiteSpace(this.optimizedPrompt); private string CustomPromptGuideFileName => this.customPromptGuideFiles.Count switch { 0 => T("No file selected"), @@ -464,6 +474,27 @@ public partial class AssistantPromptOptimizer : AssistantBaseCore + /// Moves the optimized prompt into the input field so the user can optimize it once more. + /// + /// + /// The finished run is dropped along the way. Keeping it would append the next optimization to + /// the chat thread of the previous one, and the earlier proposal would stay on screen next to + /// the prompt it was already turned into. The recommendations and every selection stay as they + /// are, though: they are what the user works with while refining the prompt. + /// + private Task UseOptimizedPromptAsInput() + { + if (!this.CanImproveFurther) + return Task.CompletedTask; + + this.inputPrompt = this.optimizedPrompt; + this.ResetOutput(); + this.ClearConversationState(); + this.ClearInputIssues(); + return Task.CompletedTask; + } + private void ResetGuidelineSummaryToDefault() { this.recClarityDirectness = T("Use clear, explicit instructions and directly state quality expectations."); diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index 453d690a..8b52aa1d 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -2193,6 +2193,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER -- View UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1582017048"] = "Anzeigen" +-- Improve further +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1582753277"] = "Weiter verbessern" + -- Separate context, task, constraints, and output format with headings or markers. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1626024580"] = "Trennen Sie Kontext, Aufgabe, Einschränkungen und Ausgabeformat mit Überschriften oder Markierungen." @@ -2289,6 +2292,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER -- Use sequential steps UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T487578804"] = "Schrittweise vorgehen" +-- Moves the optimized prompt into the prompt field so you can optimize it again. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T502438377"] = "Übernimmt den optimierten Prompt als neue Eingabe, damit Sie ihn erneut optimieren können." + -- Use clear, explicit instructions and directly state quality expectations. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T596557540"] = "Verwenden Sie klare, explizite Anweisungen und geben Sie direkt die Qualitätsmerkmale an." diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index 1e1ef9ed..8ef7f094 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -2193,6 +2193,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER -- View UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1582017048"] = "View" +-- Improve further +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1582753277"] = "Improve further" + -- Separate context, task, constraints, and output format with headings or markers. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1626024580"] = "Separate context, task, constraints, and output format with headings or markers." @@ -2289,6 +2292,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER -- Use sequential steps UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T487578804"] = "Use sequential steps" +-- Moves the optimized prompt into the prompt field so you can optimize it again. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T502438377"] = "Moves the optimized prompt into the prompt field so you can optimize it again." + -- Use clear, explicit instructions and directly state quality expectations. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T596557540"] = "Use clear, explicit instructions and directly state quality expectations." diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md index c6cdc326..79853800 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md @@ -12,6 +12,7 @@ - Added organization-wide management for tools. Among other options, IT departments can switch tools off entirely, disable individual ones, or define the provider trust a tool requires. You do not have to write any of it by hand: set a tool up in the app, then export its configuration as ready-made Lua code for your plugin, with encrypted API keys if you want them. - Added tool calling to the abilities you can state yourself in the expert provider settings. When you use a model AI Studio does not recognize as tool-capable, you can now declare that it is, the same way you already could for image input or reasoning. It works in the other direction as well: a model AI Studio has never heard of is offered tools, because most models can use them by now. Should one turn out not to be able to, AI Studio says so in plain words and points you to the same setting to switch the ability off again, instead of only passing the provider's error on. - Added support for OpenAI's GPT-6 Astra. +- Added a way to keep improving a prompt in the Prompt Optimizer. Select "Improve further" to move the latest proposal back into the prompt field, edit it the way you want, and optimize it again. Your recommendations and everything you selected stay as they are. - Added the context window to what AI Studio knows about a model, wherever its metadata states one. - Added a live read of that context window at the providers which report it, among them Mistral, Groq, OpenRouter, and self-hosted vLLM servers. You then get the window your own server was started with, not the one the model card advertises. - Added a token count below the message field, so you always see how much of the conversation you have used. It counts everything that travels along: your messages, the files you attached, what your data sources contributed, and the tools you offered the AI. It can be an estimate when a provider does not give AI Studio everything it needs to count exactly.