diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index 60963a27..60b4b947 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -976,25 +976,36 @@ jobs: FORMATTED_BUILD_TIME: ${{ needs.read_metadata.outputs.formatted_build_time }} CHANGELOG: ${{ needs.read_metadata.outputs.changelog }} - run: | + run: | # Read the platforms JSON, which was created in the previous step: platforms=$(cat $GITHUB_WORKSPACE/.updates/platforms.json) - - # Replace newlines in changelog with \n - changelog=$(echo "$CHANGELOG" | awk '{printf "%s\\n", $0}') - - # Escape double quotes in changelog: - changelog=$(echo "$changelog" | sed 's/"/\\"/g') - - # Create the latest.json file: - cat < $GITHUB_WORKSPACE/release/assets/latest.json - { - "version": "$FORMATTED_VERSION", - "notes": "$changelog", - "pub_date": "$FORMATTED_BUILD_TIME", - "platforms": $platforms - } - EOOOF + + # Create the latest.json file via jq so the changelog is escaped as valid JSON. + jq -n \ + --arg version "$FORMATTED_VERSION" \ + --arg notes "$CHANGELOG" \ + --arg pub_date "$FORMATTED_BUILD_TIME" \ + --argjson platforms "$platforms" \ + '{ + version: $version, + notes: $notes, + pub_date: $pub_date, + platforms: $platforms + }' > $GITHUB_WORKSPACE/release/assets/latest.json + + - name: Validate latest.json + env: + CHANGELOG: ${{ needs.read_metadata.outputs.changelog }} + + run: | + # Ensure the generated file is valid JSON and the changelog round-trips unchanged. + jq -e . $GITHUB_WORKSPACE/release/assets/latest.json > /dev/null + + generated_notes=$(jq -r '.notes' $GITHUB_WORKSPACE/release/assets/latest.json) + if [[ "$generated_notes" != "$CHANGELOG" ]]; then + echo "The generated notes field does not match the changelog input." + exit 1 + fi - name: Show all release assets run: ls -Rlhat $GITHUB_WORKSPACE/release/assets diff --git a/AGENTS.md b/AGENTS.md index 6bf4eb5f..7908fdcd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -186,6 +186,7 @@ Multi-level confidence scheme allows users to control which providers see which - **File changes require Write/Edit tools** - Never use bash commands like `cat <` - **End of file formatting** - Do not append an extra empty line at the end of files. +- **No automated formatting for Rust or .NET files** - Never run automated formatters on Rust files (`.rs`) or .NET files (`.cs`, `.razor`, `.csproj`, etc.). Only make the minimal manual formatting changes required for the specific edit. - **Spaces in paths** - Always quote paths with spaces in bash commands - **Agent-run .NET builds** - Do not run `.NET` builds from an agent. Ask the user to run the build locally in their IDE, preferably via `cd app/Build && dotnet run build` in an IDE terminal, then wait for their feedback before continuing. - **Debug environment** - Reads `startup.env` file with IPC credentials diff --git a/README.md b/README.md index a594ff41..5b69c065 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Since March 2025: We have started developing the plugin system. There will be la - [x] ~~Provide MindWork AI Studio in German ([PR #430](https://github.com/MindWorkAI/AI-Studio/pull/430), [PR #446](https://github.com/MindWorkAI/AI-Studio/pull/446), [PR #451](https://github.com/MindWorkAI/AI-Studio/pull/451), [PR #455](https://github.com/MindWorkAI/AI-Studio/pull/455), [PR #458](https://github.com/MindWorkAI/AI-Studio/pull/458), [PR #462](https://github.com/MindWorkAI/AI-Studio/pull/462), [PR #469](https://github.com/MindWorkAI/AI-Studio/pull/469), [PR #486](https://github.com/MindWorkAI/AI-Studio/pull/486))~~ - [x] ~~Add configuration plugins, which allow pre-defining some LLM providers in organizations ([PR #491](https://github.com/MindWorkAI/AI-Studio/pull/491), [PR #493](https://github.com/MindWorkAI/AI-Studio/pull/493), [PR #494](https://github.com/MindWorkAI/AI-Studio/pull/494), [PR #497](https://github.com/MindWorkAI/AI-Studio/pull/497))~~ - [ ] Add an app store for plugins, showcasing community-contributed plugins from public GitHub and GitLab repositories. This will enable AI Studio users to discover, install, and update plugins directly within the platform. -- [ ] Add assistant plugins ([PR #659](https://github.com/MindWorkAI/AI-Studio/pull/659)) +- [x] ~~Add assistant plugins ([PR #659](https://github.com/MindWorkAI/AI-Studio/pull/659))~~ @@ -79,6 +79,7 @@ Since March 2025: We have started developing the plugin system. There will be la +- v26.4.1: Added support for the latest AI models, assistant plugins, a slide planner assistant, a prompt optimization assistant, math rendering in chats, and a configurable start page; released the document analysis assistant and improved enterprise deployment, chat performance, file attachments, and reliability across voice recording, logging, and provider validation. - v26.2.2: Added Qdrant as a building block for our local RAG preview, added an embedding test option to validate embedding providers, and improved enterprise and configuration plugins with preselected providers, additive preview features, support for multiple configurations, and more reliable synchronization. - v26.1.1: Added the option to attach files, including images, to chat templates; added support for source code file attachments in chats and document analysis; added a preview feature for recording your own voice for transcription; fixed various bugs in provider dialogs and profile selection. - v0.10.0: Added support for newer models like Mistral 3 & GPT 5.2, OpenRouter as LLM and embedding provider, the possibility to use file attachments in chats, and support for images as input. @@ -90,7 +91,6 @@ Since March 2025: We have started developing the plugin system. There will be la - v0.9.40: Added support for the `o4` models from OpenAI. Also, we added Alibaba Cloud & Hugging Face as LLM providers. - v0.9.39: Added the plugin system as a preview feature. - v0.9.31: Added Helmholtz & GWDG as LLM providers. This is a huge improvement for many researchers out there who can use these providers for free. We added DeepSeek as a provider as well. -- v0.9.29: Added agents to support the RAG process (selecting the best data sources & validating retrieved data as part of the augmentation process) diff --git a/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs b/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs index b54beff4..bc306978 100644 --- a/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs +++ b/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs @@ -62,6 +62,7 @@ public sealed class AssistantAuditAgent(ILogger logger, ILo - Pay special attention to risky or abusable Lua basic-library features and global-state primitives such as `load`, `loadfile`, `dofile`, `collectgarbage`, `getmetatable`, `setmetatable`, `rawget`, `rawset`, `rawequal`, `_G`, or patterns that dynamically execute code, inspect or alter hidden state, bypass expected data flow, or make behavior harder to review. - If such Lua features are used in a way that could execute hidden code, mutate runtime behavior, evade review, tamper with guardrails, access unexpected files or modules, or conceal the plugin's real behavior, treat that as strong evidence for at least CAUTION and often DANGEROUS depending on impact and clarity. - When these risky Lua features appear, explicitly evaluate whether their usage is necessary and transparent for the assistant's stated purpose, or whether it creates an unnecessary attack surface even if the manifest otherwise looks benign. + - `LogInfo`, `LogDebug`, `LogWarning`, `LogError`, `InspectTable`, `DateTime` and `Timestamp` are C# helper methods that we provide and usually not necessarily DANGEROUS. Audit the usage and decide if its for Debugging only and if so mark as SAFE. - Mark the plugin as CAUTION only when there is concrete evidence of meaningful risk or ambiguity that deserves manual review. - Mark the plugin as SAFE only when no meaningful risk is apparent from the provided material. - A SAFE result should normally have no findings. Do not add low-value findings just to populate the array. diff --git a/app/MindWork AI Studio/Assistants/Agenda/AssistantAgenda.razor b/app/MindWork AI Studio/Assistants/Agenda/AssistantAgenda.razor index 8056467c..6a620049 100644 --- a/app/MindWork AI Studio/Assistants/Agenda/AssistantAgenda.razor +++ b/app/MindWork AI Studio/Assistants/Agenda/AssistantAgenda.razor @@ -52,4 +52,4 @@ } - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/Agenda/AssistantAgenda.razor.cs b/app/MindWork AI Studio/Assistants/Agenda/AssistantAgenda.razor.cs index 4658a16b..c6513cc2 100644 --- a/app/MindWork AI Studio/Assistants/Agenda/AssistantAgenda.razor.cs +++ b/app/MindWork AI Studio/Assistants/Agenda/AssistantAgenda.razor.cs @@ -1,6 +1,5 @@ using System.Text; -using AIStudio.Chat; using AIStudio.Dialogs.Settings; namespace AIStudio.Assistants.Agenda; @@ -97,10 +96,12 @@ public partial class AssistantAgenda : AssistantBaseCore protected override Func SubmitAction => this.CreateAgenda; - protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with - { - SystemPrompt = SystemPrompts.DEFAULT, - }; + protected override string SendToChatVisibleUserPromptText => + $""" + {string.Format(T("Create an agenda for the meeting '{0}' with the following contents:"), this.inputName)} + + {this.inputContent} + """; protected override void ResetForm() { @@ -322,8 +323,8 @@ public partial class AssistantAgenda : AssistantBaseCore private async Task CreateAgenda() { - await this.form!.Validate(); - if (!this.inputIsValid) + await this.Form!.Validate(); + if (!this.InputIsValid) return; this.CreateChatThread(); diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor b/app/MindWork AI Studio/Assistants/AssistantBase.razor index a0542fcd..59c9f7a2 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor @@ -8,6 +8,13 @@ @this.Title + + + + @if (this.HeaderActions is not null) + { + @this.HeaderActions + } @if (this.HasSettingsPanel) { @@ -17,7 +24,7 @@ - + @this.Description @@ -31,10 +38,10 @@ - + @this.SubmitText - @if (this.isProcessing && this.cancellationTokenSource is not null) + @if (this.isProcessing && this.CancellationTokenSource is not null) { @@ -61,9 +68,9 @@ } - @if(this.ShowResult && this.ShowEntireChatThread && this.chatThread is not null) + @if(this.ShowResult && this.ShowEntireChatThread && this.ChatThread is not null) { - foreach (var block in this.chatThread.Blocks.OrderBy(n => n.Time)) + foreach (var block in this.ChatThread.Blocks.OrderBy(n => n.Time)) { @if (block is { HideFromUser: false, Content: not null }) { @@ -71,6 +78,11 @@ } } } + + @if (this.ShowResult && this.AfterResultContent is not null) + { + @this.AfterResultContent + }
@@ -143,12 +155,12 @@ @if (this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence) { - + } @if (this.AllowProfiles && this.ShowProfileSelection) { - + } diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs index 632722ab..d9b553dd 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs @@ -79,20 +79,46 @@ public abstract partial class AssistantBase : AssistantLowerBase wher protected virtual bool ShowReset => true; - protected virtual ChatThread ConvertToChatThread => this.chatThread ?? new(); + protected virtual string? SendToChatVisibleUserPromptPrefix => null; + + protected virtual string? SendToChatVisibleUserPromptContent => null; + + protected virtual string? SendToChatVisibleUserPromptText + { + get + { + if (string.IsNullOrWhiteSpace(this.SendToChatVisibleUserPromptPrefix)) + return null; + + if (string.IsNullOrWhiteSpace(this.SendToChatVisibleUserPromptContent)) + return this.SendToChatVisibleUserPromptPrefix; + + return $""" + {this.SendToChatVisibleUserPromptPrefix} + + {this.SendToChatVisibleUserPromptContent} + """; + } + } + + protected virtual ChatThread ConvertToChatThread => this.CreateSendToChatThread(); + + private protected virtual RenderFragment? HeaderActions => null; + + private protected virtual RenderFragment? AfterResultContent => null; protected virtual IReadOnlyList FooterButtons => []; protected virtual bool HasSettingsPanel => typeof(TSettings) != typeof(NoSettingsPanel); - protected AIStudio.Settings.Provider providerSettings = Settings.Provider.NONE; - protected MudForm? form; - protected bool inputIsValid; - protected Profile currentProfile = Profile.NO_PROFILE; - protected ChatTemplate currentChatTemplate = ChatTemplate.NO_CHAT_TEMPLATE; - protected ChatThread? chatThread; - protected IContent? lastUserPrompt; - protected CancellationTokenSource? cancellationTokenSource; + protected AIStudio.Settings.Provider ProviderSettings = Settings.Provider.NONE; + protected MudForm? Form; + protected bool InputIsValid; + protected Profile CurrentProfile = Profile.NO_PROFILE; + protected ChatTemplate CurrentChatTemplate = ChatTemplate.NO_CHAT_TEMPLATE; + protected ChatThread? ChatThread; + protected IContent? LastUserPrompt; + protected CancellationTokenSource? CancellationTokenSource; private readonly Timer formChangeTimer = new(TimeSpan.FromSeconds(1.6)); @@ -121,9 +147,9 @@ public abstract partial class AssistantBase : AssistantLowerBase wher }; this.MightPreselectValues(); - this.providerSettings = this.SettingsManager.GetPreselectedProvider(this.Component); - this.currentProfile = this.SettingsManager.GetPreselectedProfile(this.Component); - this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component); + this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(this.Component); + this.CurrentProfile = this.SettingsManager.GetPreselectedProfile(this.Component); + this.CurrentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component); } protected override async Task OnParametersSetAsync() @@ -139,7 +165,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher // 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(); + this.Form?.ResetValidation(); await base.OnAfterRenderAsync(firstRender); } @@ -148,7 +174,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher private string TB(string fallbackEN) => this.T(fallbackEN, typeof(AssistantBase).Namespace, nameof(AssistantBase)); - private string SubmitButtonStyle => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence ? this.providerSettings.UsedLLMProvider.GetConfidence(this.SettingsManager).StyleBorder(this.SettingsManager) : string.Empty; + private string SubmitButtonStyle => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence ? this.ProviderSettings.UsedLLMProvider.GetConfidence(this.SettingsManager).StyleBorder(this.SettingsManager) : string.Empty; private IReadOnlyList VisibleSendToAssistants => Enum.GetValues() .Where(this.CanSendToAssistant) @@ -165,12 +191,12 @@ public abstract partial class AssistantBase : AssistantLowerBase wher private async Task Start() { - using (this.cancellationTokenSource = new()) + using (this.CancellationTokenSource = new()) { await this.SubmitAction(); } - this.cancellationTokenSource = null; + this.CancellationTokenSource = null; } private void TriggerFormChange(FormFieldChangedEventArgs _) @@ -197,7 +223,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher { Array.Resize(ref this.inputIssues, this.inputIssues.Length + 1); this.inputIssues[^1] = issue; - this.inputIsValid = false; + this.InputIsValid = false; this.StateHasChanged(); } @@ -207,17 +233,17 @@ public abstract partial class AssistantBase : AssistantLowerBase wher protected void ClearInputIssues() { this.inputIssues = []; - this.inputIsValid = true; + this.InputIsValid = true; this.StateHasChanged(); } protected void CreateChatThread() { - this.chatThread = new() + this.ChatThread = new() { IncludeDateTime = false, - SelectedProvider = this.providerSettings.Id, - SelectedProfile = this.AllowProfiles ? this.currentProfile.Id : Profile.NO_PROFILE.Id, + SelectedProvider = this.ProviderSettings.Id, + SelectedProfile = this.AllowProfiles ? this.CurrentProfile.Id : Profile.NO_PROFILE.Id, SystemPrompt = this.SystemPrompt, WorkspaceId = Guid.Empty, ChatId = Guid.NewGuid(), @@ -229,11 +255,11 @@ public abstract partial class AssistantBase : AssistantLowerBase wher protected Guid CreateChatThread(Guid workspaceId, string name) { var chatId = Guid.NewGuid(); - this.chatThread = new() + this.ChatThread = new() { IncludeDateTime = false, - SelectedProvider = this.providerSettings.Id, - SelectedProfile = this.AllowProfiles ? this.currentProfile.Id : Profile.NO_PROFILE.Id, + SelectedProvider = this.ProviderSettings.Id, + SelectedProfile = this.AllowProfiles ? this.CurrentProfile.Id : Profile.NO_PROFILE.Id, SystemPrompt = this.SystemPrompt, WorkspaceId = workspaceId, ChatId = chatId, @@ -246,27 +272,27 @@ public abstract partial class AssistantBase : AssistantLowerBase wher protected virtual void ResetProviderAndProfileSelection() { - this.providerSettings = this.SettingsManager.GetPreselectedProvider(this.Component); - this.currentProfile = this.SettingsManager.GetPreselectedProfile(this.Component); - this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component); + this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(this.Component); + this.CurrentProfile = this.SettingsManager.GetPreselectedProfile(this.Component); + this.CurrentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component); } protected DateTimeOffset AddUserRequest(string request, bool hideContentFromUser = false, params List attachments) { var time = DateTimeOffset.Now; - this.lastUserPrompt = new ContentText + this.LastUserPrompt = new ContentText { Text = request, FileAttachments = attachments, }; - this.chatThread!.Blocks.Add(new ContentBlock + this.ChatThread!.Blocks.Add(new ContentBlock { Time = time, ContentType = ContentType.TEXT, HideFromUser = hideContentFromUser, Role = ChatRole.USER, - Content = this.lastUserPrompt, + Content = this.LastUserPrompt, }); return time; @@ -274,8 +300,8 @@ public abstract partial class AssistantBase : AssistantLowerBase wher protected async Task AddAIResponseAsync(DateTimeOffset time, bool hideContentFromUser = false) { - var manageCancellationLocally = this.cancellationTokenSource is null; - this.cancellationTokenSource ??= new CancellationTokenSource(); + var manageCancellationLocally = this.CancellationTokenSource is null; + this.CancellationTokenSource ??= new CancellationTokenSource(); var aiText = new ContentText { @@ -293,10 +319,10 @@ public abstract partial class AssistantBase : AssistantLowerBase wher HideFromUser = hideContentFromUser, }; - if (this.chatThread is not null) + if (this.ChatThread is not null) { - this.chatThread.Blocks.Add(this.resultingContentBlock); - this.chatThread.SelectedProvider = this.providerSettings.Id; + this.ChatThread.Blocks.Add(this.resultingContentBlock); + this.ChatThread.SelectedProvider = this.ProviderSettings.Id; } this.isProcessing = true; @@ -305,15 +331,15 @@ public abstract partial class AssistantBase : AssistantLowerBase wher // Use the selected provider to get the AI response. // By awaiting this line, we wait for the entire // content to be streamed. - this.chatThread = await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(), this.providerSettings.Model, this.lastUserPrompt, this.chatThread, this.cancellationTokenSource!.Token); + this.ChatThread = await aiText.CreateFromProviderAsync(this.ProviderSettings.CreateProvider(), this.ProviderSettings.Model, this.LastUserPrompt, this.ChatThread, this.CancellationTokenSource!.Token); this.isProcessing = false; this.StateHasChanged(); if(manageCancellationLocally) { - this.cancellationTokenSource.Dispose(); - this.cancellationTokenSource = null; + this.CancellationTokenSource.Dispose(); + this.CancellationTokenSource = null; } // Return the AI response: @@ -322,15 +348,56 @@ public abstract partial class AssistantBase : AssistantLowerBase wher private async Task CancelStreaming() { - if (this.cancellationTokenSource is not null) - if(!this.cancellationTokenSource.IsCancellationRequested) - await this.cancellationTokenSource.CancelAsync(); + if (this.CancellationTokenSource is not null) + if(!this.CancellationTokenSource.IsCancellationRequested) + await this.CancellationTokenSource.CancelAsync(); } protected async Task CopyToClipboard() { await this.RustService.CopyText2Clipboard(this.Snackbar, this.Result2Copy()); } + + private ChatThread CreateSendToChatThread() + { + var originalChatThread = this.ChatThread ?? new ChatThread(); + if (string.IsNullOrWhiteSpace(this.SendToChatVisibleUserPromptText)) + return originalChatThread with + { + SystemPrompt = SystemPrompts.DEFAULT, + }; + + var earliestBlock = originalChatThread.Blocks.MinBy(x => x.Time); + var visiblePromptTime = earliestBlock is null + ? DateTimeOffset.Now + : earliestBlock.Time == DateTimeOffset.MinValue + ? earliestBlock.Time + : earliestBlock.Time.AddTicks(-1); + + var transferredBlocks = originalChatThread.Blocks + .Select(block => block.Role is ChatRole.USER + ? block.DeepClone(changeHideState: true) + : block.DeepClone()) + .ToList(); + + transferredBlocks.Insert(0, new ContentBlock + { + Time = visiblePromptTime, + ContentType = ContentType.TEXT, + HideFromUser = false, + Role = ChatRole.USER, + Content = new ContentText + { + Text = this.SendToChatVisibleUserPromptText, + }, + }); + + return originalChatThread with + { + SystemPrompt = SystemPrompts.DEFAULT, + Blocks = transferredBlocks, + }; + } private static string? GetButtonIcon(string icon) { @@ -368,9 +435,14 @@ public abstract partial class AssistantBase : AssistantLowerBase wher switch (destination) { case Tools.Components.CHAT: - var convertedChatThread = this.ConvertToChatThread; - convertedChatThread = convertedChatThread with { SelectedProvider = this.providerSettings.Id }; - MessageBus.INSTANCE.DeferMessage(this, sendToData.Event, convertedChatThread); + if (sendToButton.SendToChatAsInput) + MessageBus.INSTANCE.DeferMessage(this, Event.SEND_TO_CHAT_INPUT, contentToSend); + else + { + var convertedChatThread = this.ConvertToChatThread; + convertedChatThread = convertedChatThread with { SelectedProvider = this.ProviderSettings.Id }; + MessageBus.INSTANCE.DeferMessage(this, sendToData.Event, convertedChatThread); + } break; default: @@ -393,7 +465,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher private async Task InnerResetForm() { this.resultingContentBlock = null; - this.providerSettings = Settings.Provider.NONE; + this.ProviderSettings = Settings.Provider.NONE; await this.JsRuntime.ClearDiv(RESULT_DIV_ID); await this.JsRuntime.ClearDiv(AFTER_RESULT_DIV_ID); @@ -401,12 +473,12 @@ public abstract partial class AssistantBase : AssistantLowerBase wher this.ResetForm(); this.ResetProviderAndProfileSelection(); - this.inputIsValid = false; + this.InputIsValid = false; this.inputIssues = []; - this.form?.ResetValidation(); + this.Form?.ResetValidation(); this.StateHasChanged(); - this.form?.ResetValidation(); + this.Form?.ResetValidation(); } private string GetResetColor() => this.SettingsManager.IsDarkMode switch diff --git a/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor b/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor index c95f6f3a..8f582ebe 100644 --- a/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor +++ b/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor @@ -11,4 +11,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor.cs b/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor.cs index bf28b7c4..d1930b8e 100644 --- a/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/BiasDay/BiasOfTheDayAssistant.razor.cs @@ -131,8 +131,8 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/Coding/AssistantCoding.razor.cs b/app/MindWork AI Studio/Assistants/Coding/AssistantCoding.razor.cs index c96043ab..5e8a3753 100644 --- a/app/MindWork AI Studio/Assistants/Coding/AssistantCoding.razor.cs +++ b/app/MindWork AI Studio/Assistants/Coding/AssistantCoding.razor.cs @@ -29,6 +29,10 @@ public partial class AssistantCoding : AssistantBaseCore protected override Func SubmitAction => this.GetSupport; + protected override string SendToChatVisibleUserPromptPrefix => T("Help me with the following coding question:"); + + protected override string SendToChatVisibleUserPromptContent => this.questions; + protected override void ResetForm() { this.codingContexts.Clear(); @@ -104,7 +108,7 @@ public partial class AssistantCoding : AssistantBaseCore return ValueTask.CompletedTask; this.codingContexts.RemoveAt(index); - this.form?.ResetValidation(); + this.Form?.ResetValidation(); this.StateHasChanged(); return ValueTask.CompletedTask; @@ -112,8 +116,8 @@ public partial class AssistantCoding : AssistantBaseCore private async Task GetSupport() { - await this.form!.Validate(); - if (!this.inputIsValid) + await this.Form!.Validate(); + if (!this.InputIsValid) return; var sbContext = new StringBuilder(); diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 4e7a38ee..89f8e04c 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -74,7 +74,7 @@ else @T("Documents for the analysis") - + } else @@ -164,10 +164,10 @@ else @T("Documents for the analysis") - + } - + diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 419d4c9e..77522cd8 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -125,7 +125,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore @@ -408,10 +408,10 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore= minimumLevel) + if (this.ProviderSettings != Settings.Provider.NONE && + this.ProviderSettings.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel) { - this.currentProfile = this.ResolveProfileSelection(); + this.CurrentProfile = this.ResolveProfileSelection(); return; } } @@ -420,18 +420,18 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore x.Id == this.selectedPolicy.PreselectedProvider); if (policyProvider is not null && policyProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel) { - this.providerSettings = policyProvider; - this.currentProfile = this.ResolveProfileSelection(); + this.ProviderSettings = policyProvider; + this.CurrentProfile = this.ResolveProfileSelection(); return; } - var fallbackProvider = this.SettingsManager.GetPreselectedProvider(this.Component, this.providerSettings.Id); + var fallbackProvider = this.SettingsManager.GetPreselectedProvider(this.Component, this.ProviderSettings.Id); if (fallbackProvider != Settings.Provider.NONE && fallbackProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level < minimumLevel) fallbackProvider = Settings.Provider.NONE; - this.providerSettings = fallbackProvider; - this.currentProfile = this.ResolveProfileSelection(); + this.ProviderSettings = fallbackProvider; + this.CurrentProfile = this.ResolveProfileSelection(); } private ConfidenceLevel GetPolicyMinimumConfidenceLevel() @@ -482,7 +482,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore @@ -349,7 +349,7 @@ else if (component is AssistantProviderSelection providerSelection) {
- +
} break; @@ -359,7 +359,7 @@ else { var selection = profileSelection;
- +
} break; diff --git a/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs b/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs index 7703ff97..7b3b3d69 100644 --- a/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs +++ b/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs @@ -165,7 +165,7 @@ public partial class AssistantDynamic : AssistantBaseCore if (this.assistantPlugin?.HasCustomPromptBuilder != true) return this.CollectUserPromptFallback(); var input = this.BuildPromptInput(); - var prompt = await this.assistantPlugin.TryBuildPromptAsync(input, this.cancellationTokenSource?.Token ?? CancellationToken.None); + var prompt = await this.assistantPlugin.TryBuildPromptAsync(input, this.CancellationTokenSource?.Token ?? CancellationToken.None); return !string.IsNullOrWhiteSpace(prompt) ? prompt : this.CollectUserPromptFallback(); } @@ -178,10 +178,10 @@ public partial class AssistantDynamic : AssistantBaseCore var profile = new LuaTable { - ["Name"] = this.currentProfile.Name, - ["NeedToKnow"] = this.currentProfile.NeedToKnow, - ["Actions"] = this.currentProfile.Actions, - ["Num"] = this.currentProfile.Num, + ["Name"] = this.CurrentProfile.Name, + ["NeedToKnow"] = this.CurrentProfile.NeedToKnow, + ["Actions"] = this.CurrentProfile.Actions, + ["Num"] = this.CurrentProfile.Num, }; state["profile"] = profile; @@ -233,7 +233,7 @@ public partial class AssistantDynamic : AssistantBaseCore try { var input = this.BuildPromptInput(); - var cancellationToken = this.cancellationTokenSource?.Token ?? CancellationToken.None; + var cancellationToken = this.CancellationTokenSource?.Token ?? CancellationToken.None; var result = await this.assistantPlugin.TryInvokeButtonActionAsync(button, input, cancellationToken); if (result is not null) this.ApplyActionResult(result, AssistantComponentType.BUTTON); @@ -264,7 +264,7 @@ public partial class AssistantDynamic : AssistantBaseCore try { var input = this.BuildPromptInput(); - var cancellationToken = this.cancellationTokenSource?.Token ?? CancellationToken.None; + var cancellationToken = this.CancellationTokenSource?.Token ?? CancellationToken.None; var result = await this.assistantPlugin.TryInvokeSwitchChangedAsync(switchComponent, input, cancellationToken); if (result is not null) this.ApplyActionResult(result, AssistantComponentType.SWITCH); diff --git a/app/MindWork AI Studio/Assistants/EMail/AssistantEMail.razor b/app/MindWork AI Studio/Assistants/EMail/AssistantEMail.razor index 2f8783b3..620b7c95 100644 --- a/app/MindWork AI Studio/Assistants/EMail/AssistantEMail.razor +++ b/app/MindWork AI Studio/Assistants/EMail/AssistantEMail.razor @@ -22,4 +22,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/EMail/AssistantEMail.razor.cs b/app/MindWork AI Studio/Assistants/EMail/AssistantEMail.razor.cs index 70baa91e..4c1e1158 100644 --- a/app/MindWork AI Studio/Assistants/EMail/AssistantEMail.razor.cs +++ b/app/MindWork AI Studio/Assistants/EMail/AssistantEMail.razor.cs @@ -1,6 +1,5 @@ using System.Text; -using AIStudio.Chat; using AIStudio.Dialogs.Settings; namespace AIStudio.Assistants.EMail; @@ -26,10 +25,9 @@ public partial class AssistantEMail : AssistantBaseCore SubmitAction => this.CreateMail; - protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with - { - SystemPrompt = SystemPrompts.DEFAULT, - }; + protected override string SendToChatVisibleUserPromptPrefix => T("Create an email based on the following bullet points:"); + + protected override string SendToChatVisibleUserPromptContent => this.inputBulletPoints; protected override void ResetForm() { @@ -226,8 +224,8 @@ public partial class AssistantEMail : AssistantBaseCore@T("Important:") @T("The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this.") @T("However, generating all the files takes a certain amount of time.") @T("Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing.") - + @T("Write code to file system") diff --git a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor.cs b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor.cs index d8866cfe..a4c204c9 100644 --- a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor.cs +++ b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor.cs @@ -303,7 +303,7 @@ public partial class AssistantERI : AssistantBaseCore protected override bool SubmitDisabled => this.IsNoneERIServerSelected; - protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with + protected override ChatThread ConvertToChatThread => (this.ChatThread ?? new()) with { SystemPrompt = this.SystemPrompt, }; @@ -400,7 +400,7 @@ public partial class AssistantERI : AssistantBaseCore if(this.selectedERIServer is null) return; - this.SettingsManager.ConfigurationData.ERI.PreselectedProvider = this.providerSettings.Id; + this.SettingsManager.ConfigurationData.ERI.PreselectedProvider = this.ProviderSettings.Id; this.selectedERIServer.ServerName = this.serverName; this.selectedERIServer.ServerDescription = this.serverDescription; this.selectedERIServer.ERIVersion = this.selectedERIVersion; @@ -488,7 +488,7 @@ public partial class AssistantERI : AssistantBaseCore this.ResetForm(); await this.SettingsManager.StoreSettings(); - this.form?.ResetValidation(); + this.Form?.ResetValidation(); } private bool IsNoneERIServerSelected => this.selectedERIServer is null; @@ -940,8 +940,8 @@ public partial class AssistantERI : AssistantBaseCore return; await this.AutoSave(); - await this.form!.Validate(); - if (!this.inputIsValid) + await this.Form!.Validate(); + if (!this.InputIsValid) return; if(this.retrievalProcesses.Count == 0) diff --git a/app/MindWork AI Studio/Assistants/GrammarSpelling/AssistantGrammarSpelling.razor b/app/MindWork AI Studio/Assistants/GrammarSpelling/AssistantGrammarSpelling.razor index f783f657..5d116797 100644 --- a/app/MindWork AI Studio/Assistants/GrammarSpelling/AssistantGrammarSpelling.razor +++ b/app/MindWork AI Studio/Assistants/GrammarSpelling/AssistantGrammarSpelling.razor @@ -3,4 +3,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/GrammarSpelling/AssistantGrammarSpelling.razor.cs b/app/MindWork AI Studio/Assistants/GrammarSpelling/AssistantGrammarSpelling.razor.cs index 64168fd2..9f90a0fa 100644 --- a/app/MindWork AI Studio/Assistants/GrammarSpelling/AssistantGrammarSpelling.razor.cs +++ b/app/MindWork AI Studio/Assistants/GrammarSpelling/AssistantGrammarSpelling.razor.cs @@ -1,4 +1,3 @@ -using AIStudio.Chat; using AIStudio.Dialogs.Settings; namespace AIStudio.Assistants.GrammarSpelling; @@ -41,10 +40,9 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore SubmitAction => this.ProofreadText; - protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with - { - SystemPrompt = SystemPrompts.DEFAULT, - }; + protected override string SendToChatVisibleUserPromptPrefix => T("Check the following text for grammar and spelling mistakes:"); + + protected override string SendToChatVisibleUserPromptContent => this.inputText; protected override void ResetForm() { @@ -121,8 +119,8 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore + } @if (this.localizedContent.Count > 0) diff --git a/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor.cs b/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor.cs index d229eb9b..cc69e796 100644 --- a/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor.cs +++ b/app/MindWork AI Studio/Assistants/I18N/AssistantI18N.razor.cs @@ -269,8 +269,8 @@ public partial class AssistantI18N : AssistantBaseCore private async Task LocalizeTextContent() { - await this.form!.Validate(); - if (!this.inputIsValid) + await this.Form!.Validate(); + if (!this.InputIsValid) return; if(this.selectedLanguagePlugin is null) @@ -291,7 +291,7 @@ public partial class AssistantI18N : AssistantBaseCore this.localizedContent = this.addedContent.ToDictionary(); } - if(this.cancellationTokenSource!.IsCancellationRequested) + if(this.CancellationTokenSource!.IsCancellationRequested) return; // @@ -302,7 +302,7 @@ public partial class AssistantI18N : AssistantBaseCore // foreach (var keyValuePair in this.selectedLanguagePlugin.Content) { - if (this.cancellationTokenSource!.IsCancellationRequested) + if (this.CancellationTokenSource!.IsCancellationRequested) break; if (this.localizedContent.ContainsKey(keyValuePair.Key)) @@ -314,7 +314,7 @@ public partial class AssistantI18N : AssistantBaseCore this.localizedContent.Add(keyValuePair.Key, keyValuePair.Value); } - if(this.cancellationTokenSource!.IsCancellationRequested) + if(this.CancellationTokenSource!.IsCancellationRequested) return; // @@ -324,7 +324,7 @@ public partial class AssistantI18N : AssistantBaseCore var commentContent = new Dictionary(this.addedContent); foreach (var keyValuePair in PluginFactory.BaseLanguage.Content) { - if (this.cancellationTokenSource!.IsCancellationRequested) + if (this.CancellationTokenSource!.IsCancellationRequested) break; if (this.removedContent.ContainsKey(keyValuePair.Key)) @@ -342,7 +342,7 @@ public partial class AssistantI18N : AssistantBaseCore var minimumTime = TimeSpan.FromMilliseconds(500); foreach (var keyValuePair in this.addedContent) { - if(this.cancellationTokenSource!.IsCancellationRequested) + if(this.CancellationTokenSource!.IsCancellationRequested) break; // @@ -360,7 +360,7 @@ public partial class AssistantI18N : AssistantBaseCore var time = this.AddUserRequest(keyValuePair.Value); this.localizedContent.Add(keyValuePair.Key, await this.AddAIResponseAsync(time)); - if (this.cancellationTokenSource!.IsCancellationRequested) + if (this.CancellationTokenSource!.IsCancellationRequested) break; // @@ -375,7 +375,7 @@ public partial class AssistantI18N : AssistantBaseCore private void Phase2CreateLuaCode(IReadOnlyDictionary commentContent) { this.finalLuaCode.Clear(); - LuaTable.Create(ref this.finalLuaCode, "UI_TEXT_CONTENT", this.localizedContent, commentContent, this.cancellationTokenSource!.Token); + LuaTable.Create(ref this.finalLuaCode, "UI_TEXT_CONTENT", this.localizedContent, commentContent, this.CancellationTokenSource!.Token); // Next, we must remove the `root::` prefix from the keys: this.finalLuaCode.Replace("""UI_TEXT_CONTENT["root::""", """ diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 5a088dd7..9d391b76 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -256,6 +256,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::AGENDA::ASSISTANTAGENDA::T553265703"] = " -- Please provide a custom language. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::AGENDA::ASSISTANTAGENDA::T656744944"] = "Please provide a custom language." +-- Create an agenda for the meeting '{0}' with the following contents: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::AGENDA::ASSISTANTAGENDA::T748352577"] = "Create an agenda for the meeting '{0}' with the following contents:" + -- Should the participants be involved passively or actively? UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::AGENDA::ASSISTANTAGENDA::T749354834"] = "Should the participants be involved passively or actively?" @@ -352,6 +355,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::ASSISTANTCODING::T1082499335"] = -- Yes, provide compiler messages UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::ASSISTANTCODING::T1267219550"] = "Yes, provide compiler messages" +-- Help me with the following coding question: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::ASSISTANTCODING::T1290190584"] = "Help me with the following coding question:" + -- Compiler messages UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::ASSISTANTCODING::T2339992872"] = "Compiler messages" @@ -586,6 +592,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T134060413"] = "Yo -- Please start each line of your content list with a dash (-) to create a bullet point list. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1384718254"] = "Please start each line of your content list with a dash (-) to create a bullet point list." +-- Create an email based on the following bullet points: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1477828979"] = "Create an email based on the following bullet points:" + -- Create email UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1686330485"] = "Create email" @@ -1096,6 +1105,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::GRAMMARSPELLING::ASSISTANTGRAMMARSPELLING -- Check the grammar and spelling of a text. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::GRAMMARSPELLING::ASSISTANTGRAMMARSPELLING::T3184716499"] = "Check the grammar and spelling of a text." +-- Check the following text for grammar and spelling mistakes: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::GRAMMARSPELLING::ASSISTANTGRAMMARSPELLING::T3486937812"] = "Check the following text for grammar and spelling mistakes:" + -- Please provide a custom language. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::GRAMMARSPELLING::ASSISTANTGRAMMARSPELLING::T656744944"] = "Please provide a custom language." @@ -1195,6 +1207,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ICONFINDER::ASSISTANTICONFINDER::T1302165 -- Find Icon UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ICONFINDER::ASSISTANTICONFINDER::T1975161003"] = "Find Icon" +-- Find icon suggestions on {0} for the following context: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ICONFINDER::ASSISTANTICONFINDER::T2525517053"] = "Find icon suggestions on {0} for the following context:" + -- 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. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ICONFINDER::ASSISTANTICONFINDER::T347756684"] = "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." @@ -1231,6 +1246,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T133060 -- Create the job posting UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T1348170275"] = "Create the job posting" +-- Create a job posting. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T1575017511"] = "Create a job posting." + -- This is important to consider the legal framework of the country. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T1652348489"] = "This is important to consider the legal framework of the country." @@ -1249,6 +1267,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T222318 -- Target language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T237828418"] = "Target language" +-- Create a job posting for {0} based on the following job description: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T3001516791"] = "Create a job posting for {0} based on the following job description:" + -- Please provide a job description. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T3056799310"] = "Please provide a job description." @@ -1261,6 +1282,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T341483 -- (Optional) Provide the date until the job posting is valid UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T3471426808"] = "(Optional) Provide the date until the job posting is valid" +-- Create a job posting for {0}. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T3513993280"] = "Create a job posting for {0}." + -- Provide some key points about the job you want to post. The AI will then formulate a suggestion that you can finalize. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T3644893573"] = "Provide some key points about the job you want to post. The AI will then formulate a suggestion that you can finalize." @@ -1276,6 +1300,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T393005 -- (Optional) Provide the work location UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T3972042680"] = "(Optional) Provide the work location" +-- Create a job posting based on the following job description: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::JOBPOSTING::ASSISTANTJOBPOSTINGS::T795506638"] = "Create a job posting based on the following job description:" + -- Please provide a legal document as input. You might copy the desired text from a document or a website. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::LEGALCHECK::ASSISTANTLEGALCHECK::T1160217683"] = "Please provide a legal document as input. You might copy the desired text from a document or a website." @@ -1294,9 +1321,15 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::LEGALCHECK::ASSISTANTLEGALCHECK::T4016275 -- Please provide your questions as input. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::LEGALCHECK::ASSISTANTLEGALCHECK::T4154383818"] = "Please provide your questions as input." +-- Answer the following questions about a legal document: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::LEGALCHECK::ASSISTANTLEGALCHECK::T4254597664"] = "Answer the following questions about a legal document:" + -- Ask your questions UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::LEGALCHECK::ASSISTANTLEGALCHECK::T467099852"] = "Ask your questions" +-- Analyze the following text and extract my tasks: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::MYTASKS::ASSISTANTMYTASKS::T1349891364"] = "Analyze the following text and extract my tasks:" + -- Please provide some text as input. For example, an email. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::MYTASKS::ASSISTANTMYTASKS::T1962809521"] = "Please provide some text as input. For example, an email." @@ -1324,6 +1357,150 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::MYTASKS::ASSISTANTMYTASKS::T534887559"] = -- Please provide a custom language. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::MYTASKS::ASSISTANTMYTASKS::T656744944"] = "Please provide a custom language." +-- The custom prompt guide file is empty or could not be read. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1173408044"] = "The custom prompt guide file is empty or could not be read." + +-- Use English for complex prompts and explicitly request response language if needed. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T119999744"] = "Use English for complex prompts and explicitly request response language if needed." + +-- The selected custom prompt guide file could not be found. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1300996373"] = "The selected custom prompt guide file could not be found." + +-- Define a role for the model to focus output style and expertise. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1316122151"] = "Define a role for the model to focus output style and expertise." + +-- Use headings or markers to separate context, task, and constraints. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1435532298"] = "Use headings or markers to separate context, task, and constraints." + +-- Custom Prompt Guide Preview +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1526658372"] = "Custom Prompt Guide Preview" + +-- The model response was not in the expected JSON format. The raw response is shown as optimized prompt. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1548376553"] = "The model response was not in the expected JSON format. The raw response is shown as optimized prompt." + +-- View +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1582017048"] = "View" + +-- 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." + +-- Add short examples and background context for your specific use case. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1666841672"] = "Add short examples and background context for your specific use case." + +-- Assign a role to shape tone, expertise, and focus. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1679211785"] = "Assign a role to shape tone, expertise, and focus." + +-- Structure with markers +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1695758233"] = "Structure with markers" + +-- Please attach and load a valid custom prompt guide file. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1760468309"] = "Please attach and load a valid custom prompt guide file." + +-- Prompt Optimizer +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1777666968"] = "Prompt Optimizer" + +-- Add clearer goals and explicit quality expectations. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1833795299"] = "Add clearer goals and explicit quality expectations." + +-- Optimize prompt +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T1857716344"] = "Optimize prompt" + +-- Break the task into numbered steps if order matters. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T2185953360"] = "Break the task into numbered steps if order matters." + +-- Please provide a prompt or prompt description. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T2228130444"] = "Please provide a prompt or prompt description." + +-- Add examples and context +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T2386806593"] = "Add examples and context" + +-- Custom prompt guide file +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T2458417590"] = "Custom prompt guide file" + +-- Use an LLM to optimize your prompt by following either the default or your individual prompt guidelines and get targeted recommendations for future versions of the prompt. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T2466607250"] = "Use an LLM to optimize your prompt by following either the default or your individual prompt guidelines and get targeted recommendations for future versions of the prompt." + +-- Replaced the previously selected custom prompt guide file. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T2698103422"] = "Replaced the previously selected custom prompt guide file." + +-- (Optional) Important Aspects for the prompt +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T2713431429"] = "(Optional) Important Aspects for the prompt" + +-- Use the prompt recommendations from the custom prompt guide. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T2830307837"] = "Use the prompt recommendations from the custom prompt guide." + +-- Be clear and direct +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T2880063041"] = "Be clear and direct" + +-- The prompting guideline file could not be loaded. Please verify 'prompting_guideline.md' in Assistants/PromptOptimizer. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T30321193"] = "The prompting guideline file could not be loaded. Please verify 'prompting_guideline.md' in Assistants/PromptOptimizer." + +-- Custom language +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T3032662264"] = "Custom language" + +-- Give the model a role +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T3420218291"] = "Give the model a role" + +-- Failed to load custom prompt guide content. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T3488117809"] = "Failed to load custom prompt guide content." + +-- No file selected +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T3522202289"] = "No file selected" + +-- Use custom prompt guide +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T3528575759"] = "Use custom prompt guide" + +-- Prefer numbered steps when task order matters. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T3558299393"] = "Prefer numbered steps when task order matters." + +-- Recommendations for your prompt +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T3577149599"] = "Recommendations for your prompt" + +-- (Optional) Specify aspects the optimizer should emphasize in the resulting prompt, such as output structure, or constraints. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T3686962588"] = "(Optional) Specify aspects the optimizer should emphasize in the resulting prompt, such as output structure, or constraints." + +-- View default prompt guide +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T4017099405"] = "View default prompt guide" + +-- Prompt or prompt description +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T4058791116"] = "Prompt or prompt description" + +-- Include short examples and context that explain the purpose behind your requirements. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T4143206140"] = "Include short examples and context that explain the purpose behind your requirements." + +-- Prompting Guideline +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T4250996615"] = "Prompting Guideline" + +-- Use sequential steps +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T487578804"] = "Use sequential steps" + +-- 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." + +-- Choose prompt language deliberately +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T616613304"] = "Choose prompt language deliberately" + +-- Prompt recommendations were updated based on your latest optimization. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T633382478"] = "Prompt recommendations were updated based on your latest optimization." + +-- Please provide a custom language. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T656744944"] = "Please provide a custom language." + +-- No further recommendation in this area. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T659636347"] = "No further recommendation in this area." + +-- The prompting guideline file could not be loaded. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T666817418"] = "The prompting guideline file could not be loaded." + +-- Language for the optimized prompt +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T773621440"] = "Language for the optimized prompt" + +-- Use these recommendations, that are based on the default prompt guide, to improve your prompts. The suggestions are updated based on your latest prompt optimization. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T805885769"] = "Use these recommendations, that are based on the default prompt guide, to improve your prompts. The suggestions are updated based on your latest prompt optimization." + +-- For complex tasks, write prompts in English. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::PROMPTOPTIMIZER::ASSISTANTPROMPTOPTIMIZER::T85710437"] = "For complex tasks, write prompts in English." + -- Please provide a text as input. You might copy the desired text from a document or a website. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE::T137304886"] = "Please provide a text as input. You might copy the desired text from a document or a website." @@ -1339,6 +1516,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE:: -- Language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE::T2591284123"] = "Language" +-- Rewrite and improve the following text: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE::T2875363001"] = "Rewrite and improve the following text:" + -- Custom language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::REWRITEIMPROVE::ASSISTANTREWRITEIMPROVE::T3032662264"] = "Custom language" @@ -1579,6 +1759,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T617902505" -- Please provide a custom language. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T656744944"] = "Please provide a custom language." +-- Find synonyms for the following word or phrase: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SYNONYM::ASSISTANTSYNONYMS::T1793532807"] = "Find synonyms for the following word or phrase:" + -- Your word or phrase UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SYNONYM::ASSISTANTSYNONYMS::T1847246020"] = "Your word or phrase" @@ -1603,6 +1786,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SYNONYM::ASSISTANTSYNONYMS::T3501110371"] -- Custom target language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SYNONYM::ASSISTANTSYNONYMS::T3848935911"] = "Custom target language" +-- Context: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SYNONYM::ASSISTANTSYNONYMS::T4209715410"] = "Context:" + -- Please provide a custom language. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SYNONYM::ASSISTANTSYNONYMS::T656744944"] = "Please provide a custom language." @@ -1618,6 +1804,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::TEXTSUMMARIZER::ASSISTANTTEXTSUMMARIZER:: -- Text Summarizer UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::TEXTSUMMARIZER::ASSISTANTTEXTSUMMARIZER::T1907192403"] = "Text Summarizer" +-- Create a summary of my text +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::TEXTSUMMARIZER::ASSISTANTTEXTSUMMARIZER::T2013275370"] = "Create a summary of my text" + -- Target language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::TEXTSUMMARIZER::ASSISTANTTEXTSUMMARIZER::T237828418"] = "Target language" @@ -1681,6 +1870,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::TRANSLATION::ASSISTANTTRANSLATION::T20282 -- Target language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::TRANSLATION::ASSISTANTTRANSLATION::T237828418"] = "Target language" +-- Translate the following text to {0}: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::TRANSLATION::ASSISTANTTRANSLATION::T2578812023"] = "Translate the following text to {0}:" + -- Translate text from one language to another. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::TRANSLATION::ASSISTANTTRANSLATION::T3230457846"] = "Translate text from one language to another." @@ -1771,6 +1963,9 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Export C -- The selected model '{0}' is no longer available from '{1}' (provider={2}). Please adapt your provider settings. UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T3267850764"] = "The selected model '{0}' is no longer available from '{1}' (provider={2}). Please adapt your provider settings." +-- We could load models from '{0}', but the provider did not return any usable text models. +UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T3378120620"] = "We could load models from '{0}', but the provider did not return any usable text models." + -- The local image file does not exist. Skipping the image. UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T255679918"] = "The local image file does not exist. Skipping the image." @@ -2101,6 +2296,27 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T527187983"] = "C -- Install Pandoc UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T986578435"] = "Install Pandoc" +-- Version +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T1573770551"] = "Version" + +-- A new version of the terms is available. Please review it again. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T1711766303"] = "A new version of the terms is available. Please review it again." + +-- This mandatory info has not been accepted yet. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T1870532312"] = "This mandatory info has not been accepted yet." + +-- Accepted version +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T203086476"] = "Accepted version" + +-- Last accepted version +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T3407978086"] = "Last accepted version" + +-- Accepted at (UTC) +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T3511160492"] = "Accepted at (UTC)" + +-- Please review this text again. The content was changed. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T941885055"] = "Please review this text again. The content was changed." + -- Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1057189794"] = "Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications." @@ -2299,6 +2515,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAGENTASSISTANTAUDI -- Block activation below the minimum Audit-Level? UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAGENTASSISTANTAUDIT::T232834129"] = "Block activation below the minimum Audit-Level?" +-- Disabling this setting turns off assistant plugin security audits. External assistants may then be activated and used even without a valid audit or after plugin changes. Do you really want to disable this protection? +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAGENTASSISTANTAUDIT::T2516645821"] = "Disabling this setting turns off assistant plugin security audits. External assistants may then be activated and used even without a valid audit or after plugin changes. Do you really want to disable this protection?" + -- Agent: Security Audit for external Assistants UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAGENTASSISTANTAUDIT::T2910364422"] = "Agent: Security Audit for external Assistants" @@ -2314,6 +2533,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAGENTASSISTANTAUDI -- Security audit is automatically done in the background UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAGENTASSISTANTAUDIT::T3684348859"] = "Security audit is automatically done in the background" +-- Disable Assistant Audit Protection +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAGENTASSISTANTAUDIT::T4019550023"] = "Disable Assistant Audit Protection" + -- Activation is blocked below the minimum Audit-Level UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAGENTASSISTANTAUDIT::T4041192469"] = "Activation is blocked below the minimum Audit-Level" @@ -4027,6 +4249,15 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T900713019"] = "Cancel" -- The profile name must be unique; the chosen name is already in use. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T911748898"] = "The profile name must be unique; the chosen name is already in use." +-- Close +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROMPTINGGUIDELINEDIALOG::T3448155331"] = "Close" + +-- The full prompting guideline used by the Prompt Optimizer. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROMPTINGGUIDELINEDIALOG::T384594633"] = "The full prompting guideline used by the Prompt Optimizer." + +-- Prompting Guideline +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROMPTINGGUIDELINEDIALOG::T4250996615"] = "Prompting Guideline" + -- Please be aware: This section is for experts only. You are responsible for verifying the correctness of the additional parameters you provide to the API call. By default, AI Studio uses the OpenAI-compatible chat completions API, when that it is supported by the underlying service and model. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T1017509792"] = "Please be aware: This section is for experts only. You are responsible for verifying the correctness of the additional parameters you provide to the API call. By default, AI Studio uses the OpenAI-compatible chat completions API, when that it is supported by the underlying service and model." @@ -4969,6 +5200,39 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T55364659" -- Are you a project manager in a research facility? You might want to create a profile for your project management activities, one for your scientific work, and a profile for when you need to write program code. In these profiles, you can record how much experience you have or which methods you like or dislike using. Later, you can choose when and where you want to use each profile. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T56359901"] = "Are you a project manager in a research facility? You might want to create a profile for your project management activities, one for your scientific work, and a profile for when you need to write program code. In these profiles, you can record how much experience you have or which methods you like or dislike using. Later, you can choose when and where you want to use each profile." +-- Preselect the target language +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T1417990312"] = "Preselect the target language" + +-- Preselect another target language +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T1462295644"] = "Preselect another target language" + +-- Assistant: Prompt Optimizer Options +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T2309650422"] = "Assistant: Prompt Optimizer Options" + +-- Preselect aspects the optimizer should emphasize, such as role clarity, structure, or output constraints. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T2365571378"] = "Preselect aspects the optimizer should emphasize, such as role clarity, structure, or output constraints." + +-- No prompt optimizer options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T2506620531"] = "No prompt optimizer options are preselected" + +-- Prompt optimizer options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T2576287692"] = "Prompt optimizer options are preselected" + +-- Preselect prompt optimizer options? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T3159686278"] = "Preselect prompt optimizer options?" + +-- Close +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T3448155331"] = "Close" + +-- Which target language should be preselected? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T3547337928"] = "Which target language should be preselected?" + +-- When enabled, you can preselect target language, important aspects, and provider defaults for the prompt optimizer assistant. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T3570338905"] = "When enabled, you can preselect target language, important aspects, and provider defaults for the prompt optimizer assistant." + +-- Preselect important aspects +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T3705987833"] = "Preselect important aspects" + -- Which writing style should be preselected? UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGREWRITE::T1173034744"] = "Which writing style should be preselected?" @@ -5506,9 +5770,15 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1614176092"] = "Assistants" -- Coding UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1617786407"] = "Coding" +-- Optimize your prompt using a structured guideline. +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1709976267"] = "Optimize your prompt using a structured guideline." + -- Analyze a text or an email for tasks you need to complete. UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1728590051"] = "Analyze a text or an email for tasks you need to complete." +-- Prompt Optimizer +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1777666968"] = "Prompt Optimizer" + -- Text Summarizer UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1907192403"] = "Text Summarizer" @@ -5734,6 +6004,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1137744461"] = "ID mismatch: the -- This is a private AI Studio installation. It runs without an enterprise configuration. UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1209549230"] = "This is a private AI Studio installation. It runs without an enterprise configuration." +-- Unknown configuration plugin +UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1290340974"] = "Unknown configuration plugin" + -- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat. UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1388816916"] = "This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat." @@ -5764,6 +6037,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1629800076"] = "Building on .NET -- AI Studio creates a log file at startup, in which events during startup are recorded. After startup, another log file is created that records all events that occur during the use of the app. This includes any errors that may occur. Depending on when an error occurs (at startup or during use), the contents of these log files can be helpful for troubleshooting. Sensitive information such as passwords is not included in the log files. UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1630237140"] = "AI Studio creates a log file at startup, in which events during startup are recorded. After startup, another log file is created that records all events that occur during the use of the app. This includes any errors that may occur. Depending on when an error occurs (at startup or during use), the contents of these log files can be helpful for troubleshooting. Sensitive information such as passwords is not included in the log files." +-- Consent: +UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T171952677"] = "Consent:" + -- This library is used to display the differences between two texts. This is necessary, e.g., for the grammar and spelling assistant. UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1772678682"] = "This library is used to display the differences between two texts. This is necessary, e.g., for the grammar and spelling assistant." @@ -5986,6 +6262,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T788846912"] = "Copies the config -- installed by AI Studio UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T833849470"] = "installed by AI Studio" +-- Provided by configuration plugin: {0} +UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T836298648"] = "Provided by configuration plugin: {0}" + -- We use this library to be able to read PowerPoint files. This allows us to insert content from slides into prompts and take PowerPoint files into account in RAG processes. We thank Nils Kruthoff for his work on this Rust crate. UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T855925638"] = "We use this library to be able to read PowerPoint files. This allows us to insert content from slides into prompts and take PowerPoint files into account in RAG processes. We thank Nils Kruthoff for his work on this Rust crate." @@ -6217,6 +6496,21 @@ UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Un -- no model selected UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODEL::T2234274832"] = "no model selected" +-- We could not load models from '{0}'. The account or API key does not have the required permissions. +UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODELLOADFAILUREREASONEXTENSIONS::T1143085203"] = "We could not load models from '{0}'. The account or API key does not have the required permissions." + +-- We could not load models from '{0}'. The API key is probably missing, invalid, or expired. +UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODELLOADFAILUREREASONEXTENSIONS::T2041046579"] = "We could not load models from '{0}'. The API key is probably missing, invalid, or expired." + +-- We could not load models from '{0}' because the provider is currently unavailable or could not be reached. +UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODELLOADFAILUREREASONEXTENSIONS::T2115688703"] = "We could not load models from '{0}' because the provider is currently unavailable or could not be reached." + +-- We could not load models from '{0}' because the provider returned an unexpected response. +UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODELLOADFAILUREREASONEXTENSIONS::T2186844789"] = "We could not load models from '{0}' because the provider returned an unexpected response." + +-- We could not load models from '{0}' due to an unknown error. +UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODELLOADFAILUREREASONEXTENSIONS::T3907712809"] = "We could not load models from '{0}' due to an unknown error." + -- Model as configured by whisper.cpp UI_TEXT_CONTENT["AISTUDIO::PROVIDER::SELFHOSTED::PROVIDERSELFHOSTED::T3313940770"] = "Model as configured by whisper.cpp" @@ -6520,6 +6814,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T166453786"] = "Grammar -- Legal Check Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T1886447798"] = "Legal Check Assistant" +-- Prompt Optimizer Assistant +UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T1993795352"] = "Prompt Optimizer Assistant" + -- Job Posting Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2212811874"] = "Job Posting Assistant" @@ -6862,6 +7159,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T6 -- The provided ASSISTANT lua table does not contain the boolean flag to control the allowance of profiles. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T781921072"] = "The provided ASSISTANT lua table does not contain the boolean flag to control the allowance of profiles." +-- This assistant changed after its last audit. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T1161057634"] = "This assistant changed after its last audit." + -- This assistant is currently locked. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T123211529"] = "This assistant is currently locked." @@ -6874,6 +7174,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECUR -- The current audit result is '{0}', which is below your required minimum level '{1}'. Your settings still allow manual activation, but the assistant keeps this security status and should be reviewed carefully. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T1901245910"] = "The current audit result is '{0}', which is below your required minimum level '{1}'. Your settings still allow manual activation, but the assistant keeps this security status and should be reviewed carefully." +-- This assistant can still be used because audit enforcement is disabled. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T1950430056"] = "This assistant can still be used because audit enforcement is disabled." + -- Changed UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T2311397435"] = "Changed" @@ -6889,6 +7192,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECUR -- The current audit result '{0}' is below your required minimum level '{1}'. Your security settings therefore block this assistant plugin. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T274724689"] = "The current audit result '{0}' is below your required minimum level '{1}'. Your security settings therefore block this assistant plugin." +-- The current audit result is '{0}', which is below your required minimum level '{1}'. Audit enforcement is currently disabled, so this assistant plugin can still be enabled or used. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T2774333862"] = "The current audit result is '{0}', which is below your required minimum level '{1}'. Audit enforcement is currently disabled, so this assistant plugin can still be enabled or used." + -- Not Audited UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T2828154864"] = "Not Audited" @@ -6907,6 +7213,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECUR -- Unlocked UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T3606159420"] = "Unlocked" +-- The plugin code changed after the last security audit. Audit enforcement is currently disabled, so this assistant plugin can still be enabled or used. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T3619293572"] = "The plugin code changed after the last security audit. Audit enforcement is currently disabled, so this assistant plugin can still be enabled or used." + -- Blocked UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTSECURITYRESOLVER::T3816336467"] = "Blocked" @@ -7246,6 +7555,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T4007657575"] = "Failed -- No update found. UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::UPDATESERVICE::T1015418291"] = "No update found." +-- Failed to check for updates. Please try again later. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::UPDATESERVICE::T1064148123"] = "Failed to check for updates. Please try again later." + -- Failed to install update automatically. Please try again manually. UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::UPDATESERVICE::T3709709946"] = "Failed to install update automatically. Please try again manually." diff --git a/app/MindWork AI Studio/Assistants/IconFinder/AssistantIconFinder.razor b/app/MindWork AI Studio/Assistants/IconFinder/AssistantIconFinder.razor index 278c8bb8..84dbf735 100644 --- a/app/MindWork AI Studio/Assistants/IconFinder/AssistantIconFinder.razor +++ b/app/MindWork AI Studio/Assistants/IconFinder/AssistantIconFinder.razor @@ -19,4 +19,4 @@
}
- \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/IconFinder/AssistantIconFinder.razor.cs b/app/MindWork AI Studio/Assistants/IconFinder/AssistantIconFinder.razor.cs index 294cdd3a..b6a3e5ad 100644 --- a/app/MindWork AI Studio/Assistants/IconFinder/AssistantIconFinder.razor.cs +++ b/app/MindWork AI Studio/Assistants/IconFinder/AssistantIconFinder.razor.cs @@ -27,6 +27,13 @@ public partial class AssistantIconFinder : AssistantBaseCore SubmitAction => this.FindIcon; + protected override string SendToChatVisibleUserPromptText => + $""" + {string.Format(T("Find icon suggestions on {0} for the following context:"), this.selectedIconSource.Name())} + + {this.inputContext} + """; + protected override void ResetForm() { this.inputContext = string.Empty; @@ -73,8 +80,8 @@ public partial class AssistantIconFinder : AssistantBaseCore - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/JobPosting/AssistantJobPostings.razor.cs b/app/MindWork AI Studio/Assistants/JobPosting/AssistantJobPostings.razor.cs index d13c2f6d..9d44eae7 100644 --- a/app/MindWork AI Studio/Assistants/JobPosting/AssistantJobPostings.razor.cs +++ b/app/MindWork AI Studio/Assistants/JobPosting/AssistantJobPostings.razor.cs @@ -1,4 +1,3 @@ -using AIStudio.Chat; using AIStudio.Dialogs.Settings; namespace AIStudio.Assistants.JobPosting; @@ -50,11 +49,35 @@ public partial class AssistantJobPostings : AssistantBaseCore false; protected override bool AllowProfiles => false; - - protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with + + protected override string SendToChatVisibleUserPromptText { - SystemPrompt = SystemPrompts.DEFAULT, - }; + get + { + if (!string.IsNullOrWhiteSpace(this.inputCompanyName) && !string.IsNullOrWhiteSpace(this.inputJobDescription)) + { + return $""" + {string.Format(T("Create a job posting for {0} based on the following job description:"), this.inputCompanyName)} + + {this.inputJobDescription} + """; + } + + if (!string.IsNullOrWhiteSpace(this.inputCompanyName)) + return string.Format(T("Create a job posting for {0}."), this.inputCompanyName); + + if (!string.IsNullOrWhiteSpace(this.inputJobDescription)) + { + return $""" + {T("Create a job posting based on the following job description:")} + + {this.inputJobDescription} + """; + } + + return T("Create a job posting."); + } + } protected override void ResetForm() { @@ -264,8 +287,8 @@ public partial class AssistantJobPostings : AssistantBaseCore + } - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/LegalCheck/AssistantLegalCheck.razor.cs b/app/MindWork AI Studio/Assistants/LegalCheck/AssistantLegalCheck.razor.cs index 100c3df4..a7c01bca 100644 --- a/app/MindWork AI Studio/Assistants/LegalCheck/AssistantLegalCheck.razor.cs +++ b/app/MindWork AI Studio/Assistants/LegalCheck/AssistantLegalCheck.razor.cs @@ -1,4 +1,3 @@ -using AIStudio.Chat; using AIStudio.Dialogs.Settings; namespace AIStudio.Assistants.LegalCheck; @@ -27,11 +26,10 @@ public partial class AssistantLegalCheck : AssistantBaseCore SubmitAction => this.AksQuestions; protected override bool SubmitDisabled => this.isAgentRunning; - - protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with - { - SystemPrompt = SystemPrompts.DEFAULT, - }; + + protected override string SendToChatVisibleUserPromptPrefix => T("Answer the following questions about a legal document:"); + + protected override string SendToChatVisibleUserPromptContent => this.inputQuestions; protected override void ResetForm() { @@ -93,8 +91,8 @@ public partial class AssistantLegalCheck : AssistantBaseCore - + - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor.cs b/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor.cs index c93246a8..ff5ab87f 100644 --- a/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor.cs +++ b/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor.cs @@ -1,4 +1,3 @@ -using AIStudio.Chat; using AIStudio.Dialogs.Settings; using AIStudio.Settings; @@ -31,10 +30,9 @@ public partial class AssistantMyTasks : AssistantBaseCore protected override bool ShowProfileSelection => false; - protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with - { - SystemPrompt = SystemPrompts.DEFAULT, - }; + protected override string SendToChatVisibleUserPromptPrefix => T("Analyze the following text and extract my tasks:"); + + protected override string SendToChatVisibleUserPromptContent => this.inputText; protected override void ResetForm() { @@ -112,8 +110,8 @@ public partial class AssistantMyTasks : AssistantBaseCore private async Task AnalyzeText() { - await this.form!.Validate(); - if (!this.inputIsValid) + await this.Form!.Validate(); + if (!this.InputIsValid) return; this.CreateChatThread(); @@ -121,4 +119,4 @@ public partial class AssistantMyTasks : AssistantBaseCore await this.AddAIResponseAsync(time); } -} \ No newline at end of file +} diff --git a/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor b/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor new file mode 100644 index 00000000..b2c1d3b1 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor @@ -0,0 +1,124 @@ +@attribute [Route(Routes.ASSISTANT_PROMPT_OPTIMIZER)] +@inherits AssistantBaseCore + + + + + + + + + @T("Recommendations for your prompt") + + +@if (this.ShowUpdatedPromptGuidelinesIndicator) +{ + + + @T("Prompt recommendations were updated based on your latest optimization.") + + +} + +@if (!this.useCustomPromptGuide) +{ + @T("Use these recommendations, that are based on the default prompt guide, to improve your prompts. The suggestions are updated based on your latest prompt optimization.") + + + + + + + + + + + + + + + + + + + + + +} + +@if (this.useCustomPromptGuide) +{ +@T("Use the prompt recommendations from the custom prompt guide.") +} + + + + @T("View default prompt guide") + + + + @T("Use custom prompt guide") + + + @if (this.useCustomPromptGuide) + { + + } + + + + + @T("View") + + + + diff --git a/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor.cs b/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor.cs new file mode 100644 index 00000000..b1df8944 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/PromptOptimizer/AssistantPromptOptimizer.razor.cs @@ -0,0 +1,571 @@ +using System.Text.Json; +using System.Text.RegularExpressions; + +using AIStudio.Chat; +using AIStudio.Dialogs; +using AIStudio.Dialogs.Settings; +using Microsoft.AspNetCore.Components; + +#if !DEBUG +using System.Reflection; +using Microsoft.Extensions.FileProviders; +#endif + +namespace AIStudio.Assistants.PromptOptimizer; + +public partial class AssistantPromptOptimizer : AssistantBaseCore +{ + private static readonly Regex JSON_CODE_FENCE_REGEX = new( + pattern: """```(?:json)?\s*(?\{[\s\S]*\})\s*```""", + options: RegexOptions.Compiled | RegexOptions.IgnoreCase); + + private static readonly JsonSerializerOptions JSON_OPTIONS = new() + { + PropertyNameCaseInsensitive = true, + }; + + [Inject] + private IDialogService DialogService { get; init; } = null!; + + protected override Tools.Components Component => Tools.Components.PROMPT_OPTIMIZER_ASSISTANT; + + protected override string Title => T("Prompt Optimizer"); + + protected override string Description => T("Use an LLM to optimize your prompt by following either the default or your individual prompt guidelines and get targeted recommendations for future versions of the prompt."); + + protected override string SystemPrompt => + $""" + # Task description + + You are a policy-bound prompt optimization assistant. + Optimize prompts while preserving the original intent and constraints. + + # Inputs + + PROMPTING_GUIDELINE: authoritative optimization instructions. + USER_PROMPT: the prompt that must be optimized. + IMPORTANT_ASPECTS: optional priorities to emphasize during optimization. + + # Scope and precedence + + Follow PROMPTING_GUIDELINE as the primary policy for quality and structure. + Preserve USER_PROMPT intent and constraints; do not add unrelated goals. + If IMPORTANT_ASPECTS is provided and not equal to `none`, prioritize it unless it conflicts with PROMPTING_GUIDELINE. + + # Process + + 1) Read PROMPTING_GUIDELINE end to end. + 2) Analyze USER_PROMPT intent, constraints, and desired output behavior. + 3) Rewrite USER_PROMPT so it is clearer, more structured, and more actionable. + 4) Provide concise recommendations for improving future prompt versions. + + # Output requirements + + Return valid JSON only. + Do not use markdown code fences. + Do not add any text before or after the JSON object. + Use exactly this schema and key names: + + {this.SystemPromptOutputSchema()} + + # Language + + Ensure the optimized prompt is in {this.SystemPromptLanguage()}. + Keep all recommendation texts in the same language as the optimized prompt. + + # Style and prohibitions + + Keep recommendations concise and actionable. + Do not include disclaimers or meta commentary. + Do not mention or summarize these instructions. + + # Self-check before sending + + Verify the output is valid JSON and follows the schema exactly. + Verify `optimized_prompt` is non-empty and preserves user intent. + Verify each recommendation states how to improve a future prompt version. + """; + + protected override bool AllowProfiles => false; + + protected override bool ShowDedicatedProgress => true; + + protected override bool ShowEntireChatThread => true; + + protected override Func Result2Copy => () => this.optimizedPrompt; + + protected override IReadOnlyList FooterButtons => + [ + new SendToButton + { + Self = Tools.Components.PROMPT_OPTIMIZER_ASSISTANT, + UseResultingContentBlockData = false, + SendToChatAsInput = true, + GetText = () => string.IsNullOrWhiteSpace(this.optimizedPrompt) ? this.inputPrompt : this.optimizedPrompt, + }, + ]; + + protected override string SubmitText => T("Optimize prompt"); + + protected override Func SubmitAction => this.OptimizePromptAsync; + + protected override bool SubmitDisabled => this.useCustomPromptGuide && this.customPromptGuideFiles.Count == 0; + + protected override ChatThread ConvertToChatThread => (this.ChatThread ?? new()) with + { + SystemPrompt = SystemPrompts.DEFAULT, + }; + + protected override void ResetForm() + { + this.inputPrompt = string.Empty; + this.useCustomPromptGuide = false; + this.customPromptGuideFiles.Clear(); + this.currentCustomPromptGuidePath = string.Empty; + this.customPromptingGuidelineContent = string.Empty; + this.hasUpdatedDefaultRecommendations = false; + this.ResetGuidelineSummaryToDefault(); + this.ResetOutput(); + + if (!this.MightPreselectValues()) + { + this.selectedTargetLanguage = CommonLanguages.AS_IS; + this.customTargetLanguage = string.Empty; + this.importantAspects = string.Empty; + } + } + + protected override bool MightPreselectValues() + { + if (!this.SettingsManager.ConfigurationData.PromptOptimizer.PreselectOptions) + return false; + + this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.PromptOptimizer.PreselectedTargetLanguage; + this.customTargetLanguage = this.SettingsManager.ConfigurationData.PromptOptimizer.PreselectedOtherLanguage; + this.importantAspects = this.SettingsManager.ConfigurationData.PromptOptimizer.PreselectedImportantAspects; + return true; + } + + protected override async Task OnInitializedAsync() + { + this.ResetGuidelineSummaryToDefault(); + this.hasUpdatedDefaultRecommendations = false; + + var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages(Event.SEND_TO_PROMPT_OPTIMIZER_ASSISTANT).FirstOrDefault(); + if (deferredContent is not null) + this.inputPrompt = deferredContent; + + await base.OnInitializedAsync(); + } + + private string inputPrompt = string.Empty; + private CommonLanguages selectedTargetLanguage = CommonLanguages.AS_IS; + private string customTargetLanguage = string.Empty; + private string importantAspects = string.Empty; + private bool useCustomPromptGuide; + private HashSet customPromptGuideFiles = []; + private string currentCustomPromptGuidePath = string.Empty; + private string customPromptingGuidelineContent = string.Empty; + private bool isLoadingCustomPromptGuide; + private bool hasUpdatedDefaultRecommendations; + + private string optimizedPrompt = string.Empty; + private string recClarityDirectness = string.Empty; + private string recExamplesContext = string.Empty; + private string recSequentialSteps = string.Empty; + private string recStructureMarkers = string.Empty; + private string recRoleDefinition = string.Empty; + private string recLanguageChoice = string.Empty; + + private bool ShowUpdatedPromptGuidelinesIndicator => !this.useCustomPromptGuide && this.hasUpdatedDefaultRecommendations; + private bool CanPreviewCustomPromptGuide => this.useCustomPromptGuide && this.customPromptGuideFiles.Count > 0; + private string CustomPromptGuideFileName => this.customPromptGuideFiles.Count switch + { + 0 => T("No file selected"), + _ => this.customPromptGuideFiles.First().FileName + }; + + private string? ValidateInputPrompt(string text) + { + if (string.IsNullOrWhiteSpace(text)) + return T("Please provide a prompt or prompt description."); + + return null; + } + + private string? ValidateCustomLanguage(string language) + { + if (this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language)) + return T("Please provide a custom language."); + + return null; + } + + private string SystemPromptLanguage() + { + var language = this.selectedTargetLanguage switch + { + CommonLanguages.AS_IS => "the source language of the input prompt", + CommonLanguages.OTHER => this.customTargetLanguage, + _ => this.selectedTargetLanguage.Name(), + }; + + if (string.IsNullOrWhiteSpace(language)) + return "the source language of the input prompt"; + + return language; + } + + private async Task OptimizePromptAsync() + { + await this.Form!.Validate(); + if (!this.InputIsValid) + return; + + this.ClearInputIssues(); + this.ResetOutput(); + this.hasUpdatedDefaultRecommendations = false; + + var promptingGuideline = await this.GetPromptingGuidelineForOptimizationAsync(); + if (string.IsNullOrWhiteSpace(promptingGuideline)) + { + if (this.useCustomPromptGuide) + this.AddInputIssue(T("Please attach and load a valid custom prompt guide file.")); + else + this.AddInputIssue(T("The prompting guideline file could not be loaded. Please verify 'prompting_guideline.md' in Assistants/PromptOptimizer.")); + return; + } + + this.CreateChatThread(); + var requestTime = this.AddUserRequest(this.BuildOptimizationRequest(promptingGuideline), hideContentFromUser: true); + var aiResponse = await this.AddAIResponseAsync(requestTime, hideContentFromUser: true); + + if (!TryParseOptimizationResult(aiResponse, out var parsedResult)) + { + this.optimizedPrompt = aiResponse.Trim(); + if (!this.useCustomPromptGuide) + { + this.ApplyFallbackRecommendations(); + this.MarkRecommendationsUpdated(); + } + + this.AddInputIssue(T("The model response was not in the expected JSON format. The raw response is shown as optimized prompt.")); + this.AddVisibleOptimizedPromptBlock(); + return; + } + + this.ApplyOptimizationResult(parsedResult); + this.AddVisibleOptimizedPromptBlock(); + } + + private string BuildOptimizationRequest(string promptingGuideline) + { + return + $$""" + # PROMPTING_GUIDELINE + + {{promptingGuideline}} + + + # USER_PROMPT + + {{this.inputPrompt}} + + + {{this.PromptImportantAspects()}} + """; + } + + private string PromptImportantAspects() + { + return string.IsNullOrWhiteSpace(this.importantAspects) ? string.Empty : $""" + # IMPORTANT_ASPECTS + + {this.importantAspects} + + """; + } + + private string SystemPromptOutputSchema() => + """ + { + "optimized_prompt": "string", + "recommendations": { + "clarity_and_directness": "string", + "examples_and_context": "string", + "sequential_steps": "string", + "structure_with_markers": "string", + "role_definition": "string", + "language_choice": "string" + } + } + """; + + private static bool TryParseOptimizationResult(string rawResponse, out PromptOptimizationResult parsedResult) + { + parsedResult = new(); + + if (TryDeserialize(rawResponse, out parsedResult)) + return true; + + var codeFenceMatch = JSON_CODE_FENCE_REGEX.Match(rawResponse); + if (codeFenceMatch.Success) + { + var codeFenceJson = codeFenceMatch.Groups["json"].Value; + if (TryDeserialize(codeFenceJson, out parsedResult)) + return true; + } + + var firstBrace = rawResponse.IndexOf('{'); + var lastBrace = rawResponse.LastIndexOf('}'); + if (firstBrace >= 0 && lastBrace > firstBrace) + { + var objectText = rawResponse[firstBrace..(lastBrace + 1)]; + if (TryDeserialize(objectText, out parsedResult)) + return true; + } + + return false; + } + + private static bool TryDeserialize(string json, out PromptOptimizationResult parsedResult) + { + parsedResult = new(); + + if (string.IsNullOrWhiteSpace(json)) + return false; + + try + { + var probe = JsonSerializer.Deserialize(json, JSON_OPTIONS); + if (probe is null || string.IsNullOrWhiteSpace(probe.OptimizedPrompt)) + return false; + + parsedResult = probe; + return true; + } + catch + { + return false; + } + } + + private void ApplyOptimizationResult(PromptOptimizationResult optimizationResult) + { + this.optimizedPrompt = optimizationResult.OptimizedPrompt.Trim(); + if (this.useCustomPromptGuide) + return; + + this.ApplyRecommendations(optimizationResult.Recommendations); + this.MarkRecommendationsUpdated(); + } + + private void MarkRecommendationsUpdated() + { + this.hasUpdatedDefaultRecommendations = true; + } + + private void ApplyRecommendations(PromptOptimizationRecommendations recommendations) + { + this.recClarityDirectness = this.EmptyFallback(recommendations.ClarityAndDirectness); + this.recExamplesContext = this.EmptyFallback(recommendations.ExamplesAndContext); + this.recSequentialSteps = this.EmptyFallback(recommendations.SequentialSteps); + this.recStructureMarkers = this.EmptyFallback(recommendations.StructureWithMarkers); + this.recRoleDefinition = this.EmptyFallback(recommendations.RoleDefinition); + this.recLanguageChoice = this.EmptyFallback(recommendations.LanguageChoice); + } + + private void ApplyFallbackRecommendations() + { + this.recClarityDirectness = T("Add clearer goals and explicit quality expectations."); + this.recExamplesContext = T("Add short examples and background context for your specific use case."); + this.recSequentialSteps = T("Break the task into numbered steps if order matters."); + this.recStructureMarkers = T("Use headings or markers to separate context, task, and constraints."); + this.recRoleDefinition = T("Define a role for the model to focus output style and expertise."); + this.recLanguageChoice = T("Use English for complex prompts and explicitly request response language if needed."); + } + + private string EmptyFallback(string text) + { + if (string.IsNullOrWhiteSpace(text)) + return T("No further recommendation in this area."); + + return text.Trim(); + } + + private void ResetOutput() + { + this.optimizedPrompt = string.Empty; + } + + private void ResetGuidelineSummaryToDefault() + { + this.recClarityDirectness = T("Use clear, explicit instructions and directly state quality expectations."); + this.recExamplesContext = T("Include short examples and context that explain the purpose behind your requirements."); + this.recSequentialSteps = T("Prefer numbered steps when task order matters."); + this.recStructureMarkers = T("Separate context, task, constraints, and output format with headings or markers."); + this.recRoleDefinition = T("Assign a role to shape tone, expertise, and focus."); + this.recLanguageChoice = T("For complex tasks, write prompts in English."); + } + + private void AddVisibleOptimizedPromptBlock() + { + if (string.IsNullOrWhiteSpace(this.optimizedPrompt)) + return; + + if (this.ChatThread is null) + return; + + var visibleResponseContent = new ContentText + { + Text = this.optimizedPrompt, + }; + + this.ChatThread.Blocks.Add(new ContentBlock + { + Time = DateTimeOffset.Now, + ContentType = ContentType.TEXT, + Role = ChatRole.AI, + HideFromUser = false, + Content = visibleResponseContent, + }); + } + + private static async Task ReadPromptingGuidelineAsync() + { +#if DEBUG + var guidelinePath = Path.Join(Environment.CurrentDirectory, "Assistants", "PromptOptimizer", "prompting_guideline.md"); + return File.Exists(guidelinePath) + ? await File.ReadAllTextAsync(guidelinePath) + : string.Empty; +#else + var resourceFileProvider = new ManifestEmbeddedFileProvider(Assembly.GetAssembly(type: typeof(Program))!, "Assistants/PromptOptimizer"); + var file = resourceFileProvider.GetFileInfo("prompting_guideline.md"); + if (!file.Exists) + return string.Empty; + + await using var fileStream = file.CreateReadStream(); + using var reader = new StreamReader(fileStream); + return await reader.ReadToEndAsync(); +#endif + } + + private async Task GetPromptingGuidelineForOptimizationAsync() + { + if (!this.useCustomPromptGuide) + return await ReadPromptingGuidelineAsync(); + + if (this.customPromptGuideFiles.Count == 0) + return string.Empty; + + if (!string.IsNullOrWhiteSpace(this.customPromptingGuidelineContent)) + return this.customPromptingGuidelineContent; + + var fileAttachment = this.customPromptGuideFiles.First(); + await this.LoadCustomPromptGuidelineContentAsync(fileAttachment); + return this.customPromptingGuidelineContent; + } + + private async Task SetUseCustomPromptGuide(bool useCustom) + { + this.useCustomPromptGuide = useCustom; + if (!useCustom) + return; + + if (this.customPromptGuideFiles.Count == 0) + return; + + var fileAttachment = this.customPromptGuideFiles.First(); + if (string.IsNullOrWhiteSpace(this.customPromptingGuidelineContent)) + await this.LoadCustomPromptGuidelineContentAsync(fileAttachment); + } + + private async Task OnCustomPromptGuideFilesChanged(HashSet files) + { + if (files.Count == 0) + { + this.customPromptGuideFiles.Clear(); + this.currentCustomPromptGuidePath = string.Empty; + this.customPromptingGuidelineContent = string.Empty; + return; + } + + var selected = files.FirstOrDefault(file => !string.Equals(file.FilePath, this.currentCustomPromptGuidePath, StringComparison.OrdinalIgnoreCase)) + ?? files.First(); + + var replacedPrevious = !string.IsNullOrWhiteSpace(this.currentCustomPromptGuidePath) && + !string.Equals(this.currentCustomPromptGuidePath, selected.FilePath, StringComparison.OrdinalIgnoreCase); + + this.customPromptGuideFiles = [ selected ]; + this.currentCustomPromptGuidePath = selected.FilePath; + + if (files.Count > 1 || replacedPrevious) + this.Snackbar.Add(T("Replaced the previously selected custom prompt guide file."), Severity.Info); + + await this.LoadCustomPromptGuidelineContentAsync(selected); + } + + private async Task LoadCustomPromptGuidelineContentAsync(FileAttachment fileAttachment) + { + if (!fileAttachment.Exists) + { + this.customPromptingGuidelineContent = string.Empty; + this.Snackbar.Add(T("The selected custom prompt guide file could not be found."), Severity.Warning); + return; + } + + try + { + this.isLoadingCustomPromptGuide = true; + this.customPromptingGuidelineContent = await UserFile.LoadFileData(fileAttachment.FilePath, this.RustService, this.DialogService); + if (string.IsNullOrWhiteSpace(this.customPromptingGuidelineContent)) + this.Snackbar.Add(T("The custom prompt guide file is empty or could not be read."), Severity.Warning); + } + catch + { + this.customPromptingGuidelineContent = string.Empty; + this.Snackbar.Add(T("Failed to load custom prompt guide content."), Severity.Error); + } + finally + { + this.isLoadingCustomPromptGuide = false; + this.StateHasChanged(); + } + } + + private async Task OpenPromptingGuidelineDialog() + { + var promptingGuideline = await ReadPromptingGuidelineAsync(); + if (string.IsNullOrWhiteSpace(promptingGuideline)) + { + this.Snackbar.Add(T("The prompting guideline file could not be loaded."), Severity.Warning); + return; + } + + var dialogParameters = new DialogParameters + { + { x => x.GuidelineMarkdown, promptingGuideline } + }; + + var dialogReference = await this.DialogService.ShowAsync(T("Prompting Guideline"), dialogParameters, Dialogs.DialogOptions.FULLSCREEN); + await dialogReference.Result; + } + + private async Task OpenCustomPromptGuideDialog() + { + if (this.customPromptGuideFiles.Count == 0) + return; + + var fileAttachment = this.customPromptGuideFiles.First(); + if (string.IsNullOrWhiteSpace(this.customPromptingGuidelineContent) && !this.isLoadingCustomPromptGuide) + await this.LoadCustomPromptGuidelineContentAsync(fileAttachment); + + var dialogParameters = new DialogParameters + { + { x => x.Document, fileAttachment }, + { x => x.FileContent, this.customPromptingGuidelineContent }, + }; + + await this.DialogService.ShowAsync(T("Custom Prompt Guide Preview"), dialogParameters, Dialogs.DialogOptions.FULLSCREEN); + } +} diff --git a/app/MindWork AI Studio/Assistants/PromptOptimizer/PromptOptimizationResult.cs b/app/MindWork AI Studio/Assistants/PromptOptimizer/PromptOptimizationResult.cs new file mode 100644 index 00000000..88a78374 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/PromptOptimizer/PromptOptimizationResult.cs @@ -0,0 +1,33 @@ +using System.Text.Json.Serialization; + +namespace AIStudio.Assistants.PromptOptimizer; + +public sealed class PromptOptimizationResult +{ + [JsonPropertyName("optimized_prompt")] + public string OptimizedPrompt { get; set; } = string.Empty; + + [JsonPropertyName("recommendations")] + public PromptOptimizationRecommendations Recommendations { get; set; } = new(); +} + +public sealed class PromptOptimizationRecommendations +{ + [JsonPropertyName("clarity_and_directness")] + public string ClarityAndDirectness { get; set; } = string.Empty; + + [JsonPropertyName("examples_and_context")] + public string ExamplesAndContext { get; set; } = string.Empty; + + [JsonPropertyName("sequential_steps")] + public string SequentialSteps { get; set; } = string.Empty; + + [JsonPropertyName("structure_with_markers")] + public string StructureWithMarkers { get; set; } = string.Empty; + + [JsonPropertyName("role_definition")] + public string RoleDefinition { get; set; } = string.Empty; + + [JsonPropertyName("language_choice")] + public string LanguageChoice { get; set; } = string.Empty; +} diff --git a/app/MindWork AI Studio/Assistants/PromptOptimizer/prompting_guideline.md b/app/MindWork AI Studio/Assistants/PromptOptimizer/prompting_guideline.md new file mode 100644 index 00000000..701018e4 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/PromptOptimizer/prompting_guideline.md @@ -0,0 +1,85 @@ +# 1 – Be Clear and Direct + +LLMs respond best to clear, explicit instructions. Being specific about your desired output improves results. If you want high-quality work, ask for it directly rather than expecting the model to guess. + +Think of the LLM as a skilled new employee: They do not know your specific workflows yet. The more precisely you explain what you want, the better the result. + +**Golden Rule:** If a colleague would be confused by your prompt without extra context, the LLM will be too. + +**Less Effective:** +```text +Create an analytics dashboard +``` + +**More Effective:** +```text +Create an analytics dashboard. Include relevant features and interactions. Go beyond the basics to create a fully-featured implementation. +``` + +# 2 – Add Examples and Context to Improve Performance + +Providing examples, context, or the reason behind your instructions helps the model understand your goals. + +**Less Effective:** +```text +NEVER use ellipses +``` + +**More Effective:** +```text +Your response will be read aloud by a text-to-speech engine, so never use ellipses since the engine will not know how to pronounce them. +``` + +The model can generalize from the explanation. + +# 3 – Use Sequential Steps + +When the order of tasks matters, provide instructions as a numbered list. + +**Example:** +```text +1. Analyze the provided text for key themes. +2. Extract the top 5 most frequent terms. +3. Format the output as a table with columns: Term, Frequency, Context. +``` + +# 4 – Structure Prompts with Markers + +Headings (e.g., `#` or `###`) or backticks (` `````` `) help the model parse complex prompts, especially when mixing instructions, context, and data. + +**Less Effective:** +```text +{text input here} + +Summarize the text above as a bullet point list of the most important points. +``` + +**More Effective:** +```text +# Text: +```{text input here}``` + +# Task: +Summarize the text above as a bullet point list of the most important points. +``` + +# 5 – Give the LLM a Role + +Setting a role in your prompt focuses the LLM's behavior and tone. Even a single sentence makes a difference. + +**Example:** +```text +You are a helpful coding assistant specializing in Python. +``` +```text +You are a senior marketing expert with 10 years of experience in the aerospace industry. +``` + +# 6 – Prompt Language + +LLMs are primarily trained on English text. They generally perform best with prompts written in **English**, especially for complex tasks. + +* **Recommendation:** Write your prompts in English. +* **If needed:** You can ask the LLM to respond in your native language (e.g., "Answer in German"). +* **Note:** This is especially important for smaller models, which may have limited multilingual capabilities. + diff --git a/app/MindWork AI Studio/Assistants/RewriteImprove/AssistantRewriteImprove.razor b/app/MindWork AI Studio/Assistants/RewriteImprove/AssistantRewriteImprove.razor index 952ff997..75393fab 100644 --- a/app/MindWork AI Studio/Assistants/RewriteImprove/AssistantRewriteImprove.razor +++ b/app/MindWork AI Studio/Assistants/RewriteImprove/AssistantRewriteImprove.razor @@ -5,4 +5,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/RewriteImprove/AssistantRewriteImprove.razor.cs b/app/MindWork AI Studio/Assistants/RewriteImprove/AssistantRewriteImprove.razor.cs index 2ddac0fd..81eaa6b3 100644 --- a/app/MindWork AI Studio/Assistants/RewriteImprove/AssistantRewriteImprove.razor.cs +++ b/app/MindWork AI Studio/Assistants/RewriteImprove/AssistantRewriteImprove.razor.cs @@ -1,4 +1,3 @@ -using AIStudio.Chat; using AIStudio.Dialogs.Settings; namespace AIStudio.Assistants.RewriteImprove; @@ -42,10 +41,9 @@ public partial class AssistantRewriteImprove : AssistantBaseCore SubmitAction => this.RewriteText; - protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with - { - SystemPrompt = SystemPrompts.DEFAULT, - }; + protected override string SendToChatVisibleUserPromptPrefix => T("Rewrite and improve the following text:"); + + protected override string SendToChatVisibleUserPromptContent => this.inputText; protected override void ResetForm() { @@ -128,8 +126,8 @@ public partial class AssistantRewriteImprove : AssistantBaseCore @T("Attach documents") - + @T("Details about the desired presentation") @@ -66,4 +66,4 @@ - + diff --git a/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.cs b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.cs index 1faf2bde..33a07a5c 100644 --- a/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.cs @@ -82,7 +82,7 @@ public partial class SlideAssistant : AssistantBaseCore