From 6eb23ebbcbb15447cdf7643cdc7431515ea3e799 Mon Sep 17 00:00:00 2001 From: Sabrina-devops Date: Sun, 25 Oct 2026 18:52:39 +0100 Subject: [PATCH] Added PowerPoint templates to the Slide Assistant (#1055) Co-authored-by: Thorsten Sommer --- AGENTS.md | 1 + app/AGENTS.md | 8 + .../Assistants/AssistantBase.razor | 12 +- .../Assistants/AssistantBase.razor.cs | 67 +- .../Assistants/AssistantLowerBase.cs | 17 +- .../Assistants/Builder/AssistantBuilder.razor | 78 +- .../Assistants/Builder/LuaResponse.Parse.cs | 4 +- .../Assistants/I18N/allTexts.lua | 1453 ++++++++++++++++- .../SlideBuilder/PresentationOccasion.cs | 30 + .../PresentationOccasionExtensions.cs | 56 + .../SlideBuilder/SlideAssistant.razor | 130 +- .../SlideAssistant.razor.Library.cs | 257 +++ .../SlideAssistant.razor.Presentation.cs | 592 +++++++ .../SlideAssistant.razor.Progress.cs | 60 + .../SlideBuilder/SlideAssistant.razor.cs | 426 ++++- .../SlideBuilder/SlideAssistantTexts.cs | 41 + .../SlideBuilder/TemplateSlideExtensions.cs | 30 + .../TemplateSlideUseExtensions.cs | 17 + app/MindWork AI Studio/Chat/ContentText.cs | 31 +- .../Components/CompactExpansionPanel.razor | 15 + .../Components/CompactExpansionPanel.razor.cs | 39 + .../Components/ConfigurationDirectory.razor | 51 +- .../ConfigurationDirectory.razor.cs | 23 + .../Components/ConfigurationFile.razor | 51 +- .../Components/ConfigurationFile.razor.cs | 23 + .../Components/LayoutChoicePanels.razor | 13 + .../Components/LayoutChoicePanels.razor.cs | 62 + .../Components/PathDropZone.razor.cs | 9 + .../Components/SelectDirectory.razor.cs | 32 +- .../Components/SelectFile.razor.cs | 39 +- .../AssistantPluginRevisionDialog.razor | 18 +- .../DirectChatLauncherSettingsDialog.razor | 18 +- .../Settings/SettingsDialogSlideBuilder.razor | 82 +- .../SettingsDialogSlideBuilder.razor.cs | 167 +- .../MindWork AI Studio.csproj | 1 + app/MindWork AI Studio/Pages/Assistants.razor | 2 +- app/MindWork AI Studio/Pages/Supporters.razor | 2 +- .../Plugins/configuration/plugin.lua | 111 ++ .../plugin.lua | 1453 ++++++++++++++++- .../plugin.lua | 1453 ++++++++++++++++- .../ConfigurationSelectDataFactory.cs | 8 +- .../Settings/DataModel/Data.cs | 2 +- .../Settings/DataModel/DataSlideBuilder.cs | 105 +- .../Settings/ManagedConfiguration.Parsing.cs | 165 +- .../Settings/ManagedConfiguration.Register.cs | 72 + .../Settings/ManagedConfiguration.cs | 68 + .../Settings/PluginFilePath.cs | 172 ++ .../Settings/PluginIconFile.cs | 65 +- .../Tools/ComponentsExtensions.cs | 2 +- app/MindWork AI Studio/Tools/DroppedFile.cs | 42 + app/MindWork AI Studio/Tools/DroppedFolder.cs | 36 + .../Tools/FileExportFormatExtensions.cs | 2 +- .../Tools/PluginSystem/PluginConfiguration.cs | 42 + .../Tools/PowerPoint/AGENTS.md | 79 + .../Tools/PowerPoint/CLAUDE.md | 1 + .../Tools/PowerPoint/ChosenLayouts.cs | 79 + .../Tools/PowerPoint/IPictureSource.cs | 15 + .../Tools/PowerPoint/LayoutFamily.cs | 27 + .../Tools/PowerPoint/LayoutPurpose.cs | 207 +++ .../Tools/PowerPoint/LayoutPurposeArea.cs | 46 + .../PowerPoint/LayoutPurposeAreaExtensions.cs | 26 + .../LayoutPurposeExtensions.Business.cs | 54 + .../LayoutPurposeExtensions.Framing.cs | 25 + .../LayoutPurposeExtensions.General.cs | 39 + .../PowerPoint/LayoutPurposeExtensions.Law.cs | 30 + .../LayoutPurposeExtensions.Medicine.cs | 28 + .../LayoutPurposeExtensions.Science.cs | 41 + .../LayoutPurposeExtensions.Teaching.cs | 29 + .../PowerPoint/LayoutPurposeExtensions.cs | 89 + .../Tools/PowerPoint/LayoutPurposeInfo.cs | 10 + .../Tools/PowerPoint/LayoutVariant.cs | 8 + .../Tools/PowerPoint/LibraryPicture.cs | 9 + .../Tools/PowerPoint/LibraryPictures.cs | 14 + .../Tools/PowerPoint/PictureLibrary.cs | 100 ++ .../Tools/PowerPoint/PictureLibraryContent.cs | 21 + .../Tools/PowerPoint/PlaceholderRole.cs | 37 + .../PowerPoint/PlaceholderRoleExtensions.cs | 95 ++ .../Tools/PowerPoint/PresentationFile.cs | 111 ++ .../PowerPoint/PresentationFileResult.cs | 14 + .../PresentationTemplate.Catalog.cs | 368 +++++ .../PresentationTemplate.Default.cs | 69 + .../PresentationTemplate.Families.cs | 140 ++ .../PresentationTemplate.Reading.cs | 332 ++++ .../PowerPoint/PresentationTemplate.Slides.cs | 455 ++++++ .../Tools/PowerPoint/PresentationTemplate.cs | 104 ++ .../PowerPoint/PresentationWriteOptions.cs | 9 + .../PowerPoint/PresentationWriteResult.cs | 7 + .../PowerPoint/PresentationWriter.Sections.cs | 60 + .../PowerPoint/PresentationWriter.Shapes.cs | 346 ++++ .../PresentationWriter.TemplateSlides.cs | 443 +++++ .../Tools/PowerPoint/PresentationWriter.cs | 223 +++ .../Tools/PowerPoint/RustPictureSource.cs | 38 + .../Tools/PowerPoint/SlideDeckSpec.Outline.cs | 141 ++ .../Tools/PowerPoint/SlideDeckSpec.Parsing.cs | 201 +++ .../Tools/PowerPoint/SlideDeckSpec.cs | 14 + .../PowerPoint/SlideDeckSpecValidator.cs | 521 ++++++ .../Tools/PowerPoint/SlideParagraph.cs | 8 + .../Tools/PowerPoint/SlidePicture.cs | 11 + .../Tools/PowerPoint/SlideSpec.cs | 74 + .../Tools/PowerPoint/SlideTableSpec.cs | 8 + .../Tools/PowerPoint/SlideTextBlock.cs | 7 + .../Tools/PowerPoint/SlotBounds.cs | 54 + .../Tools/PowerPoint/StreamedSlideCounter.cs | 50 + .../Tools/PowerPoint/TemplateLayout.cs | 36 + .../Tools/PowerPoint/TemplateSlide.cs | 75 + .../Tools/PowerPoint/TemplateSlideContent.cs | 8 + .../Tools/PowerPoint/TemplateSlideElement.cs | 23 + .../PowerPoint/TemplateSlideElementKind.cs | 41 + .../TemplateSlideElementKindExtensions.cs | 21 + .../Tools/PowerPoint/TemplateSlideShapes.cs | 78 + .../Tools/PowerPoint/TemplateSlideUse.cs | 22 + .../TemplateSlideUseListExtensions.cs | 28 + .../Tools/PowerPoint/TemplateSlot.cs | 45 + .../Tools/PowerPoint/TemplateSlotCopy.cs | 15 + .../Tools/PowerPoint/TextCapacity.cs | 12 + .../Tools/Rust/FileTypes.cs | 14 + app/MindWork AI Studio/packages.lock.json | 22 + .../wwwroot/changelog/v26.10.1.md | 4 + app/Tests/Settings/PluginFilePathTests.cs | 121 ++ app/Tests/Settings/PreselectedLayoutsTests.cs | 147 ++ .../PreselectedMaxBulletPointsTests.cs | 131 ++ .../PreselectedTemplateSlideUsesTests.cs | 148 ++ .../ManagedSettingsCoverageTests.cs | 19 +- .../Tools/PowerPoint/ChosenLayoutsTests.cs | 102 ++ .../Tools/PowerPoint/LayoutPurposeTests.cs | 52 + .../Tools/PowerPoint/PictureLibraryTests.cs | 111 ++ .../Tools/PowerPoint/PresentationFileTests.cs | 126 ++ .../PowerPoint/PresentationTemplateTests.cs | 549 +++++++ .../PowerPoint/PresentationWriterTests.cs | 769 +++++++++ .../Tools/PowerPoint/SlideDeckSpecTests.cs | 273 ++++ .../PowerPoint/SlideDeckSpecValidatorTests.cs | 517 ++++++ app/Tests/Tools/PowerPoint/StackedHeadings.cs | 67 + .../PowerPoint/StreamedSlideCounterTests.cs | 57 + .../PowerPoint/TemplateSlideUsesTests.cs | 54 + app/Tests/Tools/PowerPoint/TestTemplate.cs | 532 ++++++ documentation/Enterprise IT.md | 166 ++ 136 files changed, 16535 insertions(+), 522 deletions(-) create mode 100644 app/MindWork AI Studio/Assistants/SlideBuilder/PresentationOccasion.cs create mode 100644 app/MindWork AI Studio/Assistants/SlideBuilder/PresentationOccasionExtensions.cs create mode 100644 app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Library.cs create mode 100644 app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Presentation.cs create mode 100644 app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Progress.cs create mode 100644 app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistantTexts.cs create mode 100644 app/MindWork AI Studio/Assistants/SlideBuilder/TemplateSlideExtensions.cs create mode 100644 app/MindWork AI Studio/Assistants/SlideBuilder/TemplateSlideUseExtensions.cs create mode 100644 app/MindWork AI Studio/Components/CompactExpansionPanel.razor create mode 100644 app/MindWork AI Studio/Components/CompactExpansionPanel.razor.cs create mode 100644 app/MindWork AI Studio/Components/LayoutChoicePanels.razor create mode 100644 app/MindWork AI Studio/Components/LayoutChoicePanels.razor.cs create mode 100644 app/MindWork AI Studio/Settings/PluginFilePath.cs create mode 100644 app/MindWork AI Studio/Tools/DroppedFile.cs create mode 100644 app/MindWork AI Studio/Tools/DroppedFolder.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/AGENTS.md create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/CLAUDE.md create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/ChosenLayouts.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/IPictureSource.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutFamily.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurpose.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeArea.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeAreaExtensions.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeExtensions.Business.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeExtensions.Framing.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeExtensions.General.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeExtensions.Law.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeExtensions.Medicine.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeExtensions.Science.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeExtensions.Teaching.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeExtensions.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutPurposeInfo.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LayoutVariant.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LibraryPicture.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/LibraryPictures.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PictureLibrary.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PictureLibraryContent.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PlaceholderRole.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PlaceholderRoleExtensions.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationFile.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationFileResult.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationTemplate.Catalog.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationTemplate.Default.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationTemplate.Families.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationTemplate.Reading.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationTemplate.Slides.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationTemplate.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationWriteOptions.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationWriteResult.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationWriter.Sections.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationWriter.Shapes.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationWriter.TemplateSlides.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/PresentationWriter.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/RustPictureSource.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlideDeckSpec.Outline.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlideDeckSpec.Parsing.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlideDeckSpec.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlideDeckSpecValidator.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlideParagraph.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlidePicture.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlideSpec.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlideTableSpec.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlideTextBlock.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/SlotBounds.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/StreamedSlideCounter.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateLayout.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlide.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlideContent.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlideElement.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlideElementKind.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlideElementKindExtensions.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlideShapes.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlideUse.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlideUseListExtensions.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlot.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TemplateSlotCopy.cs create mode 100644 app/MindWork AI Studio/Tools/PowerPoint/TextCapacity.cs create mode 100644 app/Tests/Settings/PluginFilePathTests.cs create mode 100644 app/Tests/Settings/PreselectedLayoutsTests.cs create mode 100644 app/Tests/Settings/PreselectedMaxBulletPointsTests.cs create mode 100644 app/Tests/Settings/PreselectedTemplateSlideUsesTests.cs create mode 100644 app/Tests/Tools/PowerPoint/ChosenLayoutsTests.cs create mode 100644 app/Tests/Tools/PowerPoint/LayoutPurposeTests.cs create mode 100644 app/Tests/Tools/PowerPoint/PictureLibraryTests.cs create mode 100644 app/Tests/Tools/PowerPoint/PresentationFileTests.cs create mode 100644 app/Tests/Tools/PowerPoint/PresentationTemplateTests.cs create mode 100644 app/Tests/Tools/PowerPoint/PresentationWriterTests.cs create mode 100644 app/Tests/Tools/PowerPoint/SlideDeckSpecTests.cs create mode 100644 app/Tests/Tools/PowerPoint/SlideDeckSpecValidatorTests.cs create mode 100644 app/Tests/Tools/PowerPoint/StackedHeadings.cs create mode 100644 app/Tests/Tools/PowerPoint/StreamedSlideCounterTests.cs create mode 100644 app/Tests/Tools/PowerPoint/TemplateSlideUsesTests.cs create mode 100644 app/Tests/Tools/PowerPoint/TestTemplate.cs diff --git a/AGENTS.md b/AGENTS.md index 2aaca8a34..74da49154 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,6 +39,7 @@ Therefore, before you plan, read, or change anything in one of these areas, read | anything under `app/MindWork AI Studio/Models/` or `app/Tests/Models/` | `app/MindWork AI Studio/Models/AGENTS.md` | | anything under `app/MindWork AI Studio/Tools/Services/Indexing/`, or `DataSourceEmbeddingService` | `app/MindWork AI Studio/Tools/Services/Indexing/AGENTS.md` | | anything under `app/MindWork AI Studio/Tools/Databases/` | `app/MindWork AI Studio/Tools/Databases/AGENTS.md` | +| anything under `app/MindWork AI Studio/Tools/PowerPoint/` or `app/Tests/Tools/PowerPoint/`, or the PowerPoint part of the Slide Assistant | `app/MindWork AI Studio/Tools/PowerPoint/AGENTS.md` | This file keeps only what applies to the whole repository. `app/AGENTS.md` keeps what applies to all of the .NET app, such as the rules for code which calls into one of the areas below it. Add instructions about a diff --git a/app/AGENTS.md b/app/AGENTS.md index 111dd266f..a15f1d59a 100644 --- a/app/AGENTS.md +++ b/app/AGENTS.md @@ -136,6 +136,14 @@ active language plugin. Storage sizes are the exception: they keep using the byt **Area guide:** `app/MindWork AI Studio/Tools/Databases/AGENTS.md`, with both stores and what to keep in mind when working on them, EF Core migrations included. +## Slide Assistant and PowerPoint + +The Slide Assistant plans slides for the layouts of a PowerPoint template and writes the +presentation with the Open XML SDK (`DocumentFormat.OpenXml`), in `app/MindWork AI Studio/Tools/PowerPoint/`. + +**Area guide:** `app/MindWork AI Studio/Tools/PowerPoint/AGENTS.md`, with how a presentation comes about +and the rules which are easy to break. + ## Enterprise IT Support AI Studio supports centralized configuration for enterprise environments: diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor b/app/MindWork AI Studio/Assistants/AssistantBase.razor index f9d0379b6..9660d2c29 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor @@ -69,7 +69,17 @@ @if (this.ShowDedicatedProgress && this.IsProcessing) { - + @if (string.IsNullOrWhiteSpace(this.ProgressText)) + { + + } + else + { + + + @this.ProgressText + + } }
diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs index e26db1351..45b179173 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs @@ -107,6 +107,11 @@ public abstract partial class AssistantBase : AssistantLowerBase wher protected virtual bool ShowProfileSelection => true; protected virtual bool ShowDedicatedProgress => false; + + /// + /// What the assistant is doing right now, shown below the dedicated progress bar; empty for no text. + /// + protected virtual string ProgressText => string.Empty; protected virtual bool ShowSendTo => true; @@ -124,6 +129,15 @@ public abstract partial class AssistantBase : AssistantLowerBase wher protected virtual bool ShowReset => true; + /// + /// Whether the system prompt starts with the current date and time. + /// + /// + /// Off for most assistants, whose results do not depend on the date. An assistant which writes + /// the date into its result, or plans around it, turns this on rather than guessing the date. + /// + protected virtual bool IncludeDateTime => false; + protected virtual string? SendToChatVisibleUserPromptPrefix => null; protected virtual string? SendToChatVisibleUserPromptContent => null; @@ -385,7 +399,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher { this.ChatThread = new() { - IncludeDateTime = false, + IncludeDateTime = this.IncludeDateTime, SelectedProvider = this.ProviderSettings.Id, SelectedProfile = this.AllowProfiles ? this.CurrentProfile.Id : Profile.NO_PROFILE.Id, SystemPrompt = this.SystemPrompt, @@ -403,7 +417,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher var chatId = Guid.NewGuid(); this.ChatThread = new() { - IncludeDateTime = false, + IncludeDateTime = this.IncludeDateTime, SelectedProvider = this.ProviderSettings.Id, SelectedProfile = this.AllowProfiles ? this.CurrentProfile.Id : Profile.NO_PROFILE.Id, SystemPrompt = this.SystemPrompt, @@ -527,10 +541,46 @@ public abstract partial class AssistantBase : AssistantLowerBase wher InitialRemoteWait = true, }; + // + // The stream calls this for every chunk and waits for it. A checkpoint captures the whole + // state of the assistant and makes the main layout render as well, so both happen only now + // and then. When the stream is done, both happen in any case: + // + var lastRendering = DateTimeOffset.MinValue; + var lastCheckpoint = DateTimeOffset.MinValue; + string? lastProgressText = null; aiText.StreamingEvent = async () => { - await this.CheckpointAssistantSession(); - await this.RefreshAssistantUIAsync(); + var now = DateTimeOffset.Now; + if (now - lastCheckpoint >= STREAMING_CHECKPOINT_MIN_TIME) + { + lastCheckpoint = now; + await this.CheckpointAssistantSession(); + } + + if (now - lastRendering < STREAMING_RENDER_MIN_TIME) + return; + + lastRendering = now; + if (!hideContentFromUser) + { + await this.RefreshAssistantUIAsync(); + return; + } + + // + // A hidden answer shows nothing but the progress text, so the whole form renders only + // when that text changed. Thinking models stream for minutes before they write a word: + // + await this.RefreshAssistantUIAsync(() => + { + var progressText = this.ProgressText; + if (progressText == lastProgressText) + return false; + + lastProgressText = progressText; + return true; + }); }; aiText.StreamingDone = async () => @@ -995,15 +1045,20 @@ public abstract partial class AssistantBase : AssistantLowerBase wher /// /// Refreshes the component when it is still mounted. /// + /// Decides whether anything visible changed, asked on the thread of the renderer, so it may read what the rendering reads; null to render in any case. /// A task that completes after the renderer was notified. - protected async Task RefreshAssistantUIAsync() + protected async Task RefreshAssistantUIAsync(Func? hasChanged = null) { if (this.isDisposed) return; try { - await this.InvokeAsync(this.StateHasChanged); + await this.InvokeAsync(() => + { + if (hasChanged is null || hasChanged()) + this.StateHasChanged(); + }); } catch (InvalidOperationException) { diff --git a/app/MindWork AI Studio/Assistants/AssistantLowerBase.cs b/app/MindWork AI Studio/Assistants/AssistantLowerBase.cs index bfde4c2d5..b6ea7a134 100644 --- a/app/MindWork AI Studio/Assistants/AssistantLowerBase.cs +++ b/app/MindWork AI Studio/Assistants/AssistantLowerBase.cs @@ -12,7 +12,22 @@ public abstract class AssistantLowerBase : MSGComponentBase internal const string RESULT_DIV_ID = "assistantResult"; internal const string BEFORE_RESULT_DIV_ID = "beforeAssistantResult"; internal const string AFTER_RESULT_DIV_ID = "afterAssistantResult"; - + + /// + /// The minimum time between two renderings of the assistant while an answer streams in. + /// + /// + /// The stream waits for each rendering, and an assistant renders its whole form, which may hold + /// more than a hundred fields. Ten renderings a second still read as a live stream. + /// + private protected static readonly TimeSpan STREAMING_RENDER_MIN_TIME = TimeSpan.FromMilliseconds(100); + + /// + /// The minimum time between two checkpoints of the assistant session while an answer streams in, + /// as in the chat. + /// + private protected static readonly TimeSpan STREAMING_CHECKPOINT_MIN_TIME = TimeSpan.FromSeconds(3); + protected static readonly AssistantSessionStateKey PROVIDER_SETTINGS_STATE_KEY = new(nameof(ProviderSettings)); protected static readonly AssistantSessionStateKey INPUT_IS_VALID_STATE_KEY = new(nameof(InputIsValid)); protected static readonly AssistantSessionStateKey CURRENT_PROFILE_STATE_KEY = new(nameof(CurrentProfile)); diff --git a/app/MindWork AI Studio/Assistants/Builder/AssistantBuilder.razor b/app/MindWork AI Studio/Assistants/Builder/AssistantBuilder.razor index 7aca54644..c4a666c20 100644 --- a/app/MindWork AI Studio/Assistants/Builder/AssistantBuilder.razor +++ b/app/MindWork AI Studio/Assistants/Builder/AssistantBuilder.razor @@ -43,44 +43,32 @@ } - - - -
- - - @T("Advanced Options") - -
-
- - @* A launcher shows this field inside its own frame above, next to the chat settings - it belongs with. *@ - @if (!this.createChatLauncher) + + @* A launcher shows this field inside its own frame above, next to the chat settings + it belongs with. *@ + @if (!this.createChatLauncher) + { + + } + + @if (!this.createChatLauncher) + { + + + + @foreach (var component in ASSISTANT_COMPONENT_OPTIONS) { - + + @component.GetDisplayName() + } - - @if (!this.createChatLauncher) - { - - - - @foreach (var component in ASSISTANT_COMPONENT_OPTIONS) - { - - @component.GetDisplayName() - - } - - - - - - } - -
-
+ + + + + + } + @this.HighPerformanceLLMInfo @@ -122,21 +110,9 @@ else @code { private protected override RenderFragment? BelowSubmitContent => this.step is BuilderStep.DONE && !string.IsNullOrWhiteSpace(this.generatedLuaAssistant) ? @ - - - -
- - - @T("Generated Lua plugin") - -
-
- - - -
-
+ + + diff --git a/app/MindWork AI Studio/Assistants/Builder/LuaResponse.Parse.cs b/app/MindWork AI Studio/Assistants/Builder/LuaResponse.Parse.cs index a3313aff1..5c48d6bbc 100644 --- a/app/MindWork AI Studio/Assistants/Builder/LuaResponse.Parse.cs +++ b/app/MindWork AI Studio/Assistants/Builder/LuaResponse.Parse.cs @@ -163,8 +163,8 @@ internal sealed partial class LuaResponse /// Reads the first complete JSON object out of a model answer that may carry text around it. /// /// - /// Shared with the launcher texts response, which is a different shape but arrives the same - /// way, wrapped in whatever prose the model felt like adding. + /// Shared with the launcher texts response and the slide deck of the Slide Assistant, which are + /// different shapes but arrive the same way, wrapped in whatever prose the model felt like adding. /// internal static string ExtractJson(string input) { diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 33e75619e..3b45fb54c 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -2515,36 +2515,147 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::AUDIENCEPROFILEEXTENSIONS:: -- Software developers UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::AUDIENCEPROFILEEXTENSIONS::T831424531"] = "Software developers" +-- Kick-off +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T1289358099"] = "Kick-off" + +-- Pitch +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T2019197265"] = "Pitch" + +-- Unspecified occasion +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T227451887"] = "Unspecified occasion" + +-- Training +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T2287937623"] = "Training" + +-- Conference talk +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T2421639635"] = "Conference talk" + +-- Other occasion +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T2509856260"] = "Other occasion" + +-- Talk +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T2530449775"] = "Talk" + +-- Lecture +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T2695461681"] = "Lecture" + +-- Presentation of research results +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T2950712069"] = "Presentation of research results" + +-- Workshop of several days +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T3144398028"] = "Workshop of several days" + +-- Workshop of one day +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T3310080195"] = "Workshop of one day" + +-- Team meeting +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T3390299757"] = "Team meeting" + +-- Product presentation +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T3522562796"] = "Product presentation" + +-- Defense of a thesis or dissertation +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T3767586701"] = "Defense of a thesis or dissertation" + +-- Project or status report +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T4260502387"] = "Project or status report" + +-- Report to management +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T4288525803"] = "Report to management" + +-- Keynote +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::PRESENTATIONOCCASIONEXTENSIONS::T657131160"] = "Keynote" + +-- Documents and images attached here are source material: the LLM reads them, but puts none of them on a slide. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T101042708"] = "Documents and images attached here are source material: the LLM reads them, but puts none of them on a slide." + +-- Attach the pictures which the presentation must show, e.g., photos, diagrams, or screenshots. Each of them goes on exactly one slide with room for a picture. Only PNG and JPEG pictures are possible. An LLM which can read images sees them; any other LLM knows only their file names, so clear names help. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1011018167"] = "Attach the pictures which the presentation must show, e.g., photos, diagrams, or screenshots. Each of them goes on exactly one slide with room for a picture. Only PNG and JPEG pictures are possible. An LLM which can read images sees them; any other LLM knows only their file names, so clear names help." + +-- The LLM is planning the structure of the presentation... +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1047730248"] = "The LLM is planning the structure of the presentation..." + +-- Slides of the template +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1178900119"] = "Slides of the template" + -- Important Aspects UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1379883528"] = "Important Aspects" -- Extent of the planned presentation UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1408740929"] = "Extent of the planned presentation" +-- Save the presentation +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T144139589"] = "Save the presentation" + +-- The template has no layouts with room for content. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1443064107"] = "The template has no layouts with room for content." + +-- The PowerPoint template of your organization is not available right now, e.g., because its network drive cannot be reached. Until it is, the assistant plans an outline only. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1473992941"] = "The PowerPoint template of your organization is not available right now, e.g., because its network drive cannot be reached. Until it is, the assistant plans an outline only." + +-- Occasion of the presentation +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1500915876"] = "Occasion of the presentation" + +-- Shown on every slide whose layout has a footer, e.g., your name, organization, and date. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1541134619"] = "Shown on every slide whose layout has a footer, e.g., your name, organization, and date." + -- You might want to specify important aspects that the LLM should consider when creating the slides. For example, the use of emojis or specific topics that should be highlighted. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1672597841"] = "You might want to specify important aspects that the LLM should consider when creating the slides. For example, the use of emojis or specific topics that should be highlighted." +-- Occasion +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1774567962"] = "Occasion" + -- Details about the desired presentation UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1793579367"] = "Details about the desired presentation" -- Text content UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1820253043"] = "Text content" +-- Maximum number of bullet points per slide +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1849301398"] = "Maximum number of bullet points per slide" + +-- Slide Assistant +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1883918574"] = "Slide Assistant" + +-- These files are already attached as pictures for the slides and were removed from the documents: {0} +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T1915311879"] = "These files are already attached as pictures for the slides and were removed from the documents: {0}" + -- Please provide a text or at least one valid document or image. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2013746884"] = "Please provide a text or at least one valid document or image." -- Content to derive slide from UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2086228265"] = "Content to derive slide from" +-- Please describe the occasion. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2152067908"] = "Please describe the occasion." + +-- The occasion helps the LLM to structure the presentation. A lecture, for example, may close its chapters with an interim summary or with room for questions, and a report to management leads with the key messages. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2174617817"] = "The occasion helps the LLM to structure the presentation. A lecture, for example, may close its chapters with an interim summary or with room for questions, and a report to management leads with the key messages." + +-- Counting the pictures of the folder... +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2357708754"] = "Counting the pictures of the folder..." + -- Target language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T237828418"] = "Target language" +-- {0} other files are left out, because they are neither PNG nor JPEG. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2384026372"] = "{0} other files are left out, because they are neither PNG nor JPEG." + -- (Optional) Important Aspects UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T24391765"] = "(Optional) Important Aspects" +-- The folder holds no PNG or JPEG pictures. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2452478824"] = "The folder holds no PNG or JPEG pictures." + -- Audience age group UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2496533563"] = "Audience age group" +-- Other occasion +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2509856260"] = "Other occasion" + +-- Not every slide fits its layout as planned; for example, a text may run long. Please check the slides before presenting. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2541602129"] = "Not every slide fits its layout as planned; for example, a text may run long. Please check the slides before presenting." + -- You can enter text, use one or more documents or images, or use both. At least one of these options is required. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2542045947"] = "You can enter text, use one or more documents or images, or use both. At least one of these options is required." @@ -2554,17 +2665,29 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2591284123 -- Audience organizational level UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2599228833"] = "Audience organizational level" +-- Picture library +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2652783742"] = "Picture library" + +-- Please choose a PowerPoint template to create a file from the slides. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2660312931"] = "Please choose a PowerPoint template to create a file from the slides." + +-- Keep empty picture placeholders +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2712554607"] = "Keep empty picture placeholders" + +-- Your template offers its layouts in several colors. Choose one for the presentation. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2751707658"] = "Your template offers its layouts in several colors. Choose one for the presentation." + +-- The LLM did not describe the slides in a usable form, even after a second request. Please try again, or choose another model. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2799381756"] = "The LLM did not describe the slides in a usable form, even after a second request. Please try again, or choose another model." + -- Number of slides UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2823798965"] = "Number of slides" --- This assistant helps you create clear, structured slides from long texts or documents. Enter a presentation title and provide the content either as text or with one or more documents. Important aspects allow you to add instructions to the LLM regarding output or formatting. Set the number of slides either directly or based on your desired presentation duration. You can also specify the number of bullet points. If the default value of 0 is not changed, the LLM will independently determine how many slides or bullet points to generate. The output can be flexibly generated in various languages and tailored to a specific audience. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2910177051"] = "This assistant helps you create clear, structured slides from long texts or documents. Enter a presentation title and provide the content either as text or with one or more documents. Important aspects allow you to add instructions to the LLM regarding output or formatting. Set the number of slides either directly or based on your desired presentation duration. You can also specify the number of bullet points. If the default value of 0 is not changed, the LLM will independently determine how many slides or bullet points to generate. The output can be flexibly generated in various languages and tailored to a specific audience." +-- Pictures for the slides +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2882839332"] = "Pictures for the slides" --- Slide Planner Assistant -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2924755246"] = "Slide Planner Assistant" - --- The result of your previous slide builder session. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3000286990"] = "The result of your previous slide builder session." +-- Use no template +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T2967784903"] = "Use no template" -- Please enter a title for the presentation. This will help the LLM to select more relevant content. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3013824309"] = "Please enter a title for the presentation. This will help the LLM to select more relevant content." @@ -2575,15 +2698,39 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3049299559 -- Create Slides UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3079776593"] = "Create Slides" +-- The picture library of your organization is not available right now, e.g., because its network drive cannot be reached. Until it is, the assistant plans the slides without it. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T314279150"] = "The picture library of your organization is not available right now, e.g., because its network drive cannot be reached. Until it is, the assistant plans the slides without it." + +-- Use no picture library +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3221010098"] = "Use no picture library" + +-- These pictures could not be placed, because PowerPoint cannot show their format or they cannot be read: {0} +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3302350746"] = "These pictures could not be placed, because PowerPoint cannot show their format or they cannot be read: {0}" + +-- Layouts for kinds of slides +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3306428265"] = "Layouts for kinds of slides" + +-- The folder does not exist. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3306802135"] = "The folder does not exist." + +-- Advanced Options +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3393521529"] = "Advanced Options" + +-- Choose a PowerPoint presentation or template (.pptx, .potx) whose layouts the slides should use. The LLM then plans every slide for one of these layouts, and you can create a PowerPoint file (.pptx) in the design of your template, which other programs such as LibreOffice Impress open as well. OpenDocument presentations (.odp, .otp) cannot serve as a template yet. Without a template, you get an outline, which you can copy or export. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3447420430"] = "Choose a PowerPoint presentation or template (.pptx, .potx) whose layouts the slides should use. The LLM then plans every slide for one of these layouts, and you can create a PowerPoint file (.pptx) in the design of your template, which other programs such as LibreOffice Impress open as well. OpenDocument presentations (.odp, .otp) cannot serve as a template yet. Without a template, you get an outline, which you can copy or export." + -- Please specify the audience for the planned presentation. This will help the LLM to create a presentation that fits your needs. You can specify the audience profile, the age group, organizational level, and the expertise. You don't have to specify all of these parameters, for example you might only want to specify the audience profile and leave the other parameters at their default values. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3465256803"] = "Please specify the audience for the planned presentation. This will help the LLM to create a presentation that fits your needs. You can specify the audience profile, the age group, organizational level, and the expertise. You don't have to specify all of these parameters, for example you might only want to specify the audience profile and leave the other parameters at their default values." --- (Optional) Specify aspects that the LLM should consider when creating the slides. For example, the use of emojis or specific topics that should be highlighted. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3476149293"] = "(Optional) Specify aspects that the LLM should consider when creating the slides. For example, the use of emojis or specific topics that should be highlighted." +-- PowerPoint template +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3472250354"] = "PowerPoint template" -- Audience UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3506118019"] = "Audience" +-- Please plan the slides first. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3528182735"] = "Please plan the slides first." + -- Time specification (minutes) UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3539067305"] = "Time specification (minutes)" @@ -2593,30 +2740,120 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3649769130 -- Attach documents UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3666048746"] = "Attach documents" --- Number of bullet points -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3796347042"] = "Number of bullet points" +-- Select a PowerPoint template +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3690748035"] = "Select a PowerPoint template" + +-- For each planning, the LLM gets a random {0} of them. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T382757370"] = "For each planning, the LLM gets a random {0} of them." -- Custom target language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3848935911"] = "Custom target language" +-- Create PowerPoint file +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3852632268"] = "Create PowerPoint file" + +-- The template file does not exist. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3882045083"] = "The template file does not exist." + -- Presentation title UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3893271035"] = "Presentation title" --- {0} - Slide Builder Session -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3922788056"] = "{0} - Slide Builder Session" +-- Color variant +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T3930823017"] = "Color variant" --- Please specify the extent of the planned presentation. This can be the number of slides, the number of bullet points per slide, or the time specification for the presentation. This will help the LLM to create a presentation that fits your needs. Leave the default values if you don't have specific requirements regarding the extent of the presentation. You might only want to specify one of these parameters, for example the time specification, and leave the others at their default values. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T4131419342"] = "Please specify the extent of the planned presentation. This can be the number of slides, the number of bullet points per slide, or the time specification for the presentation. This will help the LLM to create a presentation that fits your needs. Leave the default values if you don't have specific requirements regarding the extent of the presentation. You might only want to specify one of these parameters, for example the time specification, and leave the others at their default values." +-- The result of your previous Slide Assistant session. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T4180398467"] = "The result of your previous Slide Assistant session." + +-- The template has changed since the slides were planned. Please create the slides again. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T4193152417"] = "The template has changed since the slides were planned. Please create the slides again." + +-- The LLM is writing slide {0}... +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T4246305612"] = "The LLM is writing slide {0}..." -- Audience expertise UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T4279519256"] = "Audience expertise" +-- (Optional) Footer +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T531280033"] = "(Optional) Footer" + +-- The LLM is fitting the slides to the layouts... +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T583856064"] = "The LLM is fitting the slides to the layouts..." + +-- The PowerPoint file was created. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T590228290"] = "The PowerPoint file was created." + -- Title UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T617902505"] = "Title" +-- {0} - Slide Assistant Session +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T645201099"] = "{0} - Slide Assistant Session" + -- Please provide a custom language. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T656744944"] = "Please provide a custom language." +-- Creates a PowerPoint file in the design of your template. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T682162982"] = "Creates a PowerPoint file in the design of your template." + +-- {0} pictures, {1} of them icons. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T72691638"] = "{0} pictures, {1} of them icons." + +-- Select a picture library +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T801027183"] = "Select a picture library" + +-- Please specify the extent of the planned presentation. This can be the number of slides, the maximum number of bullet points per slide, or the time specification for the presentation. This will help the LLM to create a presentation that fits your needs. Leave the default values if you don't have specific requirements regarding the extent of the presentation. You might only want to specify one of these parameters, for example the time specification, and leave the others at their default values. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T805699788"] = "Please specify the extent of the planned presentation. This can be the number of slides, the maximum number of bullet points per slide, or the time specification for the presentation. This will help the LLM to create a presentation that fits your needs. Leave the default values if you don't have specific requirements regarding the extent of the presentation. You might only want to specify one of these parameters, for example the time specification, and leave the others at their default values." + +-- The LLM cannot edit this slide, because its layout has no placeholders for content. Please keep it unchanged or leave it out. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T82751648"] = "The LLM cannot edit this slide, because its layout has no placeholders for content. Please keep it unchanged or leave it out." + +-- This assistant helps you create clear, structured slides from long texts or documents. Enter a presentation title and provide the content either as text or with one or more documents. Important aspects allow you to add instructions to the LLM regarding output or formatting. Set the number of slides either directly or based on your desired presentation duration. You can also limit the number of bullet points per slide. If the default value of 0 is not changed, the LLM will independently determine how many slides or bullet points to generate. The output can be flexibly generated in various languages and tailored to a specific audience. When you choose a PowerPoint template, the slides use its layouts, and you can create a PowerPoint file in its design from the result. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T854215805"] = "This assistant helps you create clear, structured slides from long texts or documents. Enter a presentation title and provide the content either as text or with one or more documents. Important aspects allow you to add instructions to the LLM regarding output or formatting. Set the number of slides either directly or based on your desired presentation duration. You can also limit the number of bullet points per slide. If the default value of 0 is not changed, the LLM will independently determine how many slides or bullet points to generate. The output can be flexibly generated in various languages and tailored to a specific audience. When you choose a PowerPoint template, the slides use its layouts, and you can create a PowerPoint file in its design from the result." + +-- The template cannot be read. Please choose a PowerPoint presentation or template (.pptx, .potx). +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T928047772"] = "The template cannot be read. Please choose a PowerPoint presentation or template (.pptx, .potx)." + +-- The slides were planned for another template. Please plan them again. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T94807224"] = "The slides were planned for another template. Please plan them again." + +-- (Optional) Picture library +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T963454719"] = "(Optional) Picture library" + +-- The PowerPoint file could not be created. Please check that the template can be read and that the target file is not open in another program. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANT::T966839368"] = "The PowerPoint file could not be created. Please check that the template can be read and that the target file is not open in another program." + +-- Choose which layout of your template the LLM uses for certain kinds of slides. The lists offer the layouts with room for content. Where you have no preference, the LLM decides by the names and placeholders of the layouts. A choice says which layout such a slide uses, not whether the presentation has one: whether there is, e.g., an agenda, follows from your content and your important aspects. Only for the framing slides, e.g., the table of contents or the imprint, does a choice also add such a slide; their help says so. Each chapter becomes a section in PowerPoint, which the slide sorter shows as an outline. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANTTEXTS::T2111748232"] = "Choose which layout of your template the LLM uses for certain kinds of slides. The lists offer the layouts with room for content. Where you have no preference, the LLM decides by the names and placeholders of the layouts. A choice says which layout such a slide uses, not whether the presentation has one: whether there is, e.g., an agenda, follows from your content and your important aspects. Only for the framing slides, e.g., the table of contents or the imprint, does a choice also add such a slide; their help says so. Each chapter becomes a section in PowerPoint, which the slide sorter shows as an outline." + +-- When a new slide has no picture for a picture placeholder of its layout, it leaves the placeholder out, as every other placeholder without content. Keep these placeholders to insert pictures of your own later: PowerPoint shows them while you edit and hides them in the slide show. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANTTEXTS::T2143216044"] = "When a new slide has no picture for a picture placeholder of its layout, it leaves the placeholder out, as every other placeholder without content. Keep these placeholders to insert pictures of your own later: PowerPoint shows them while you edit and hides them in the slide show." + +-- Choose a folder with pictures and icons, e.g., the picture library of your organization. The LLM reads only their names, never the pictures themselves, and uses a picture where its name fits a slide; it does not have to use any. So clear names such as “rocket-launch.jpg” help. Only PNG and JPEG pictures count: many icons come as SVG, which the assistant leaves out. A picture whose name, or the name of one of its folders, the chosen folder included, starts with “icon” is an icon. An icon may appear on several slides and goes into picture placeholders of any size, except those which cover half the slide or more, as a background picture does. From a folder with more than {0} pictures, the LLM gets a random {0} of them for each planning. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANTTEXTS::T4122949257"] = "Choose a folder with pictures and icons, e.g., the picture library of your organization. The LLM reads only their names, never the pictures themselves, and uses a picture where its name fits a slide; it does not have to use any. So clear names such as “rocket-launch.jpg” help. Only PNG and JPEG pictures count: many icons come as SVG, which the assistant leaves out. A picture whose name, or the name of one of its folders, the chosen folder included, starts with “icon” is an icon. An icon may appear on several slides and goes into picture placeholders of any size, except those which cover half the slide or more, as a background picture does. From a folder with more than {0} pictures, the LLM gets a random {0} of them for each planning." + +-- Besides its layouts, your file contains slides, e.g., samples of the template or the slides of an earlier presentation. By default, the presentation leaves them out. Choose for each slide whether the presentation keeps it unchanged or lets the LLM edit its content. The LLM uses each of these slides exactly once, keeps them in their order, and may add new slides before, between, and after them. It never copies a slide as a pattern: new slides always come from the layouts of your template. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANTTEXTS::T554384175"] = "Besides its layouts, your file contains slides, e.g., samples of the template or the slides of an earlier presentation. By default, the presentation leaves them out. Choose for each slide whether the presentation keeps it unchanged or lets the LLM edit its content. The LLM uses each of these slides exactly once, keeps them in their order, and may add new slides before, between, and after them. It never copies a slide as a pattern: new slides always come from the layouts of your template." + +-- The LLM does not see what your layouts look like. It knows only their names from the slide master of your template, where their placeholders sit, and how much text fits into them. Clear names such as “Chapter” or “Content with picture” therefore help it choose well; in PowerPoint, you rename a layout in the slide master view. Logo, background, and footer come with the layout. Layouts which differ only in their color count as one, and the color applies to the whole presentation. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::SLIDEASSISTANTTEXTS::T672635431"] = "The LLM does not see what your layouts look like. It knows only their names from the slide master of your template, where their placeholders sit, and how much text fits into them. Clear names such as “Chapter” or “Content with picture” therefore help it choose well; in PowerPoint, you rename a layout in the slide master view. Logo, background, and footer come with the layout. Layouts which differ only in their color count as one, and the color applies to the whole presentation." + +-- Slide {0}: {1} +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::TEMPLATESLIDEEXTENSIONS::T3684030069"] = "Slide {0}: {1}" + +-- Slide {0} +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::TEMPLATESLIDEEXTENSIONS::T3921179924"] = "Slide {0}" + +-- hidden +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::TEMPLATESLIDEEXTENSIONS::T4128829753"] = "hidden" + +-- Let the LLM edit it +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::TEMPLATESLIDEUSEEXTENSIONS::T2549215047"] = "Let the LLM edit it" + +-- Leave out +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::TEMPLATESLIDEUSEEXTENSIONS::T2769076356"] = "Leave out" + +-- Keep unchanged +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SLIDEBUILDER::TEMPLATESLIDEUSEEXTENSIONS::T2931681185"] = "Keep unchanged" + -- Find synonyms for the following word or phrase: UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::SYNONYM::ASSISTANTSYNONYMS::T1793532807"] = "Find synonyms for the following word or phrase:" @@ -3772,9 +4009,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIDENCEINFO::T847071819"] = "Shows and -- This feature is managed by your organization and has therefore been disabled. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONBASE::T1416426626"] = "This feature is managed by your organization and has therefore been disabled." +-- You can also drag & drop the folder here. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONDIRECTORY::T350096725"] = "You can also drag & drop the folder here." + -- Choose Directory UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONDIRECTORY::T4256489763"] = "Choose Directory" +-- You can also drag & drop the file here. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONFILE::T1984243691"] = "You can also drag & drop the file here." + -- Choose File UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONFILE::T4285779702"] = "Choose File" @@ -4840,33 +5083,18 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SECRETINPUTFIELD::T1273315904"] = "Hide c -- Show content UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SECRETINPUTFIELD::T2891011873"] = "Show content" --- The dropped folder could not be accessed. Please choose it with the folder chooser instead. -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SELECTDIRECTORY::T1153417816"] = "The dropped folder could not be accessed. Please choose it with the folder chooser instead." - --- Please drop a folder, not a file. -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SELECTDIRECTORY::T3289690493"] = "Please drop a folder, not a file." - -- You can also drag & drop the folder here. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SELECTDIRECTORY::T350096725"] = "You can also drag & drop the folder here." -- Choose Directory UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SELECTDIRECTORY::T4256489763"] = "Choose Directory" --- Please drop a file, not a folder. -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SELECTFILE::T1472251601"] = "Please drop a file, not a folder." - -- You can also drag & drop the file here. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SELECTFILE::T1984243691"] = "You can also drag & drop the file here." -- Choose File UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SELECTFILE::T4285779702"] = "Choose File" --- Please drop a file with a supported file type. -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SELECTFILE::T930441004"] = "Please drop a file with a supported file type." - --- The dropped file could not be accessed. Please choose it with the file chooser instead. -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SELECTFILE::T984660028"] = "The dropped file could not be accessed. Please choose it with the file chooser instead." - -- External Assistants rated below this audit level are treated as insufficiently reviewed. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAGENTASSISTANTAUDIT::T1162151451"] = "External Assistants rated below this audit level are treated as insufficiently reviewed." @@ -9478,27 +9706,51 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGREWRITE::T553954963" -- Preselect the audience expertise UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1017131030"] = "Preselect the audience expertise" --- When enabled, you can preselect slide builder options. This is might be useful when you prefer a specific language or LLM model. -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1393378753"] = "When enabled, you can preselect slide builder options. This is might be useful when you prefer a specific language or LLM model." +-- Preselect another occasion +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1150085788"] = "Preselect another occasion" + +-- Slides of the template +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1178900119"] = "Slides of the template" + +-- Preselect the occasion +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1451545352"] = "Preselect the occasion" -- Preselect aspects for the LLM to focus on when generating slides, such as bullet points or specific topics to emphasize. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1528169602"] = "Preselect aspects for the LLM to focus on when generating slides, such as bullet points or specific topics to emphasize." --- Slide Planner Assistant options are preselected -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1549358578"] = "Slide Planner Assistant options are preselected" - --- No Slide Planner Assistant options are preselected -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1694374279"] = "No Slide Planner Assistant options are preselected" +-- Preselect a PowerPoint template +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1745818752"] = "Preselect a PowerPoint template" -- Choose whether the assistant should use the app default profile, no profile, or a specific profile. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1766361623"] = "Choose whether the assistant should use the app default profile, no profile, or a specific profile." +-- Shown on every slide whose layout has a footer, e.g., your name, organization, and date. Leave it empty for no footer. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1770252925"] = "Shown on every slide whose layout has a footer, e.g., your name, organization, and date. Leave it empty for no footer." + +-- Preselect what the assistant starts with for each presentation: the aspects to emphasize, the language, the audience, and the occasion. You can still change them in the assistant. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1883749129"] = "Preselect what the assistant starts with for each presentation: the aspects to emphasize, the language, the audience, and the occasion. You can still change them in the assistant." + +-- Preselect which LLM plans the slides and which profile it gets. A profile can, e.g., name your organization, which the LLM may use for the imprint. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1886202233"] = "Preselect which LLM plans the slides and which profile it gets. A profile can, e.g., name your organization, which the LLM may use for the imprint." + +-- Preselect the footer text +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1952334375"] = "Preselect the footer text" + -- Preselect the audience organizational level UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2014662371"] = "Preselect the audience organizational level" +-- AI selection +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2105832301"] = "AI selection" + -- Which audience organizational level should be preselected? UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T216511105"] = "Which audience organizational level should be preselected?" +-- Preselect Slide Assistant options? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T227645894"] = "Preselect Slide Assistant options?" + +-- The preselected template contains no slides besides its layouts. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2310759788"] = "The preselected template contains no slides besides its layouts." + -- Preselect a profile UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2322771068"] = "Preselect a profile" @@ -9508,36 +9760,96 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T23451 -- Preselect another language UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2382415529"] = "Preselect another language" +-- Content and audience +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2399412443"] = "Content and audience" + +-- Preselect a picture library +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2462036412"] = "Preselect a picture library" + +-- Which occasion of the presentation should be preselected? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T253212936"] = "Which occasion of the presentation should be preselected?" + -- Preselect the language UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2571465005"] = "Preselect the language" -- Preselect the audience age group UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2645589441"] = "Preselect the audience age group" --- Assistant: Slide Planner Assistant Options -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3226042276"] = "Assistant: Slide Planner Assistant Options" +-- The slides use the layouts of this PowerPoint presentation or template (.pptx, .potx), and you can create a PowerPoint file (.pptx) from the result. OpenDocument presentations (.odp, .otp) cannot serve as a template yet. Leave it empty to plan an outline only. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2931578847"] = "The slides use the layouts of this PowerPoint presentation or template (.pptx, .potx), and you can create a PowerPoint file (.pptx) from the result. OpenDocument presentations (.odp, .otp) cannot serve as a template yet. Leave it empty to plan an outline only." + +-- Preselect a readable template above to choose its layouts for kinds of slides. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3212897766"] = "Preselect a readable template above to choose its layouts for kinds of slides." + +-- Preselect the maximum number of bullet points per slide +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3214836964"] = "Preselect the maximum number of bullet points per slide" + +-- Assistant: Slide Assistant Options +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3215549988"] = "Assistant: Slide Assistant Options" -- Which audience expertise should be preselected? UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3228597992"] = "Which audience expertise should be preselected?" --- Preselect Slide Planner Assistant options? -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T339924858"] = "Preselect Slide Planner Assistant options?" +-- Layouts for kinds of slides +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3306428265"] = "Layouts for kinds of slides" + +-- Preselect keeping empty picture placeholders? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3344629637"] = "Preselect keeping empty picture placeholders?" -- Close UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3448155331"] = "Close" +-- PowerPoint template +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3472250354"] = "PowerPoint template" + +-- Empty picture placeholders are left out +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3506495573"] = "Empty picture placeholders are left out" + +-- Visual elements +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T366689306"] = "Visual elements" + +-- Select a PowerPoint template +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3690748035"] = "Select a PowerPoint template" + -- Preselect important aspects UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3705987833"] = "Preselect important aspects" +-- Empty picture placeholders are kept +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3852335360"] = "Empty picture placeholders are kept" + +-- No maximum +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3915183720"] = "No maximum" + +-- No Slide Assistant options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T4214398691"] = "No Slide Assistant options are preselected" + +-- When enabled, you can preselect options of the Slide Assistant. This might be useful when you prefer a specific language or LLM model. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T522980576"] = "When enabled, you can preselect options of the Slide Assistant. This might be useful when you prefer a specific language or LLM model." + +-- The LLM may choose pictures and icons for the slides from this folder. Leave it empty for no picture library. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T53668203"] = "The LLM may choose pictures and icons for the slides from this folder. Leave it empty for no picture library." + +-- Preselect a readable template above to choose what the presentation does with its slides. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T799025846"] = "Preselect a readable template above to choose what the presentation does with its slides." + +-- Select a picture library +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T801027183"] = "Select a picture library" + -- Preselect the audience profile UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T861397972"] = "Preselect the audience profile" +-- Slide Assistant options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T93124146"] = "Slide Assistant options are preselected" + -- Which audience age group should be preselected? UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T956845877"] = "Which audience age group should be preselected?" -- Which audience profile should be preselected? UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T973572510"] = "Which audience profile should be preselected?" +-- A slide holds at most this many bullet points, in all of its text slots together. Match it to the room for text in the layouts of your template. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T995644230"] = "A slide holds at most this many bullet points, in all of its text slots together. Match it to the room for text in the layouts of your template." + -- When enabled, you can preselect synonym options. This is might be useful when you prefer a specific language or LLM model. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSYNONYMS::T183953912"] = "When enabled, you can preselect synonym options. This is might be useful when you prefer a specific language or LLM model." @@ -10213,6 +10525,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1728590051"] = "Analyze a text or -- Prompt Optimizer UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1777666968"] = "Prompt Optimizer" +-- Slide Assistant +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1883918574"] = "Slide Assistant" + -- Text Summarizer UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1907192403"] = "Text Summarizer" @@ -10255,9 +10570,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2830810750"] = "AI Studio Develop -- Generate a job posting for a given job description. UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2831103254"] = "Generate a job posting for a given job description." --- Slide Planner Assistant -UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2924755246"] = "Slide Planner Assistant" - -- Installed Assistants UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T295232966"] = "Installed Assistants" @@ -10270,9 +10582,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T3026443472"] = "E-Mail" -- The automatic security audit for the assistant plugin '{0}' failed. Please run it manually from the plugins page. UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T311775455"] = "The automatic security audit for the assistant plugin '{0}' failed. Please run it manually from the plugins page." --- Develop slide content based on a given topic and content. -UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T311912219"] = "Develop slide content based on a given topic and content." - -- Translate AI Studio text content into other languages UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T3181803840"] = "Translate AI Studio text content into other languages" @@ -10336,6 +10645,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T892147062"] = "View and filter AI -- Localization UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T897888480"] = "Localization" +-- Turn texts and documents into slides, also as a PowerPoint file in the design of your template. +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T943132958"] = "Turn texts and documents into slides, also as a PowerPoint file in the design of your template." + -- Hide search UI_TEXT_CONTENT["AISTUDIO::PAGES::CHAT::T1281128983"] = "Hide search" @@ -11362,9 +11674,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::SUPPORTERS::T1714878838"] = "Thank you, Peer, -- Individual Contributors UI_TEXT_CONTENT["AISTUDIO::PAGES::SUPPORTERS::T1874835680"] = "Individual Contributors" --- Thank you, Sabrina, for bringing file attachments to the chat, the Slide Planner Assistant, and the protection against prompt injection. -UI_TEXT_CONTENT["AISTUDIO::PAGES::SUPPORTERS::T2053817136"] = "Thank you, Sabrina, for bringing file attachments to the chat, the Slide Planner Assistant, and the protection against prompt injection." - -- The first 10 supporters who make a one-time contribution: UI_TEXT_CONTENT["AISTUDIO::PAGES::SUPPORTERS::T2410456125"] = "The first 10 supporters who make a one-time contribution:" @@ -11380,6 +11689,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::SUPPORTERS::T2640760894"] = "Become one of our -- Supporters UI_TEXT_CONTENT["AISTUDIO::PAGES::SUPPORTERS::T2929332068"] = "Supporters" +-- Thank you, Sabrina, for bringing file attachments to the chat, the Slide Assistant, and the protection against prompt injection. +UI_TEXT_CONTENT["AISTUDIO::PAGES::SUPPORTERS::T2978040576"] = "Thank you, Sabrina, for bringing file attachments to the chat, the Slide Assistant, and the protection against prompt injection." + -- Content Contributors UI_TEXT_CONTENT["AISTUDIO::PAGES::SUPPORTERS::T3060804484"] = "Content Contributors" @@ -12181,6 +12493,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T1546040625"] = "My Task -- Grammar & Spelling Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T166453786"] = "Grammar & Spelling Assistant" +-- Slide Assistant +UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T1883918574"] = "Slide Assistant" + -- Legal Check Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T1886447798"] = "Legal Check Assistant" @@ -12202,9 +12517,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T277804139"] = "Visual B -- Synonym Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2921123194"] = "Synonym Assistant" --- Slide Planner Assistant -UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2924755246"] = "Slide Planner Assistant" - -- Assistant Builder UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T3303547904"] = "Assistant Builder" @@ -12457,6 +12769,21 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATASOURCEREPAIR::T4175865785"] = "Repair Data -- The index of the data source '{0}' cannot be read anymore. Repairing it means building the index from scratch: everything indexed so far is thrown away, and every document of this data source is sent to your embedding provider once more. With a cloud provider, this costs money, and with a large data source it takes a while. Do you want to repair this data source now? UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATASOURCEREPAIR::T857336889"] = "The index of the data source '{0}' cannot be read anymore. Repairing it means building the index from scratch: everything indexed so far is thrown away, and every document of this data source is sent to your embedding provider once more. With a cloud provider, this costs money, and with a large data source it takes a while. Do you want to repair this data source now?" +-- Please drop a file, not a folder. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::DROPPEDFILE::T1472251601"] = "Please drop a file, not a folder." + +-- Please drop a file with a supported file type. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::DROPPEDFILE::T930441004"] = "Please drop a file with a supported file type." + +-- The dropped file could not be accessed. Please choose it with the file chooser instead. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::DROPPEDFILE::T984660028"] = "The dropped file could not be accessed. Please choose it with the file chooser instead." + +-- The dropped folder could not be accessed. Please choose it with the folder chooser instead. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::DROPPEDFOLDER::T1153417816"] = "The dropped folder could not be accessed. Please choose it with the folder chooser instead." + +-- Please drop a folder, not a file. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::DROPPEDFOLDER::T3289690493"] = "Please drop a folder, not a file." + -- Import Embedding UI_TEXT_CONTENT["AISTUDIO::TOOLS::EMBEDDINGPROVIDERSETUP::T1681763001"] = "Import Embedding" @@ -13540,6 +13867,1020 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINTYPEEXTENSIONS::T237059392 -- Configuration plugin UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINTYPEEXTENSIONS::T3353383632"] = "Configuration plugin" +-- Business and projects +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEAREAEXTENSIONS::T1042553620"] = "Business and projects" + +-- Science and research +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEAREAEXTENSIONS::T1909173573"] = "Science and research" + +-- Structure and framing +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEAREAEXTENSIONS::T2152680157"] = "Structure and framing" + +-- Medicine +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEAREAEXTENSIONS::T2556266301"] = "Medicine" + +-- Law +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEAREAEXTENSIONS::T2984971435"] = "Law" + +-- Other kinds of slides +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEAREAEXTENSIONS::T574173375"] = "Other kinds of slides" + +-- Teaching and workshops +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEAREAEXTENSIONS::T875074265"] = "Teaching and workshops" + +-- General content +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEAREAEXTENSIONS::T897777590"] = "General content" + +-- Layout for partners +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1014233027"] = "Layout for partners" + +-- Which slide layout should a single court ruling use, e.g., with court, date, case number, and headnote? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1020148914"] = "Which slide layout should a single court ruling use, e.g., with court, date, case number, and headnote?" + +-- Which slide layout should a single opportunity use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T103149100"] = "Which slide layout should a single opportunity use, shown prominently?" + +-- Which slide layout should a decision use which the audience is asked to make? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1040281888"] = "Which slide layout should a decision use which the audience is asked to make?" + +-- Layout for breaks +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1064102044"] = "Layout for breaks" + +-- Layout for stories +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1070686897"] = "Layout for stories" + +-- Which slide layout should a narrative use, which frames, e.g., a project? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1077820264"] = "Which slide layout should a narrative use, which frames, e.g., a project?" + +-- Layout for several problems +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1094127856"] = "Layout for several problems" + +-- Which slide layout should a chain of arguments use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1104132271"] = "Which slide layout should a chain of arguments use?" + +-- Layout for timelines +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1115997848"] = "Layout for timelines" + +-- Which slide layout should the contribution of the work use, i.e., what is new? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1117697696"] = "Which slide layout should the contribution of the work use, i.e., what is new?" + +-- Layout for “Any questions?” +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1129259891"] = "Layout for “Any questions?”" + +-- Which slide layout should several assumptions use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1141663885"] = "Which slide layout should several assumptions use, shown together?" + +-- Which slide layout should several delimitations use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1152239577"] = "Which slide layout should several delimitations use, shown together?" + +-- Layout for the team +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T115619112"] = "Layout for the team" + +-- Layout for acknowledgements +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1165298089"] = "Layout for acknowledgements" + +-- Layout for the summary +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1217016695"] = "Layout for the summary" + +-- Which slide layout should slides with little content use, e.g., a short statement? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T122211757"] = "Which slide layout should slides with little content use, e.g., a short statement?" + +-- Layout for one use case +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1231694521"] = "Layout for one use case" + +-- Which slide layout should several examples use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T123810252"] = "Which slide layout should several examples use, shown together?" + +-- Which slide layout should open each chapter? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1240241139"] = "Which slide layout should open each chapter?" + +-- Layout for the state of research +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1281296692"] = "Layout for the state of research" + +-- Which slide layout should a look back on where we come from use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1308711435"] = "Which slide layout should a look back on where we come from use?" + +-- Which slide layout should a summary or a conclusion use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1335800860"] = "Which slide layout should a summary or a conclusion use?" + +-- Layout for the study design +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1339678504"] = "Layout for the study design" + +-- Which slide layout should a single result use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1353098126"] = "Which slide layout should a single result use, shown prominently?" + +-- Which slide layout should the definition of a single term use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1354815318"] = "Which slide layout should the definition of a single term use?" + +-- Layout for one contract clause +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1364307455"] = "Layout for one contract clause" + +-- Layout for one goal +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1366104671"] = "Layout for one goal" + +-- Layout for SWOT analyses +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T136706369"] = "Layout for SWOT analyses" + +-- Layout for guideline recommendations +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1403379894"] = "Layout for guideline recommendations" + +-- Which slide layout should the medical history of a patient use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1410100783"] = "Which slide layout should the medical history of a patient use?" + +-- Which slide layout should clinical findings use, e.g., of a physical examination? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T142386677"] = "Which slide layout should clinical findings use, e.g., of a physical examination?" + +-- Layout for one scenario +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1428654470"] = "Layout for one scenario" + +-- Layout for one hypothesis +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1445572710"] = "Layout for one hypothesis" + +-- Layout for an overview of KPIs +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1447134482"] = "Layout for an overview of KPIs" + +-- Layout for forecasts +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1487244874"] = "Layout for forecasts" + +-- Layout for one assumption +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1503180167"] = "Layout for one assumption" + +-- Which slide layout should conflicts of interest and disclaimers use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1507945603"] = "Which slide layout should conflicts of interest and disclaimers use?" + +-- Which slide layout should pros and cons use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1514618392"] = "Which slide layout should pros and cons use?" + +-- Which slide layout should a call to action use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1517426306"] = "Which slide layout should a call to action use?" + +-- Which slide layout should the status of a project use, e.g., as a traffic light? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1534894088"] = "Which slide layout should the status of a project use, e.g., as a traffic light?" + +-- Layout for the title slide +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1535308880"] = "Layout for the title slide" + +-- Which slide layout should the proof of a theorem use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1568120253"] = "Which slide layout should the proof of a theorem use?" + +-- Which slide layout should the context or the starting point use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T158061098"] = "Which slide layout should the context or the starting point use?" + +-- Layout for pros and cons +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1587972966"] = "Layout for pros and cons" + +-- Layout for several delimitations +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1610652216"] = "Layout for several delimitations" + +-- Which slide layout should timelines use, e.g., the course of a project? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1625275711"] = "Which slide layout should timelines use, e.g., the course of a project?" + +-- Which slide layout should several court rulings use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1627282810"] = "Which slide layout should several court rulings use, shown together?" + +-- Which slide layout should a single quote use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1633664977"] = "Which slide layout should a single quote use, shown prominently?" + +-- Which slide layout should a single passage of a legal commentary use, e.g., of an annotated code, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1644569586"] = "Which slide layout should a single passage of a legal commentary use, e.g., of an annotated code, shown prominently?" + +-- Layout for several definitions +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1645055642"] = "Layout for several definitions" + +-- Which slide layout should several opportunities use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1671430802"] = "Which slide layout should several opportunities use, shown together?" + +-- Layout for the experimental setup +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1678480418"] = "Layout for the experimental setup" + +-- Layout for introducing several speakers +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1680921944"] = "Layout for introducing several speakers" + +-- Which slide layout should the presentation of a patient case use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1685663750"] = "Which slide layout should the presentation of a patient case use?" + +-- Which slide layout should imaging use, e.g., an X-ray, CT, or MRI with its findings? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1695270380"] = "Which slide layout should imaging use, e.g., an X-ray, CT, or MRI with its findings?" + +-- Which slide layout should the study population use, e.g., with inclusion and exclusion criteria? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1710911895"] = "Which slide layout should the study population use, e.g., with inclusion and exclusion criteria?" + +-- Which slide layout should the state of research use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1747258262"] = "Which slide layout should the state of research use?" + +-- Layout for one user story +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1754624674"] = "Layout for one user story" + +-- Layout for one piece of evidence +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1761362584"] = "Layout for one piece of evidence" + +-- Layout for one learning objective +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1771256293"] = "Layout for one learning objective" + +-- Which slide layout should the introduction of a single speaker use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1776932064"] = "Which slide layout should the introduction of a single speaker use?" + +-- Which slide layout should a key message use, which states the one thing to remember? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1787619917"] = "Which slide layout should a key message use, which states the one thing to remember?" + +-- Which slide layout should a theorem use, e.g., in mathematics? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1802886934"] = "Which slide layout should a theorem use, e.g., in mathematics?" + +-- Layout for the project status +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1807351352"] = "Layout for the project status" + +-- Layout for the table of contents +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1823365046"] = "Layout for the table of contents" + +-- Layout for several pictures +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1828342463"] = "Layout for several pictures" + +-- Which slide layout should comparisons use, e.g., before and after, or two options? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1840246589"] = "Which slide layout should comparisons use, e.g., before and after, or two options?" + +-- Which slide layout should the ground rules for working together use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1847072681"] = "Which slide layout should the ground rules for working together use?" + +-- Which slide layout should organizational notes use, e.g., on rooms or Wi-Fi? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1857170293"] = "Which slide layout should organizational notes use, e.g., on rooms or Wi-Fi?" + +-- Layout for lab values +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1875667171"] = "Layout for lab values" + +-- Layout for several research questions +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1877198900"] = "Layout for several research questions" + +-- Layout for several learning objectives +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T191598066"] = "Layout for several learning objectives" + +-- Which slide layout should an exercise use, with its task, time frame, and expected result? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1929274048"] = "Which slide layout should an exercise use, with its task, time frame, and expected result?" + +-- Layout for an overview of work packages +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1950946185"] = "Layout for an overview of work packages" + +-- Which slide layout should medication use, e.g., with agent, dose, and duration? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1955333344"] = "Which slide layout should medication use, e.g., with agent, dose, and duration?" + +-- Which slide layout should acceptance criteria use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1959540330"] = "Which slide layout should acceptance criteria use?" + +-- Which slide layout should a slide use which presents a team? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1979984215"] = "Which slide layout should a slide use which presents a team?" + +-- Which slide layout should a single scenario use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T1982380825"] = "Which slide layout should a single scenario use, shown prominently?" + +-- Which slide layout should several formulas use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2030308484"] = "Which slide layout should several formulas use, shown together?" + +-- Which slide layout should the methodology use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T203822370"] = "Which slide layout should the methodology use?" + +-- Which slide layout should several quotes use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2041878078"] = "Which slide layout should several quotes use, shown together?" + +-- Which slide layout should a note on the funding of the work use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2077700183"] = "Which slide layout should a note on the funding of the work use?" + +-- Which slide layout should the introduction of several speakers use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2094194578"] = "Which slide layout should the introduction of several speakers use?" + +-- Layout for step-by-step explanations +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2111999519"] = "Layout for step-by-step explanations" + +-- Layout for one milestone +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2114685310"] = "Layout for one milestone" + +-- Which slide layout should a slide with a table use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2147948257"] = "Which slide layout should a slide with a table use?" + +-- Layout for to-dos +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2149537898"] = "Layout for to-dos" + +-- Layout for one quote +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2150775408"] = "Layout for one quote" + +-- Which slide layout should a prompt for a discussion use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2166518417"] = "Which slide layout should a prompt for a discussion use?" + +-- Which slide layout should a single goal use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2178279832"] = "Which slide layout should a single goal use, shown prominently?" + +-- Which slide layout should several pieces of evidence use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2198315510"] = "Which slide layout should several pieces of evidence use, shown together?" + +-- Default layout for content +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2216550238"] = "Default layout for content" + +-- Layout for several goals +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2217393844"] = "Layout for several goals" + +-- Which slide layout should an overview of several milestones use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2251715184"] = "Which slide layout should an overview of several milestones use?" + +-- Layout for several pieces of evidence +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2257157973"] = "Layout for several pieces of evidence" + +-- Layout for the contribution +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2263473163"] = "Layout for the contribution" + +-- Which slide layout should several reasons use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2280792678"] = "Which slide layout should several reasons use, shown together?" + +-- Layout for the positions of the parties +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2297947419"] = "Layout for the positions of the parties" + +-- Layout for polls +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2299527458"] = "Layout for polls" + +-- Which slide layout should the experimental setup use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2300173724"] = "Which slide layout should the experimental setup use?" + +-- Layout for legal consequences +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2323155405"] = "Layout for legal consequences" + +-- Layout for one reason +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2324022664"] = "Layout for one reason" + +-- Which slide layout should a single user story use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2329609477"] = "Which slide layout should a single user story use, shown prominently?" + +-- Layout for the context +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T233353792"] = "Layout for the context" + +-- Layout for expectations +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2371205947"] = "Layout for expectations" + +-- Which slide layout should the endpoints of a study use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2381313738"] = "Which slide layout should the endpoints of a study use?" + +-- Layout for one KPI +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2388056074"] = "Layout for one KPI" + +-- Which slide layout should several goals use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2417807229"] = "Which slide layout should several goals use, shown together?" + +-- Which slide layout should the therapy or the treatment plan use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2420939131"] = "Which slide layout should the therapy or the treatment plan use?" + +-- Layout for one opportunity +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2428145985"] = "Layout for one opportunity" + +-- Layout for interim summaries +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2438421040"] = "Layout for interim summaries" + +-- Layout for the methodology +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2451437972"] = "Layout for the methodology" + +-- Which slide layout should the design of a study use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2454384104"] = "Which slide layout should the design of a study use?" + +-- Layout for endpoints +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2457995550"] = "Layout for endpoints" + +-- Which slide layout should a round use in which the participants introduce themselves? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T246747363"] = "Which slide layout should a round use in which the participants introduce themselves?" + +-- Layout for the imprint +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2479880990"] = "Layout for the imprint" + +-- Layout for several results +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2488831402"] = "Layout for several results" + +-- Which slide layout should the solution of an exercise use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2529501126"] = "Which slide layout should the solution of an exercise use?" + +-- Which slide layout should several hypotheses use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2537315271"] = "Which slide layout should several hypotheses use, shown together?" + +-- Layout for tables +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2540038829"] = "Layout for tables" + +-- Which slide layout should several contract clauses use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2550841501"] = "Which slide layout should several contract clauses use, shown together?" + +-- Layout for chains of arguments +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2559513003"] = "Layout for chains of arguments" + +-- Layout for introducing one speaker +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2568963247"] = "Layout for introducing one speaker" + +-- Which slide layout should the table of contents use, which lists the topics of the presentation? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2570153877"] = "Which slide layout should the table of contents use, which lists the topics of the presentation?" + +-- Which slide layout should reflecting on and recording the results use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2576096519"] = "Which slide layout should reflecting on and recording the results use?" + +-- Layout for theorems +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T259369873"] = "Layout for theorems" + +-- Which slide layout should a single piece of evidence use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2606871105"] = "Which slide layout should a single piece of evidence use, shown prominently?" + +-- Which slide layout should the next steps use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2607482691"] = "Which slide layout should the next steps use?" + +-- Layout for one dependency +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2610479757"] = "Layout for one dependency" + +-- Which slide layout should a SWOT analysis use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2655203380"] = "Which slide layout should a SWOT analysis use?" + +-- Which slide layout should a poll, a vote, or a knowledge check use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2694466351"] = "Which slide layout should a poll, a vote, or a knowledge check use?" + +-- Which slide layout should collecting the expectations of the participants use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2697820950"] = "Which slide layout should collecting the expectations of the participants use?" + +-- No preference (the LLM decides) +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2736980667"] = "No preference (the LLM decides)" + +-- Layout for several contract clauses +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2738284820"] = "Layout for several contract clauses" + +-- Which slide layout should a single note or remark use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2752575508"] = "Which slide layout should a single note or remark use, shown prominently?" + +-- Layout for one work package +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2760560305"] = "Layout for one work package" + +-- Which slide layout should a single reason use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2764805851"] = "Which slide layout should a single reason use, shown prominently?" + +-- Which slide layout should a scheme use by which a legal question is examined step by step? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2772805348"] = "Which slide layout should a scheme use by which a legal question is examined step by step?" + +-- Layout for one thesis +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2776067892"] = "Layout for one thesis" + +-- Layout for one commentary +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2787854397"] = "Layout for one commentary" + +-- Layout for deadlines +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2797417629"] = "Layout for deadlines" + +-- Which slide layout should an overview of several work packages use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2799714841"] = "Which slide layout should an overview of several work packages use?" + +-- Which slide layout should several risks use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2809967041"] = "Which slide layout should several risks use, shown together?" + +-- Layout for the therapy +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2814677978"] = "Layout for the therapy" + +-- Which slide layout should several legal questions use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T282499161"] = "Which slide layout should several legal questions use, shown together?" + +-- Layout for several theses +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2832902216"] = "Layout for several theses" + +-- Which slide layout should an interpretation of the results use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2838598093"] = "Which slide layout should an interpretation of the results use?" + +-- Layout for a look back +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2854650733"] = "Layout for a look back" + +-- Layout for the diagnosis +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2872699274"] = "Layout for the diagnosis" + +-- Layout for one example +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2884053898"] = "Layout for one example" + +-- Layout for one delimitation +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2887082539"] = "Layout for one delimitation" + +-- Which slide layout should a single work package use, e.g., in a project report? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2892903451"] = "Which slide layout should a single work package use, e.g., in a project report?" + +-- Layout for examination schemes +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2897211069"] = "Layout for examination schemes" + +-- Layout for clinical findings +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2897905529"] = "Layout for clinical findings" + +-- Layout for one definition +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2901571581"] = "Layout for one definition" + +-- Which slide layout should a single legal question use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2905824880"] = "Which slide layout should a single legal question use, shown prominently?" + +-- Which slide layout should the title slide use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2927095458"] = "Which slide layout should the title slide use?" + +-- Which slide layout should a single research question use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2929392338"] = "Which slide layout should a single research question use, shown prominently?" + +-- Which slide layout should the facts of a legal case use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2937844829"] = "Which slide layout should the facts of a legal case use?" + +-- Layout for decision requests +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2970628172"] = "Layout for decision requests" + +-- Layout for several counterarguments +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2975929628"] = "Layout for several counterarguments" + +-- Layout for questions to the audience +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2984056773"] = "Layout for questions to the audience" + +-- Which slide layout should the positions of the parties use, e.g., of plaintiff and defendant? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2988925171"] = "Which slide layout should the positions of the parties use, e.g., of plaintiff and defendant?" + +-- Layout for several rulings +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2991603466"] = "Layout for several rulings" + +-- Which slide layout should several counterarguments use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T2999624893"] = "Which slide layout should several counterarguments use, shown together?" + +-- Layout for the prognosis +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3007491939"] = "Layout for the prognosis" + +-- Which slide layout should a single use case use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3051456178"] = "Which slide layout should a single use case use, shown prominently?" + +-- Which slide layout should several research questions use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3073525085"] = "Which slide layout should several research questions use, shown together?" + +-- Which slide layout should to-dos use, e.g., with who does them and by when? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3075071043"] = "Which slide layout should to-dos use, e.g., with who does them and by when?" + +-- Which slide layout should a description of the data use, e.g., of a dataset? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3083535091"] = "Which slide layout should a description of the data use, e.g., of a dataset?" + +-- Which slide layout should a single thesis or central claim use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3085355069"] = "Which slide layout should a single thesis or central claim use, shown prominently?" + +-- Which slide layout should a dispute of legal opinions use, e.g., the prevailing and a minority opinion? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3097909957"] = "Which slide layout should a dispute of legal opinions use, e.g., the prevailing and a minority opinion?" + +-- Which slide layout should slides with much content use, e.g., many points or a longer explanation? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3100562182"] = "Which slide layout should slides with much content use, e.g., many points or a longer explanation?" + +-- Layout for roadmaps +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3108446521"] = "Layout for roadmaps" + +-- Layout for the study population +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3133129441"] = "Layout for the study population" + +-- Which slide layout should a single assumption use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3134718364"] = "Which slide layout should a single assumption use, shown prominently?" + +-- Which slide layout should a checklist use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3135542815"] = "Which slide layout should a checklist use?" + +-- Layout for one counterargument +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3176066423"] = "Layout for one counterargument" + +-- Layout for the appendix +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3231339388"] = "Layout for the appendix" + +-- Layout for comparisons +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3236321854"] = "Layout for comparisons" + +-- Which slide layout should a slide use which invites the questions of the audience? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3238718471"] = "Which slide layout should a slide use which invites the questions of the audience?" + +-- Layout for several hypotheses +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3255105074"] = "Layout for several hypotheses" + +-- Layout for checklists +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3259851537"] = "Layout for checklists" + +-- Which slide layout should several scenarios use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3290319304"] = "Which slide layout should several scenarios use, shown together?" + +-- Layout for source code +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3293257190"] = "Layout for source code" + +-- Layout for several opportunities +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3296599085"] = "Layout for several opportunities" + +-- Layout for several assumptions +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3303991020"] = "Layout for several assumptions" + +-- Which slide layout should the prognosis use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3337342787"] = "Which slide layout should the prognosis use?" + +-- Layout for organizational notes +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3337686411"] = "Layout for organizational notes" + +-- Layout for the agenda +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3343931801"] = "Layout for the agenda" + +-- Layout for medication +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3344067059"] = "Layout for medication" + +-- Which slide layout should several notes or remarks use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3344123040"] = "Which slide layout should several notes or remarks use, shown together?" + +-- Which slide layout should the research gap use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3350032786"] = "Which slide layout should the research gap use?" + +-- Which slide layout should open an appendix with backup slides? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3360010463"] = "Which slide layout should open an appendix with backup slides?" + +-- Layout for differential diagnoses +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3376045644"] = "Layout for differential diagnoses" + +-- Which slide layout should a roadmap use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3376320251"] = "Which slide layout should a roadmap use?" + +-- Which slide layout should a single milestone use, e.g., with a report? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T340072348"] = "Which slide layout should a single milestone use, e.g., with a report?" + +-- Which slide layout should a single problem use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3408433614"] = "Which slide layout should a single problem use, shown prominently?" + +-- Which slide layout should resources use, e.g., costs, people, or machines? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3415463181"] = "Which slide layout should resources use, e.g., costs, people, or machines?" + +-- Which slide layout should several problems use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3415830569"] = "Which slide layout should several problems use, shown together?" + +-- Which slide layout should a single recommendation use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3429598200"] = "Which slide layout should a single recommendation use, shown prominently?" + +-- Layout for the narrative +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3431189329"] = "Layout for the narrative" + +-- Choosing a layout also adds such a slide to the presentation. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3455006548"] = "Choosing a layout also adds such a slide to the presentation." + +-- Layout for several use cases +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3455648654"] = "Layout for several use cases" + +-- Which slide layout should a single formula use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3465105335"] = "Which slide layout should a single formula use, shown prominently?" + +-- Layout for funding notes +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3479554352"] = "Layout for funding notes" + +-- Layout for lessons learned +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3481358786"] = "Layout for lessons learned" + +-- Which slide layout should the imprint use, e.g., with authors, organization, and date? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3482700194"] = "Which slide layout should the imprint use, e.g., with authors, organization, and date?" + +-- Which slide layout should a slide use which presents partners, e.g., with their logos? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3497108376"] = "Which slide layout should a slide use which presents partners, e.g., with their logos?" + +-- Which slide layout should several legal provisions use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3497982524"] = "Which slide layout should several legal provisions use, shown together?" + +-- Layout for the course of a disease +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3505206048"] = "Layout for the course of a disease" + +-- Layout for the research gap +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3509558196"] = "Layout for the research gap" + +-- Layout for data +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3512688144"] = "Layout for data" + +-- Which slide layout should the closing slide use, e.g., with thanks and contact details? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3543885893"] = "Which slide layout should the closing slide use, e.g., with thanks and contact details?" + +-- Which slide layout should feedback use, e.g., of customers or users? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3550149798"] = "Which slide layout should feedback use, e.g., of customers or users?" + +-- Layout for proofs +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3550214783"] = "Layout for proofs" + +-- Which slide layout should a single risk use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3556807844"] = "Which slide layout should a single risk use, shown prominently?" + +-- Layout for the executive summary +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3560846545"] = "Layout for the executive summary" + +-- Which slide layout should an interim summary at the end of a chapter use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T356449757"] = "Which slide layout should an interim summary at the end of a chapter use?" + +-- Layout for one research question +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3565608351"] = "Layout for one research question" + +-- Which slide layout should the approval of an ethics committee use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3582048079"] = "Which slide layout should the approval of an ethics committee use?" + +-- Layout for one formula +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3582301086"] = "Layout for one formula" + +-- Which slide layout should several pictures use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T358514112"] = "Which slide layout should several pictures use, shown together?" + +-- Which slide layout should a step-by-step explanation use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3591485915"] = "Which slide layout should a step-by-step explanation use?" + +-- Layout for ground rules +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3608808260"] = "Layout for ground rules" + +-- Which slide layout should the end of a day or the start of the next use in a workshop of several days? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3683858868"] = "Which slide layout should the end of a day or the start of the next use in a workshop of several days?" + +-- Layout for several user stories +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3692846210"] = "Layout for several user stories" + +-- Which slide layout should the limitations of the work use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3693036613"] = "Which slide layout should the limitations of the work use?" + +-- Which slide layout should a break use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T370295206"] = "Which slide layout should a break use?" + +-- Layout for the medical history +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3716905152"] = "Layout for the medical history" + +-- Layout for several risks +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3766935148"] = "Layout for several risks" + +-- Layout for several examples +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3795085003"] = "Layout for several examples" + +-- Which slide layout should the definitions of several terms use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3798037761"] = "Which slide layout should the definitions of several terms use?" + +-- Layout for several commentaries +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3813550849"] = "Layout for several commentaries" + +-- Which slide layout should several dependencies and their countermeasures use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3816121265"] = "Which slide layout should several dependencies and their countermeasures use?" + +-- Which slide layout should the acknowledgements use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3832735898"] = "Which slide layout should the acknowledgements use?" + +-- Which slide layout should a single picture use, shown prominently, e.g., a screenshot, a photo, or a sketch? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3855855203"] = "Which slide layout should a single picture use, shown prominently, e.g., a screenshot, a photo, or a sketch?" + +-- Layout for one legal provision +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3856771638"] = "Layout for one legal provision" + +-- Layout for much content +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T38628112"] = "Layout for much content" + +-- Which slide layout should a single example or case study use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3892617705"] = "Which slide layout should a single example or case study use?" + +-- Layout for several scenarios +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3919966111"] = "Layout for several scenarios" + +-- Which slide layout should deadlines use, e.g., for an appeal? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3924921260"] = "Which slide layout should deadlines use, e.g., for an appeal?" + +-- Which slide layout should group work use, e.g., the groups and their tasks? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3944216706"] = "Which slide layout should group work use, e.g., the groups and their tasks?" + +-- Which slide layout should an agenda with times and rooms use, e.g., of a workshop? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3970798363"] = "Which slide layout should an agenda with times and rooms use, e.g., of a workshop?" + +-- Layout for discussion prompts +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3976709671"] = "Layout for discussion prompts" + +-- Which slide layout should several theses or central claims use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T398665322"] = "Which slide layout should several theses or central claims use, shown together?" + +-- Layout for processes +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T3988497225"] = "Layout for processes" + +-- Layout for one picture +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4004724742"] = "Layout for one picture" + +-- Which slide layout should differential diagnoses use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4007791050"] = "Which slide layout should differential diagnoses use?" + +-- Which slide layout should several user stories use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4020220483"] = "Which slide layout should several user stories use, shown together?" + +-- Which slide layout should a single delimitation use, i.e., what the work leaves out? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4024727480"] = "Which slide layout should a single delimitation use, i.e., what the work leaves out?" + +-- Which slide layout should a single learning objective use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4043291982"] = "Which slide layout should a single learning objective use, shown prominently?" + +-- Layout for one ruling +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4064917261"] = "Layout for one ruling" + +-- Which slide layout should the course of a disease use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4086697966"] = "Which slide layout should the course of a disease use?" + +-- Layout for one legal question +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4097508115"] = "Layout for one legal question" + +-- Which slide layout should a vision use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T411531801"] = "Which slide layout should a vision use?" + +-- Layout for patient cases +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4126193860"] = "Layout for patient cases" + +-- Which slide layout should several use cases use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T412705947"] = "Which slide layout should several use cases use, shown together?" + +-- Layout for exercises +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4139918235"] = "Layout for exercises" + +-- Which slide layout should a single contract clause use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4148748174"] = "Which slide layout should a single contract clause use, shown prominently?" + +-- Layout for one recommendation +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4152682543"] = "Layout for one recommendation" + +-- Which slide layout should a forecast use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4157101626"] = "Which slide layout should a forecast use?" + +-- Layout for several dependencies +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4167135281"] = "Layout for several dependencies" + +-- Which slide layout should a single legal provision use, e.g., a quoted section of a law? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4240339049"] = "Which slide layout should a single legal provision use, e.g., a quoted section of a law?" + +-- Which slide layout should the sources and the literature use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T424325956"] = "Which slide layout should the sources and the literature use?" + +-- Layout for chapters +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4270765578"] = "Layout for chapters" + +-- Layout for sources and literature +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4288705850"] = "Layout for sources and literature" + +-- Layout for reflection +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4291696997"] = "Layout for reflection" + +-- Layout for group work +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T4352908"] = "Layout for group work" + +-- Which slide layout should side effects and adverse events use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T436684467"] = "Which slide layout should side effects and adverse events use?" + +-- Which slide layout should processes use, e.g., the steps of a workflow? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T472481710"] = "Which slide layout should processes use, e.g., the steps of a workflow?" + +-- Which slide layout should questions to the audience during the presentation use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T481382299"] = "Which slide layout should questions to the audience during the presentation use?" + +-- Which slide layout should a single dependency and its countermeasures use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T483166750"] = "Which slide layout should a single dependency and its countermeasures use?" + +-- Layout for several recommendations +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T488858884"] = "Layout for several recommendations" + +-- Layout for next steps +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T492677118"] = "Layout for next steps" + +-- Layout for disclaimers +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T499992444"] = "Layout for disclaimers" + +-- Layout for one risk +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T520213671"] = "Layout for one risk" + +-- Layout for the facts of the case +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T525510334"] = "Layout for the facts of the case" + +-- Layout for the outlook +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T532661312"] = "Layout for the outlook" + +-- Which slide layout should legal consequences use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T534233457"] = "Which slide layout should legal consequences use?" + +-- Layout for one note +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T542913088"] = "Layout for one note" + +-- Layout for a key message +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T580205055"] = "Layout for a key message" + +-- Which slide layout should an overview of several key figures use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T591913673"] = "Which slide layout should an overview of several key figures use?" + +-- Which slide layout should a single key figure use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T597027606"] = "Which slide layout should a single key figure use, shown prominently?" + +-- Which slide layout should several passages of legal commentaries or other legal literature use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T619125822"] = "Which slide layout should several passages of legal commentaries or other legal literature use, shown together?" + +-- Layout for several reasons +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T642594705"] = "Layout for several reasons" + +-- Layout for adverse events +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T644446987"] = "Layout for adverse events" + +-- Layout for disputes of opinions +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T654393377"] = "Layout for disputes of opinions" + +-- Which slide layout should an executive summary use, which sums up the presentation for decision makers? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T656187586"] = "Which slide layout should an executive summary use, which sums up the presentation for decision makers?" + +-- Which slide layout should several learning objectives use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T661130415"] = "Which slide layout should several learning objectives use, shown together?" + +-- Layout for feedback +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T696819471"] = "Layout for feedback" + +-- Layout for several quotes +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T712009129"] = "Layout for several quotes" + +-- Layout for the closing slide +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T720559061"] = "Layout for the closing slide" + +-- Layout for several notes +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T72227865"] = "Layout for several notes" + +-- Layout for several legal provisions +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T732679023"] = "Layout for several legal provisions" + +-- Which slide layout should lab values use, e.g., with their reference ranges? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T775796006"] = "Which slide layout should lab values use, e.g., with their reference ranges?" + +-- Layout for the ethics approval +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T776275760"] = "Layout for the ethics approval" + +-- Which slide layout should a recommendation of a guideline use, e.g., with its level of evidence? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T779609788"] = "Which slide layout should a recommendation of a guideline use, e.g., with its level of evidence?" + +-- Which slide layout should ordinary slides with content use by default? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T786472161"] = "Which slide layout should ordinary slides with content use by default?" + +-- Layout for imaging +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T792438990"] = "Layout for imaging" + +-- Layout for interpretations +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T805484287"] = "Layout for interpretations" + +-- Layout for little content +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T80953305"] = "Layout for little content" + +-- Layout for several legal questions +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T811795984"] = "Layout for several legal questions" + +-- Which slide layout should an outlook on what comes next use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T813908001"] = "Which slide layout should an outlook on what comes next use?" + +-- Layout for the change of days +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T83666001"] = "Layout for the change of days" + +-- Layout for solutions of exercises +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T839629486"] = "Layout for solutions of exercises" + +-- Layout for one result +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T839738989"] = "Layout for one result" + +-- Layout for calls to action +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T842816024"] = "Layout for calls to action" + +-- Which slide layout should lessons learned use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T843945672"] = "Which slide layout should lessons learned use?" + +-- Which slide layout should the diagnosis use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T847877816"] = "Which slide layout should the diagnosis use?" + +-- Which slide layout should several results use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T852132531"] = "Which slide layout should several results use, shown together?" + +-- Layout for several formulas +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T852509607"] = "Layout for several formulas" + +-- Which slide layout should source code use? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T875188064"] = "Which slide layout should source code use?" + +-- Which slide layout should several recommendations use, shown together? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T910165957"] = "Which slide layout should several recommendations use, shown together?" + +-- Layout for the vision +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T91142277"] = "Layout for the vision" + +-- Which slide layout should a single hypothesis use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T928643773"] = "Which slide layout should a single hypothesis use, shown prominently?" + +-- Which slide layout should a single counterargument use, shown prominently? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T932548010"] = "Which slide layout should a single counterargument use, shown prominently?" + +-- Which slide layout should a story use, e.g., in the storytelling of a keynote? +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T935856327"] = "Which slide layout should a story use, e.g., in the storytelling of a keynote?" + +-- Layout for introduction rounds +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T939876765"] = "Layout for introduction rounds" + +-- Layout for acceptance criteria +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T959706504"] = "Layout for acceptance criteria" + +-- Layout for limitations +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T967847257"] = "Layout for limitations" + +-- Layout for an overview of milestones +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T972717018"] = "Layout for an overview of milestones" + +-- Layout for resources +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T976410413"] = "Layout for resources" + +-- Layout for one problem +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::LAYOUTPURPOSEEXTENSIONS::T980921811"] = "Layout for one problem" + +-- Picture: {0} +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::SLIDEDECKSPEC::T1001457607"] = "Picture: {0}" + +-- Slide {0} of the template, unchanged +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::SLIDEDECKSPEC::T1446011141"] = "Slide {0} of the template, unchanged" + +-- Slide {0} of the template, edited +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::SLIDEDECKSPEC::T2956338097"] = "Slide {0} of the template, edited" + +-- Picture of the template +UI_TEXT_CONTENT["AISTUDIO::TOOLS::POWERPOINT::SLIDEDECKSPEC::T3520350217"] = "Picture of the template" + -- Standard augmentation process UI_TEXT_CONTENT["AISTUDIO::TOOLS::RAG::AUGMENTATIONPROCESSES::AUGMENTATIONONE::T1072508429"] = "Standard augmentation process" @@ -13615,6 +14956,12 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPES::T2547828883"] = "Shortcut" -- Readable text UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPES::T2618627384"] = "Readable text" +-- Picture for slides +UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPES::T2703341748"] = "Picture for slides" + +-- PowerPoint template +UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPES::T3472250354"] = "PowerPoint template" + -- Media UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPES::T3507473059"] = "Media" diff --git a/app/MindWork AI Studio/Assistants/SlideBuilder/PresentationOccasion.cs b/app/MindWork AI Studio/Assistants/SlideBuilder/PresentationOccasion.cs new file mode 100644 index 000000000..c4080bfdc --- /dev/null +++ b/app/MindWork AI Studio/Assistants/SlideBuilder/PresentationOccasion.cs @@ -0,0 +1,30 @@ +namespace AIStudio.Assistants.SlideBuilder; + +/// +/// The occasion of a presentation, which shapes how the LLM structures it. +/// +/// +/// The list covers the common occasions only; OTHER takes any other one as text. +/// +public enum PresentationOccasion +{ + UNSPECIFIED = 0, + + TALK, + KEYNOTE, + CONFERENCE_TALK, + LECTURE, + TRAINING, + WORKSHOP, + MULTI_DAY_WORKSHOP, + THESIS_DEFENSE, + RESEARCH_RESULTS, + PROJECT_REPORT, + MANAGEMENT_REPORT, + PITCH, + PRODUCT_PRESENTATION, + KICK_OFF, + TEAM_MEETING, + + OTHER, +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/SlideBuilder/PresentationOccasionExtensions.cs b/app/MindWork AI Studio/Assistants/SlideBuilder/PresentationOccasionExtensions.cs new file mode 100644 index 000000000..44936b346 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/SlideBuilder/PresentationOccasionExtensions.cs @@ -0,0 +1,56 @@ +namespace AIStudio.Assistants.SlideBuilder; + +public static class PresentationOccasionExtensions +{ + private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(PresentationOccasionExtensions).Namespace, nameof(PresentationOccasionExtensions)); + + public static string Name(this PresentationOccasion occasion) => occasion switch + { + PresentationOccasion.UNSPECIFIED => TB("Unspecified occasion"), + PresentationOccasion.TALK => TB("Talk"), + PresentationOccasion.KEYNOTE => TB("Keynote"), + PresentationOccasion.CONFERENCE_TALK => TB("Conference talk"), + PresentationOccasion.LECTURE => TB("Lecture"), + PresentationOccasion.TRAINING => TB("Training"), + PresentationOccasion.WORKSHOP => TB("Workshop of one day"), + PresentationOccasion.MULTI_DAY_WORKSHOP => TB("Workshop of several days"), + PresentationOccasion.THESIS_DEFENSE => TB("Defense of a thesis or dissertation"), + PresentationOccasion.RESEARCH_RESULTS => TB("Presentation of research results"), + PresentationOccasion.PROJECT_REPORT => TB("Project or status report"), + PresentationOccasion.MANAGEMENT_REPORT => TB("Report to management"), + PresentationOccasion.PITCH => TB("Pitch"), + PresentationOccasion.PRODUCT_PRESENTATION => TB("Product presentation"), + PresentationOccasion.KICK_OFF => TB("Kick-off"), + PresentationOccasion.TEAM_MEETING => TB("Team meeting"), + PresentationOccasion.OTHER => TB("Other occasion"), + + _ => TB("Unspecified occasion"), + }; + + /// + /// Tells the model what the occasion means for the structure of the presentation. + /// + /// The occasion. + /// The occasion the user described, for OTHER. + public static string Prompt(this PresentationOccasion occasion, string customOccasion) => occasion switch + { + PresentationOccasion.TALK => "The presentation accompanies a talk. Structure it for a speaker who talks the audience through it.", + PresentationOccasion.KEYNOTE => "The presentation accompanies a keynote. Favor few words per slide, strong key messages, and a story which carries the audience.", + PresentationOccasion.CONFERENCE_TALK => "The presentation accompanies a talk at a conference. Keep to the essentials of a short time slot, and end with the key messages and room for questions.", + PresentationOccasion.LECTURE => "The presentation accompanies a lecture. Teach step by step, with examples, and where it suits, end chapters with an interim summary or with room for questions.", + PresentationOccasion.TRAINING => "The presentation accompanies a training. Teach practical skills step by step, with examples and exercises where the content offers them.", + PresentationOccasion.WORKSHOP => "The presentation accompanies a workshop of one day. Plan for interaction, e.g., exercises, group work, or discussions, and for the breaks the schedule of the content has.", + PresentationOccasion.MULTI_DAY_WORKSHOP => "The presentation accompanies a workshop of several days. Plan for interaction, mark where a day ends and the next one starts, and look back at the start of each day, following the schedule of the content.", + PresentationOccasion.THESIS_DEFENSE => "The presentation defends a thesis or a dissertation before a committee. Present the research questions, the method, the results, and the contribution precisely, and anticipate critical questions.", + PresentationOccasion.RESEARCH_RESULTS => "The presentation presents research results. Present the questions, the method, the results, and their meaning precisely and comprehensibly.", + PresentationOccasion.PROJECT_REPORT => "The presentation reports on a project. Present the status, the progress, the problems, and the next steps clearly.", + PresentationOccasion.MANAGEMENT_REPORT => "The presentation reports to management and may prepare a decision. Lead with the key messages, keep details short, and state clearly what is to be decided.", + PresentationOccasion.PITCH => "The presentation pitches an idea, a product, or an offer. Lead with the benefit for the audience, and end with a clear call to action.", + PresentationOccasion.PRODUCT_PRESENTATION => "The presentation presents a product. Show what it does and what it brings the audience, with examples.", + PresentationOccasion.KICK_OFF => "The presentation opens a project at its kick-off. Present the goals, the team, the plan, and how the work is organized.", + PresentationOccasion.TEAM_MEETING => "The presentation serves a team meeting. Keep it short and practical, with clear points and next steps.", + PresentationOccasion.OTHER => $"The presentation is for this occasion: {customOccasion}. Structure it accordingly.", + + _ => "No particular occasion is given. Structure the presentation by its content.", + }; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor index 2d1d56dee..6f9e1f170 100644 --- a/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor +++ b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor @@ -1,4 +1,7 @@ @attribute [Route(Routes.ASSISTANT_SLIDE_BUILDER)] +@using AIStudio.Settings.DataModel +@using AIStudio.Tools.PowerPoint +@using AIStudio.Tools.Rust @inherits AssistantBaseCore @T("Content to derive slide from") @@ -7,8 +10,43 @@ - @T("Attach documents") - +@* Side by side where the window is wide enough; each column ends with its zone, so both zones line up below explanations of different length: *@ + + + @T("Attach documents") + + @T("Documents and images attached here are source material: the LLM reads them, but puts none of them on a slide.") + + + + + @T("Pictures for the slides") + + @T("Attach the pictures which the presentation must show, e.g., photos, diagrams, or screenshots. Each of them goes on exactly one slide with room for a picture. Only PNG and JPEG pictures are possible. An LLM which can read images sees them; any other LLM knows only their file names, so clear names help.") + + + + + +@T("Picture library") + + @SlideAssistantTexts.WhatAPictureLibraryOffers + + +@if (this.IsLockedPictureLibraryUnavailable) +{ + @T("The picture library of your organization is not available right now, e.g., because its network drive cannot be reached. Until it is, the assistant plans the slides without it.") +} +@if (this.PictureLibraryHint is { Length: > 0 } pictureLibraryHint) +{ + @pictureLibraryHint +} +@if (!string.IsNullOrWhiteSpace(this.pictureLibraryPath) && !this.IsPictureLibraryLocked) +{ + + @T("Use no picture library") + +} @T("Details about the desired presentation") @@ -22,11 +60,11 @@ @T("You might want to specify important aspects that the LLM should consider when creating the slides. For example, the use of emojis or specific topics that should be highlighted.") - + @T("Extent of the planned presentation") - @T("Please specify the extent of the planned presentation. This can be the number of slides, the number of bullet points per slide, or the time specification for the presentation. This will help the LLM to create a presentation that fits your needs. Leave the default values if you don't have specific requirements regarding the extent of the presentation. You might only want to specify one of these parameters, for example the time specification, and leave the others at their default values.") + @T("Please specify the extent of the planned presentation. This can be the number of slides, the maximum number of bullet points per slide, or the time specification for the presentation. This will help the LLM to create a presentation that fits your needs. Leave the default values if you don't have specific requirements regarding the extent of the presentation. You might only want to specify one of these parameters, for example the time specification, and leave the others at their default values.") @@ -39,10 +77,11 @@ @@ -58,6 +97,12 @@ @T("Language") +@T("Occasion") + + @T("The occasion helps the LLM to structure the presentation. A lecture, for example, may close its chapters with an interim summary or with room for questions, and a report to management leads with the key messages.") + + + @T("Audience") @T("Please specify the audience for the planned presentation. This will help the LLM to create a presentation that fits your needs. You can specify the audience profile, the age group, organizational level, and the expertise. You don't have to specify all of these parameters, for example you might only want to specify the audience profile and leave the other parameters at their default values.") @@ -66,4 +111,77 @@ + + @T("PowerPoint template") + + @T("Choose a PowerPoint presentation or template (.pptx, .potx) whose layouts the slides should use. The LLM then plans every slide for one of these layouts, and you can create a PowerPoint file (.pptx) in the design of your template, which other programs such as LibreOffice Impress open as well. OpenDocument presentations (.odp, .otp) cannot serve as a template yet. Without a template, you get an outline, which you can copy or export.") + + + @SlideAssistantTexts.WhatTheLLMKnowsOfLayouts + + +@if (this.IsLockedTemplateUnavailable) +{ + @T("The PowerPoint template of your organization is not available right now, e.g., because its network drive cannot be reached. Until it is, the assistant plans an outline only.") +} +@if (!string.IsNullOrWhiteSpace(this.templatePath) && !this.IsTemplateLocked) +{ + + @T("Use no template") + +} + +@* The select renders its items again on its own, e.g., while the form validates, when the template may be gone already: *@ +@if (this.template is { } loadedTemplate) +{ + + @if (loadedTemplate.VariantLabels.Count > 0) + { + + @foreach (var label in loadedTemplate.VariantLabels) + { + @label + } + + } + + + + + @T("Keep empty picture placeholders") + + + @SlideAssistantTexts.WhatKeepingEmptyPicturePlaceholdersDoes + + + @T("Layouts for kinds of slides") + + @SlideAssistantTexts.WhatALayoutChoiceDoes + + + + + @LayoutPurposeExtensions.NoPreference + @foreach (var layoutName in loadedTemplate.FamilyNames) + { + @layoutName + } + + + + + @if (loadedTemplate.Slides.Count > 0) + { + @T("Slides of the template") + + @SlideAssistantTexts.WhatHappensToTemplateSlides + + @foreach (var templateSlide in loadedTemplate.Slides) + { + + } + } + +} + diff --git a/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Library.cs b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Library.cs new file mode 100644 index 000000000..ab1ac6b4d --- /dev/null +++ b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Library.cs @@ -0,0 +1,257 @@ +using AIStudio.Settings; +using AIStudio.Tools.AssistantSessions; +using AIStudio.Tools.PowerPoint; +using AIStudio.Tools.Security; + +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Assistants.SlideBuilder; + +/// +/// The part of the Slide Assistant which offers the LLM a folder of pictures and icons to choose from. +/// +/// +/// The LLM reads only the names of the pictures, never the pictures themselves, and need not use +/// any of them; see PictureLibrary. The library is read anew for each planning, so that a large +/// one offers another random sample each time, and once whenever the user chooses a folder, to tell +/// how many pictures it holds. +/// +public partial class SlideAssistant +{ + [Inject] + private ThreadSafeRandom RandomSource { get; init; } = null!; + + private string pictureLibraryPath = string.Empty; + private static readonly AssistantSessionStateKey PICTURE_LIBRARY_PATH_STATE_KEY = new(nameof(pictureLibraryPath)); + + /// + /// How many pictures the chosen library holds, for the hint below the field; it holds no sample. + /// + private PictureLibraryContent pictureLibraryOverview = PictureLibraryContent.NONE; + + private bool isReadingPictureLibrary; + private CancellationTokenSource? pictureLibraryReading; + + /// + /// Whether the chosen library folder exists, as its last count found. + /// + /// + /// The form asks this with every rendering, and an unreachable network drive takes seconds to + /// answer, so the folder is checked only when it changes, and away from the rendering. + /// + private bool isPictureLibraryAvailable; + + /// + /// What the library offers to the planning under way, while the system prompt is written for it. + /// + private PictureLibraryContent planningLibrary = PictureLibraryContent.NONE; + + /// + /// Whether the organization dictates the picture library. + /// + /// + /// Like the template, the library is a preselection, so a lock binds only while preselection is enabled. + /// + private bool IsPictureLibraryLocked => this.SettingsManager.ConfigurationData.SlideBuilder.PreselectOptions && ManagedConfiguration.TryGet(x => x.SlideBuilder, x => x.PreselectedPictureLibraryPath, out var meta) && meta.IsLocked; + + /// + /// Whether the picture library of the organization is locked, but cannot be read right now, e.g., + /// because its network drive cannot be reached. + /// + /// + /// The user cannot choose another folder then, so it must not block the form. The assistant plans + /// without a library instead, and the form says why. + /// + private bool IsLockedPictureLibraryUnavailable => this.IsPictureLibraryLocked && this.pictureLibraryPath.Length > 0 && !this.isReadingPictureLibrary && !this.isPictureLibraryAvailable; + + private async Task OnPictureLibraryChanged(string path) + { + this.pictureLibraryPath = path; + await this.ReadPictureLibraryOverviewAsync(); + if (this.Form is not null) + await this.Form.Validate(); + } + + private async Task UseNoPictureLibrary() => await this.OnPictureLibraryChanged(string.Empty); + + private string? ValidatePictureLibrary(string path) + { + // The warning below the field explains a locked folder, since the user cannot change it, and + // while the folder is still counted, it is too early to tell: + if (string.IsNullOrWhiteSpace(path) || this.IsPictureLibraryLocked || this.isReadingPictureLibrary) + return null; + + return this.isPictureLibraryAvailable ? null : T("The folder does not exist."); + } + + /// + /// Counts the pictures of the chosen library without waiting for it, e.g., after the library was preselected or restored. + /// + private void StartCountingPictureLibrary() => this.ReadPictureLibraryOverviewAsync().Observe($"{nameof(SlideAssistant)}: counting the pictures of the library"); + + /// + /// Counts the pictures of the chosen library for the hint, and cancels a count still running for another folder. + /// + private async Task ReadPictureLibraryOverviewAsync() + { + if (this.pictureLibraryReading is { } previousReading) + { + await previousReading.CancelAsync(); + previousReading.Dispose(); + } + + this.pictureLibraryOverview = PictureLibraryContent.NONE; + this.isPictureLibraryAvailable = false; + var path = this.pictureLibraryPath; + if (path.Length == 0) + { + this.pictureLibraryReading = null; + return; + } + + var reading = new CancellationTokenSource(); + this.pictureLibraryReading = reading; + this.isReadingPictureLibrary = true; + this.StateHasChanged(); + try + { + var isAvailable = await FolderExistsAsync(path, reading.Token); + var overview = isAvailable ? await PictureLibrary.ReadAsync(path, this.RandomSource, 0, this.ReportInaccessibleLibraryFolder, reading.Token) : PictureLibraryContent.NONE; + if (!reading.IsCancellationRequested) + { + this.isPictureLibraryAvailable = isAvailable; + this.pictureLibraryOverview = overview; + } + } + catch (OperationCanceledException) + { + // Another folder was chosen meanwhile, and its count is under way. + } + catch (Exception e) + { + this.Logger.LogWarning(e, "The picture library '{FolderPath}' cannot be read.", path); + } + finally + { + // A count which started without a user's action, e.g., for a preselected folder, ends + // without a rendering of its own: + if (ReferenceEquals(this.pictureLibraryReading, reading)) + { + this.isReadingPictureLibrary = false; + this.StateHasChanged(); + } + } + } + + /// + /// Reads the library for a planning, with a new random sample when it is large. + /// + /// What the library offers; nothing when the user chose no library or it cannot be read. + private async Task ReadPictureLibraryForPlanningAsync() + { + var path = this.pictureLibraryPath; + if (path.Length == 0) + return PictureLibraryContent.NONE; + + var token = this.CancellationTokenSource?.Token ?? CancellationToken.None; + try + { + if (!await FolderExistsAsync(path, token)) + { + this.Logger.LogWarning("The picture library '{FolderPath}' is not available, so the slides are planned without it.", path); + return PictureLibraryContent.NONE; + } + + return await PictureLibrary.ReadAsync(path, this.RandomSource, PictureLibrary.MAX_LIBRARY_PICTURES, this.ReportInaccessibleLibraryFolder, token); + } + catch (Exception e) when (e is not OperationCanceledException) + { + this.Logger.LogWarning(e, "The picture library '{FolderPath}' cannot be read, so the slides are planned without it.", path); + return PictureLibraryContent.NONE; + } + } + + /// + /// Whether a folder exists, asked on a thread of its own, since an unreachable network drive takes seconds to answer. + /// + private static Task FolderExistsAsync(string path, CancellationToken token) => Task.Run(() => Directory.Exists(path), token); + + private void ReportInaccessibleLibraryFolder(string folderPath, Exception e) => this.Logger.LogWarning(e, "The folder '{FolderPath}' of the picture library cannot be read.", folderPath); + + /// + /// What the chosen library holds, below the field; empty while there is nothing to tell. + /// + private string PictureLibraryHint + { + get + { + if (this.isReadingPictureLibrary) + return T("Counting the pictures of the folder..."); + + if (!this.isPictureLibraryAvailable) + return string.Empty; + + var library = this.pictureLibraryOverview; + var hints = new List + { + library.PictureCount == 0 + ? T("The folder holds no PNG or JPEG pictures.") + : string.Format(T("{0} pictures, {1} of them icons."), library.PictureCount.CompactCount(), library.IconCount.CompactCount()), + }; + + if (library.SkippedFileCount > 0) + hints.Add(string.Format(T("{0} other files are left out, because they are neither PNG nor JPEG."), library.SkippedFileCount.CompactCount())); + + if (library.PictureCount > PictureLibrary.MAX_LIBRARY_PICTURES) + hints.Add(string.Format(T("For each planning, the LLM gets a random {0} of them."), SlideAssistantTexts.MaxLibraryPictures)); + + return string.Join(" ", hints); + } + } + + /// + /// The pictures of the library by their numbers, which follow those of the pictures for the slides, for the user's request. + /// + /// + /// The names come from a folder, which may be a network drive anybody can write to, so they pass + /// the prompt injection filter like the texts of a template. + /// + /// The prompt injection filter. + /// The action of the request, which reports what the filter removed. + /// What the library offers for this request. + /// The number of the first picture of the library. + /// The library folder. + /// The section of the request; empty without pictures in the library. + private static async Task PromptPictureLibraryAsync(PromptInjectionGuardService guardService, PromptInjectionReportingScope promptInjectionScope, PictureLibraryContent library, int firstNumber, string folderPath) + { + if (library.Pictures.Count == 0) + return string.Empty; + + var list = string.Join(Environment.NewLine, library.Pictures.Select((picture, index) => $"- Picture {firstNumber + index}: {picture.Name}{(picture.IsIcon ? " (icon)" : string.Empty)}")); + var sanitizedList = await guardService.SanitizeAsync(list, PromptInjectionSource.FileContent(folderPath), promptInjectionScope); + return $""" + + # PICTURE_LIBRARY + {sanitizedList} + """; + } + + /// + /// The rules for the pictures of the library; empty without them. + /// + private string PromptPictureLibraryRules() => this.planningLibrary.Pictures.Count == 0 + ? string.Empty + : """ + - PICTURE_LIBRARY lists further pictures by their numbers and names; you know only their names. Fill the picture slots of your new slides from it: wherever a name fits the content of a slide, place that picture there by its number. Leave a picture slot empty only when no name fits. A picture which is not an icon appears at most once. + - Pictures marked "(icon)" are icons. An icon may appear on several slides, e.g., to mark each risk the same way, and suits picture slots of any size, except those marked as backdrop. + """; + + /// + protected override void DisposeResources() + { + this.pictureLibraryReading?.Cancel(); + this.pictureLibraryReading?.Dispose(); + this.pictureLibraryReading = null; + base.DisposeResources(); + } +} diff --git a/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Presentation.cs b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Presentation.cs new file mode 100644 index 000000000..6832a62cb --- /dev/null +++ b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Presentation.cs @@ -0,0 +1,592 @@ +using System.Globalization; + +using AIStudio.Chat; +using AIStudio.Settings; +using AIStudio.Tools.AssistantSessions; +using AIStudio.Tools.PowerPoint; +using AIStudio.Tools.Rust; +using AIStudio.Tools.Security; + +namespace AIStudio.Assistants.SlideBuilder; + +/// +/// The part of the Slide Assistant which works with PowerPoint: the template, the slides the model +/// plans for its layouts, and the file written from them. +/// +public partial class SlideAssistant +{ + /// + /// The layouts of a plain presentation, which the model plans with when no template was chosen. + /// + private static readonly PresentationTemplate DEFAULT_CATALOG = PresentationTemplate.CreateDefault(); + + /// + /// How many issues the repair request names at most. + /// + /// + /// A model handed fifty issues fixes the first few and loses track of the rest; a dozen names + /// what is wrong in kind, and the model finds the like on its own. + /// + private const int MAX_REPORTED_ISSUES = 12; + + private string templatePath = string.Empty; + private string footerText = string.Empty; + private bool keepEmptyPicturePlaceholders; + private string? variantLabel; + private PresentationTemplate? template; + private SlideDeckSpec? slideDeck; + private bool isWritingPresentation; + + /// + /// Whether the options of the template are open: its color variant, the footer, and its slides. + /// + private bool advancedOptionsExpanded; + + /// + /// What the user chose for each slide of the template, by its number. + /// + private List templateSlideUses = []; + + /// + /// The name of the layout the user chose for each kind of slide; a kind left to the LLM is missing. + /// + /// + /// Names stay when the user chooses another template, so that they apply again once a template + /// with these layouts is back. A name the current template does not have counts as no choice. + /// + private readonly Dictionary layoutNames = new(); + + /// + /// The answer the slide deck was read from, which the session keeps to restore the deck. + /// + private string slideDeckAnswer = string.Empty; + + /// + /// The template the slide deck was planned for; empty when it was planned without one. + /// + private string slideDeckTemplatePath = string.Empty; + + /// + /// The pictures the slide deck may use, by the numbers the model gave them: every picture for the + /// slides, and those of the library which the deck uses, not the thousands it was offered. + /// + private readonly Dictionary slideDeckPicturePaths = new(); + + /// + /// The numbers of the pictures in slideDeckPicturePaths which are icons. + /// + private readonly HashSet slideDeckIconNumbers = []; + + /// + /// What the slide deck was planned on: the layouts and template slides it uses, as the model read them. + /// + /// + /// The template may change before the user saves the presentation, see SlideDeckSpecValidator.StillFits. + /// + private readonly Dictionary slideDeckBasis = new(StringComparer.Ordinal); + + private static readonly AssistantSessionStateKey TEMPLATE_PATH_STATE_KEY = new(nameof(templatePath)); + private static readonly AssistantSessionStateKey FOOTER_TEXT_STATE_KEY = new(nameof(footerText)); + private static readonly AssistantSessionStateKey KEEP_EMPTY_PICTURE_PLACEHOLDERS_STATE_KEY = new(nameof(keepEmptyPicturePlaceholders)); + private static readonly AssistantSessionStateKey VARIANT_LABEL_STATE_KEY = new(nameof(variantLabel)); + private static readonly AssistantSessionStateKey ADVANCED_OPTIONS_EXPANDED_STATE_KEY = new(nameof(advancedOptionsExpanded)); + private static readonly AssistantSessionStateKey> TEMPLATE_SLIDE_USES_STATE_KEY = new(nameof(templateSlideUses)); + private static readonly AssistantSessionStateKey> LAYOUT_NAMES_STATE_KEY = new(nameof(layoutNames)); + private static readonly AssistantSessionStateKey SLIDE_DECK_ANSWER_STATE_KEY = new(nameof(slideDeckAnswer)); + private static readonly AssistantSessionStateKey SLIDE_DECK_TEMPLATE_PATH_STATE_KEY = new(nameof(slideDeckTemplatePath)); + private static readonly AssistantSessionStateKey> SLIDE_DECK_PICTURE_PATHS_STATE_KEY = new(nameof(slideDeckPicturePaths)); + private static readonly AssistantSessionStateKey> SLIDE_DECK_ICON_NUMBERS_STATE_KEY = new(nameof(slideDeckIconNumbers)); + private static readonly AssistantSessionStateKey> SLIDE_DECK_BASIS_STATE_KEY = new(nameof(slideDeckBasis)); + + /// + /// The layouts the model plans with: those of the chosen template, or those of a plain presentation. + /// + private PresentationTemplate Catalog => this.template ?? DEFAULT_CATALOG; + + /// + /// Whether the organization dictates the template. + /// + /// + /// The template is a preselection, so a lock binds only while preselection is enabled. Without + /// preselection, the assistant starts without a template, and the user may choose one. + /// + private bool IsTemplateLocked => this.SettingsManager.ConfigurationData.SlideBuilder.PreselectOptions && ManagedConfiguration.TryGet(x => x.SlideBuilder, x => x.TemplatePath, out var meta) && meta.IsLocked; + + /// + /// Whether the template of the organization is locked, but cannot be read right now, e.g., + /// because its network drive cannot be reached. + /// + /// + /// The user cannot choose another template then, so it must not block the form. The assistant + /// plans an outline instead, as without a template, and the form says why. + /// + private bool IsLockedTemplateUnavailable => this.IsTemplateLocked && !string.IsNullOrWhiteSpace(this.templatePath) && this.template is null; + + /// + /// Whether the organization locked the layouts for kinds of slides. + /// + /// + /// Like the template, the layouts are a preselection, so a lock binds only while preselection is enabled. + /// + private bool AreLayoutsLocked => this.SettingsManager.ConfigurationData.SlideBuilder.PreselectOptions && ManagedConfiguration.TryGet(x => x.SlideBuilder, x => x.PreselectedLayouts, out var meta) && meta.IsLocked; + + /// + /// Whether the organization locked what the presentation does with the slides of the template. + /// + /// + /// The lock binds only for the preselected template, whose slides the choices number. For any + /// other template, the user chooses freely. + /// + private bool AreTemplateSlideUsesLocked => this.IsPreselectedTemplate && ManagedConfiguration.TryGet(x => x.SlideBuilder, x => x.PreselectedTemplateSlideUses, out var meta) && meta.IsLocked; + + /// + /// Whether preselection is enabled and the chosen template is the preselected one. + /// + private bool IsPreselectedTemplate => this.SettingsManager.ConfigurationData.SlideBuilder.PreselectOptions && this.template is not null && string.Equals(this.templatePath, this.SettingsManager.ConfigurationData.SlideBuilder.TemplatePath, StringComparison.Ordinal); + + /// + /// What the user chose for the slides of the template, as the model and the check of its answer see it; empty without a template. + /// + private IReadOnlyList ChosenTemplateSlideUses => this.template is null ? [] : this.templateSlideUses.ToList(); + + private bool HasChosenTemplateSlides => this.template is not null && this.templateSlideUses.Any(use => use is not TemplateSlideUse.OMIT); + + /// + /// The layouts the user chose for kinds of slides, as the current template offers them; none without a template. + /// + private ChosenLayouts ChosenLayoutsOfTemplate => this.template is null ? ChosenLayouts.NONE : ChosenLayouts.Of(this.template, this.layoutNames); + + /// + /// How many slides the user asked for, or 0 when the model may choose. + /// + /// + /// A number of slides wins over a duration. A duration means one slide per one and a half + /// minutes, as the form has always counted it. + /// + private int ExpectedSlideCount => this.numberOfSheets > 0 + ? this.numberOfSheets + : (int)Math.Round(this.timeSpecification / 1.5); + + private bool PlannedForCurrentTemplate => this.template is not null && this.slideDeckTemplatePath.Length > 0 && string.Equals(this.slideDeckTemplatePath, this.templatePath, StringComparison.Ordinal); + + private bool CanCreatePresentation => this.slideDeck is not null && this.PlannedForCurrentTemplate && !this.isWritingPresentation && !this.IsProcessing; + + private string CreatePresentationTooltip + { + get + { + if (this.slideDeck is null) + return T("Please plan the slides first."); + + if (this.template is null) + return T("Please choose a PowerPoint template to create a file from the slides."); + + if (!this.PlannedForCurrentTemplate) + return T("The slides were planned for another template. Please plan them again."); + + return T("Creates a PowerPoint file in the design of your template."); + } + } + + /// + /// Reads the layouts of the chosen template. + /// + /// + /// A template which cannot be read leaves no template at all. The form then says why, and + /// nothing is planned for layouts nobody can write. + /// + private void LoadTemplate() + { + this.template = null; + if (string.IsNullOrWhiteSpace(this.templatePath)) + return; + + if (!File.Exists(this.templatePath)) + { + this.Logger.LogWarning("The PowerPoint template '{TemplatePath}' does not exist.", this.templatePath); + return; + } + + try + { + this.template = PresentationTemplate.ReadFile(this.templatePath); + } + catch (Exception e) + { + this.Logger.LogWarning(e, "The PowerPoint template '{TemplatePath}' cannot be read.", this.templatePath); + return; + } + + // A variant of another template means nothing for this one, nor do choices for its slides: + if (this.variantLabel is null || !this.template.VariantLabels.Contains(this.variantLabel)) + this.variantLabel = this.template.VariantLabels.FirstOrDefault(); + + if (this.templateSlideUses.Count != this.template.Slides.Count) + this.templateSlideUses = DefaultTemplateSlideUsesOf(this.template); + } + + private async Task OnTemplateChanged(string path) + { + this.templatePath = path; + this.templateSlideUses = []; + this.LoadTemplate(); + this.ApplyPreselectedTemplateSlideUses(); + if (this.Form is not null) + await this.Form.Validate(); + } + + /// + /// What the presentation does with the slides of a template unless the user says otherwise. + /// + /// + /// The presentation leaves every slide out. A template serves its design first, and the slides + /// of a file are as often samples and hints as an earlier presentation: whoever wants one of them + /// in the new presentation says so. + /// + private static List DefaultTemplateSlideUsesOf(PresentationTemplate template) => Enumerable.Repeat(TemplateSlideUse.OMIT, template.Slides.Count).ToList(); + + /// + /// Applies what the settings preselect for the slides of the template, as long as it is the preselected template. + /// + /// + /// The choices number the slides of the preselected template, so they mean nothing for another + /// one. A choice which the template cannot follow, e.g., for a slide it lost since, is logged. + /// + private void ApplyPreselectedTemplateSlideUses() + { + if (!this.IsPreselectedTemplate || this.template is null) + return; + + var choices = this.SettingsManager.ConfigurationData.SlideBuilder.PreselectedTemplateSlideUses; + this.templateSlideUses = choices.ToTemplateSlideUses(this.template); + foreach (var (number, use) in choices) + if (this.templateSlideUses.UseOf(number) != use) + this.Logger.LogWarning("The PowerPoint template '{TemplatePath}' cannot follow the preselected use '{Use}' of its slide {Number}: it has no such slide, or the slide has no placeholders for content.", this.templatePath, use, number); + } + + private TemplateSlideUse TemplateSlideUseOf(int number) => this.templateSlideUses.UseOf(number); + + private void SetTemplateSlideUse(int number, TemplateSlideUse use) + { + if (number >= 1 && number <= this.templateSlideUses.Count) + this.templateSlideUses[number - 1] = use; + } + + private string? ValidateTemplateSlideUse(TemplateSlide slide, TemplateSlideUse use) + { + if (use is TemplateSlideUse.EDIT && !slide.IsEditable) + return T("The LLM cannot edit this slide, because its layout has no placeholders for content. Please keep it unchanged or leave it out."); + + return null; + } + + /// + /// The name of the layout chosen for a kind of slide, as the form shows it. + /// + /// The name, or empty when the LLM decides, which it also does when the template has no layout of this name. + private string LayoutNameOf(LayoutPurpose purpose) => this.template is not null && this.layoutNames.TryGetValue(purpose, out var name) && this.template.FindFamilyByName(name) is not null ? name : string.Empty; + + private void SetLayoutName(LayoutPurpose purpose, string name) + { + if (name.Length == 0) + this.layoutNames.Remove(purpose); + else + this.layoutNames[purpose] = name; + } + + /// + /// The rules for the layouts the user chose; empty when the LLM decides every layout. + /// + private string PromptChosenLayouts() => this.ChosenLayoutsOfTemplate.ToPromptRules(); + + private async Task UseNoTemplate() => await this.OnTemplateChanged(string.Empty); + + private string? ValidateTemplate(string path) + { + // The warning below the field explains this case, since the user cannot change the template: + if (string.IsNullOrWhiteSpace(path) || this.IsLockedTemplateUnavailable) + return null; + + if (!File.Exists(path)) + return T("The template file does not exist."); + + if (this.template is null) + return T("The template cannot be read. Please choose a PowerPoint presentation or template (.pptx, .potx)."); + + if (this.template.Families.Count == 0) + return T("The template has no layouts with room for content."); + + return null; + } + + /// + /// The pictures for the slides, in the order the model numbers them. + /// + private List PicturesOfRequest() => this.slidePictures.Where(n => n is { Exists: true, IsImage: true }).ToList(); + + /// + /// The images of the source material, which the model reads but never places. + /// + private List SourceImagesOfRequest() => this.loadedDocumentPaths.Where(n => n is { Exists: true, IsImage: true }).ToList(); + + private string PromptPictures() + { + var rules = new List(); + if (this.PicturesOfRequest().Count > 0) + rules.Add(" - PICTURES lists the pictures the presentation must show, by their numbers. Place each of them exactly once, by its number, on a slide with a picture slot whose content it fits."); + + if (this.PromptPictureLibraryRules() is { Length: > 0 } libraryRules) + rules.Add(libraryRules); + + if (rules.Count == 0) + rules.Add(" - No pictures for the slides are attached. Leave out \"pictures\" on every slide."); + + if (this.SourceImagesOfRequest().Count > 0) + rules.Add(" - Images attached as source material are for reading only. Never place them on a slide."); + + return string.Join(Environment.NewLine, rules); + } + + /// + /// The pictures for the slides by their numbers, for the user's request. + /// + /// + /// The names are those of the user's files, so they go with the request, like the paths of the + /// attached documents, rather than into the system prompt. A model which reads images gets the + /// pictures as well; any other model has only their names to go by. + /// + /// The pictures taken at the start of the request, in the order the model numbers them. + /// Whether the pictures go to the model as images. + /// The section of the request; empty without pictures. + private static string PromptPictureList(IReadOnlyList pictures, bool modelSeesPictures) + { + if (pictures.Count == 0) + return string.Empty; + + var list = string.Join(Environment.NewLine, pictures.Select((picture, index) => $"- Picture {index + 1}: {picture.FileName}")); + var seeing = modelSeesPictures + ? "The images attached to this request start with these pictures, in this order." + : "You cannot see these pictures. Place them by what their names say."; + + return $""" + + # PICTURES + {seeing} + {list} + """; + } + + private string PromptSlideCount() + { + var expectedSlideCount = this.ExpectedSlideCount; + if (expectedSlideCount <= 0) + return " - Choose as many slides as the content needs."; + + return this.HasChosenTemplateSlides + ? $" - The presentation has exactly {expectedSlideCount} slides, the title slide and the template slides included." + : $" - The presentation has exactly {expectedSlideCount} slides, the title slide included."; + } + + /// + /// The rules for the slides of the template the user chose; empty when the user chose none. + /// + /// + /// The slides themselves come with the user's request, as TEMPLATE_SLIDES, since their texts are + /// content of a file rather than instructions. + /// + private string PromptTemplateSlides() + { + if (!this.HasChosenTemplateSlides) + return string.Empty; + + return """ + + # Template slides + The user chose slides of the template to use in the presentation. TEMPLATE_SLIDES lists them in their order, each one either to keep unchanged or to edit. + - Write a slide to keep as { "template_slide": } and nothing else. Add "starts_chapter": true where it opens a chapter. + - Write a slide to edit with "template_slide": and its new content in the usual fields, which fill the slots its entry names. Leave out "layout": the slide keeps its own. A slot you neither fill nor remove keeps the content of the template slide, and so does every element you do not remove. + - Where an entry gives a slot its place and size "on this slide", the slide moved or resized it, e.g., to make room for a picture of its own, or carries it as a copy of another slot, e.g., a further heading with its text. Fill such a slot like any other, and stay within the lines and characters stated there rather than those of the layout. + - An entry to edit also lists the elements the slide carries besides its slots, e.g., pictures, text boxes, charts, or tables of its own, with their place and the slots they overlap. List what the slide no longer shows in "remove", by the names the entry uses, e.g., "remove": ["element 2", "label 1"]. + - Remove what does not fit the new content: samples and hints of the template, e.g., placeholder pictures, sample texts such as "Lorem ipsum", or a request to name the source of a picture; old content of a slot which no longer fits; and every element which overlaps a slot you fill, unless it covers most of the slide as a background. Keep what still belongs to the slide, e.g., a logo or a decoration. Never fill and remove the same slot, and never remove the title. + - Use every listed slide exactly once, in the listed order. Add new slides before, between, and after them, wherever the content calls for it. + - Do not repeat on a new slide what a kept slide says already. + - Example: "slides": [{ "template_slide": 1 }, { "layout": "L3", "title": "..." }, { "template_slide": 3, "title": "...", "texts": [["..."]], "remove": ["element 1"] }] + """; + } + + /// + /// The rule for the field listing what an edited template slide removes; empty when the user + /// edits no template slide, so that the model does not hear of the field at all. + /// + private string PromptRemoveRule() => this.template is not null && this.templateSlideUses.Any(use => use is TemplateSlideUse.EDIT) + ? """ + - "remove" lists the slots and elements a template slide to edit no longer shows, by the names TEMPLATE_SLIDES uses. Leave it out on every other slide. + """ + : string.Empty; + + /// + /// The layouts the model plans with, for the user's request. + /// + /// + /// The catalog names the layouts as the author of the template named them. These names come from + /// a file, which may carry instructions of somebody else, so the catalog goes with the request + /// rather than into the system prompt, and the layouts of a template pass the prompt injection + /// filter like its slides. The layouts of a plain presentation come from the code. + /// + /// The prompt injection filter. + /// The action of the request, which reports what the filter removed. + /// The layouts taken at the start of the request. + /// The template the layouts were read from; empty for the layouts of a plain presentation. + /// The section of the request. + private static async Task PromptLayoutsAsync(PromptInjectionGuardService guardService, PromptInjectionReportingScope promptInjectionScope, PresentationTemplate catalog, string templatePath) + { + var layouts = catalog.ToCatalogPrompt(); + if (templatePath.Length > 0) + layouts = await guardService.SanitizeAsync(layouts, PromptInjectionSource.FileContent(templatePath), promptInjectionScope); + + return $""" + + # LAYOUTS + {layouts} + """; + } + + /// + /// The slides of the template the user chose, with what they hold, for the user's request. + /// + /// + /// Their texts come from a file, which may carry instructions of somebody else, so they pass the + /// prompt injection filter like every attached document. + /// + /// The prompt injection filter. + /// The action of the request, which reports what the filter removed. + /// The layouts and slides taken at the start of the request. + /// The template they were read from; empty without a template. + /// What the user chose for each slide of the template. + /// The section of the request; empty when the user chose no slide. + private static async Task PromptTemplateSlidesAsync(PromptInjectionGuardService guardService, PromptInjectionReportingScope promptInjectionScope, PresentationTemplate catalog, string templatePath, IReadOnlyList templateSlideUses) + { + if (templatePath.Length == 0 || catalog.ToTemplateSlidesPrompt(templateSlideUses) is not { Length: > 0 } templateSlides) + return string.Empty; + + var sanitizedTemplateSlides = await guardService.SanitizeAsync(templateSlides, PromptInjectionSource.FileContent(templatePath), promptInjectionScope); + return $""" + + # TEMPLATE_SLIDES + {sanitizedTemplateSlides} + """; + } + + private string PromptBulletPoints() + { + var count = this.numberOfBulletPoints > 0 + ? $" - A slide has at most {this.numberOfBulletPoints} main points, all its text slots together. Fewer are fine where the content needs fewer." + : " - Choose between 1 and 7 main points per text slot, as its space allows."; + + return $""" + {count} + - Every point is short: at most 12 words, clear, and directly related to the slide title. + """; + } + + /// + /// Reads the slide deck out of an answer and checks it against the layouts it was planned for. + /// + /// The deck, or none when the answer cannot be read, with the issues, written for the model. + private CheckedAnswer CheckAnswer(string answer, PresentationTemplate catalog, int pictureCount, LibraryPictures libraryPictures, IReadOnlyList chosenTemplateSlideUses, ChosenLayouts chosenLayouts) + { + if (!SlideDeckSpec.TryParse(answer, out var deck, out var issue)) + return new CheckedAnswer(null, [issue]); + + return new CheckedAnswer(deck, SlideDeckSpecValidator.Validate(deck, catalog, pictureCount, this.ExpectedSlideCount, chosenTemplateSlideUses, chosenLayouts, this.numberOfBulletPoints, libraryPictures)); + } + + private static string RepairPromptOf(IReadOnlyList issues) + { + var listedIssues = string.Join(Environment.NewLine, issues.Take(MAX_REPORTED_ISSUES).Select(issue => $"- {issue}")); + return $""" + Your JSON does not fit the layouts yet: + {listedIssues} + + Answer with the complete corrected JSON object and nothing else. + """; + } + + /// + /// Shows the slide deck as an outline, which is the visible result of the assistant. + /// + /// + /// The outline becomes the last block of the chat, so copying the result, exporting it, and + /// sending it to a chat all work with the outline rather than with the JSON behind it. + /// + private void ShowOutline(SlideDeckSpec deck, PresentationTemplate catalog, IReadOnlyDictionary pictureNames) + { + var outline = new ContentBlock + { + Time = DateTimeOffset.Now, + ContentType = ContentType.TEXT, + Role = ChatRole.AI, + HideFromUser = false, + Content = new ContentText { Text = deck.ToMarkdownOutline(catalog, pictureNames) }, + }; + + this.ChatThread?.Blocks.Add(outline); + this.ResultingContentBlock = outline; + } + + private void RestoreSlideDeck() => this.slideDeck = this.slideDeckAnswer.Length > 0 && SlideDeckSpec.TryParse(this.slideDeckAnswer, out var deck, out _) ? deck : null; + + private async Task CreatePresentationFileAsync() + { + if (!this.CanCreatePresentation || this.slideDeck is not { } deck) + return; + + var fileName = FileExportFormatExtensions.ToFileNameFragment(deck.Title); + var response = await this.RustService.SaveFile(T("Save the presentation"), [FileTypes.POWER_POINT_PRESENTATION], $"{(fileName.Length == 0 ? "presentation" : fileName)}.pptx"); + if (response.UserCancelled) + return; + + var targetPath = response.SaveFilePath; + this.isWritingPresentation = true; + this.StateHasChanged(); + try + { + var options = new PresentationWriteOptions(this.variantLabel, this.footerText.Trim(), this.keepEmptyPicturePlaceholders); + var pictures = new RustPictureSource(this.RustService, this.slideDeckPicturePaths, this.slideDeckIconNumbers); + var result = await PresentationFile.CreateAsync(this.slideDeckTemplatePath, targetPath, deck, this.slideDeckBasis, options, pictures, this.Logger, CancellationToken.None); + if (!result.IsWritten) + { + this.Logger.LogWarning("The PowerPoint template '{TemplatePath}' changed since the slides were planned, and they no longer fit it.", this.slideDeckTemplatePath); + await this.MessageBus.SendError(new(Icons.Material.Filled.Slideshow, T("The template has changed since the slides were planned. Please create the slides again."))); + return; + } + + var placements = deck.Slides.SelectMany(slide => slide.Pictures).ToList(); + this.Logger.LogInformation("The slide assistant saved {SlideCount} slides to '{FilePath}', with {PlacedPictureCount} of {PictureCount} pictures placed and empty picture placeholders {EmptyPicturePlaceholders}.", deck.Slides.Count, targetPath, placements.Count(number => !result.SkippedPictures.Contains(number)), placements.Count, this.keepEmptyPicturePlaceholders ? "kept" : "left out"); + if (result.SkippedPictures.Count > 0) + { + var names = result.SkippedPictures.Select(number => this.slideDeckPicturePaths.TryGetValue(number, out var picturePath) ? Path.GetFileName(picturePath) : number.ToString(CultureInfo.InvariantCulture)); + await this.MessageBus.SendWarning(new(Icons.Material.Filled.HideImage, string.Format(T("These pictures could not be placed, because PowerPoint cannot show their format or they cannot be read: {0}"), string.Join(", ", names)))); + } + + await this.MessageBus.SendSuccess(new(Icons.Material.Filled.Slideshow, T("The PowerPoint file was created."))); + } + catch (Exception e) + { + this.Logger.LogError(e, "Creating the PowerPoint file '{FilePath}' failed.", targetPath); + await this.MessageBus.SendError(new(Icons.Material.Filled.Slideshow, T("The PowerPoint file could not be created. Please check that the template can be read and that the target file is not open in another program."))); + } + finally + { + this.isWritingPresentation = false; + this.StateHasChanged(); + } + } + + /// + /// A slide deck read out of an answer of the model, with what is wrong with it. + /// + /// The deck; null when the answer cannot be read. + /// The issues, written for the model; empty when the deck fits. + private sealed record CheckedAnswer(SlideDeckSpec? Deck, IReadOnlyList Issues); +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Progress.cs b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Progress.cs new file mode 100644 index 000000000..8c49bb937 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.Progress.cs @@ -0,0 +1,60 @@ +using AIStudio.Chat; +using AIStudio.Tools.AssistantSessions; +using AIStudio.Tools.PowerPoint; + +namespace AIStudio.Assistants.SlideBuilder; + +/// +/// The part of the Slide Assistant which tells, below the progress bar, what the LLM is doing while +/// it plans. +/// +/// +/// The answer is JSON, which the assistant does not show. Without these texts, the user would watch +/// a bar for minutes without knowing whether anything happens: the LLM first thinks about the +/// structure, which streams nothing at all, then writes the slides one by one, and may fit them to +/// the layouts in a second round. +/// +public partial class SlideAssistant +{ + private PlanningStep planningStep; + private static readonly AssistantSessionStateKey PLANNING_STEP_STATE_KEY = new(nameof(planningStep)); + + private ContentText? countedAnswer; + private StreamedSlideCounter slideCounter = new(); + + protected override string ProgressText => this.planningStep switch + { + PlanningStep.PLANNING when this.SlidesSoFar() is var slides and > 0 => string.Format(T("The LLM is writing slide {0}..."), slides), + PlanningStep.PLANNING => T("The LLM is planning the structure of the presentation..."), + PlanningStep.REPAIRING => T("The LLM is fitting the slides to the layouts..."), + + _ => string.Empty, + }; + + /// + /// Counts the slides which the answer streaming in has started so far. + /// + private int SlidesSoFar() + { + if (this.ResultingContentBlock?.Content is not ContentText answer) + return 0; + + if (!ReferenceEquals(answer, this.countedAnswer)) + { + this.countedAnswer = answer; + this.slideCounter = new(); + } + + return this.slideCounter.Count(answer.Text); + } + + /// + /// What the LLM is asked to do right now. + /// + private enum PlanningStep + { + NONE, + PLANNING, + REPAIRING, + } +} diff --git a/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.cs b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.cs index 7ebf81e07..9cc3aeddd 100644 --- a/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/SlideBuilder/SlideAssistant.razor.cs @@ -1,7 +1,9 @@ using System.Text; using AIStudio.Chat; using AIStudio.Dialogs.Settings; +using AIStudio.Settings; using AIStudio.Tools.AssistantSessions; +using AIStudio.Tools.PowerPoint; using AIStudio.Tools.Security; namespace AIStudio.Assistants.SlideBuilder; @@ -10,52 +12,77 @@ public partial class SlideAssistant : AssistantBaseCore Tools.Components.SLIDE_BUILDER_ASSISTANT; - protected override string Title => T("Slide Planner Assistant"); + protected override string Title => T("Slide Assistant"); - protected override string Description => T("This assistant helps you create clear, structured slides from long texts or documents. Enter a presentation title and provide the content either as text or with one or more documents. Important aspects allow you to add instructions to the LLM regarding output or formatting. Set the number of slides either directly or based on your desired presentation duration. You can also specify the number of bullet points. If the default value of 0 is not changed, the LLM will independently determine how many slides or bullet points to generate. The output can be flexibly generated in various languages and tailored to a specific audience."); + protected override string Description => T("This assistant helps you create clear, structured slides from long texts or documents. Enter a presentation title and provide the content either as text or with one or more documents. Important aspects allow you to add instructions to the LLM regarding output or formatting. Set the number of slides either directly or based on your desired presentation duration. You can also limit the number of bullet points per slide. If the default value of 0 is not changed, the LLM will independently determine how many slides or bullet points to generate. The output can be flexibly generated in various languages and tailored to a specific audience. When you choose a PowerPoint template, the slides use its layouts, and you can create a PowerPoint file in its design from the result."); protected override string SystemPrompt => $$$""" You are a professional presentation editor and writer. - Create a clear, single-slide outline from the user's inputs. - + Plan a presentation from the user's inputs and describe it slide by slide as JSON, using the slide layouts LAYOUTS lists. + # Presentation title: - IGNORE the language of the PRESENTATION_TITLE. - Translate PRESENTATION_TITLE in: {{{this.selectedTargetLanguage.PromptGeneralPurpose(this.customTargetLanguage)}}} - - # Content - - You get the following inputs: PRESENTATION_TITLE, PRESENTATION_CONTENT, and any attached documents that may provide additional context or source material (DOCUMENTS). - - {{{this.GetDocumentTaskDescription()}}} - {{{this.PromptImportantAspects()}}} - - # Subheadings - - Rule for creating the individual subheadings: - - If {{{this.numberOfSheets}}} is NOT 0 - - Generate exactly {{{this.numberOfSheets}}} precise subheadings, each heading represents one slide in a presentation. - - If {{{this.timeSpecification}}} is NOT 0 - - Generate exactly {{{this.calculatedNumberOfSlides}}} precise subheadings, each heading represents one slide in a presentation. - - If either parameter is 0, ignore that rules. - - Each subheadings must have: - - A clear, concise, and thematically meaningful heading. - - Place *** on its own line immediately before each heading. - - # Bullet points (per subheading) - - You MUST generate exactly this {{{this.numberOfBulletPoints}}} many bullet points per subheading: - - If {{{this.numberOfBulletPoints}}} == 0 → choose a number between 1 and 7 (your choice, but max 7). - - Each bullet point must have: - - Each bullet point must be max 12 words. - - Clear and directly related to the subheading and summarizing the slide’s content. - # Output requirements: - - Output only Markdown. - - Start with a single H1 title that contains the user's PRESENTATION_TITLE. - - Then add headings with own bullet lists based on the provided source material: PRESENTATION_CONTENT, DOCUMENTS, and attached images. + # Content + - You get the following inputs: PRESENTATION_TITLE, PRESENTATION_CONTENT, the layouts the slides use (LAYOUTS), any attached documents (DOCUMENTS) or images that provide source material, and the pictures for the slides (PICTURES). + - Base the slides on the provided source material: PRESENTATION_CONTENT, DOCUMENTS, and attached images. - If both PRESENTATION_CONTENT and attached source material are provided, use all of them, while prioritizing direct user instructions from PRESENTATION_CONTENT when resolving ambiguity. - If PRESENTATION_CONTENT is empty but attached source material is available, create the slides from the attached source material. - - If neither PRESENTATION_CONTENT nor any attached source material is available, output the title and one bullet: "No content provided." + - If neither PRESENTATION_CONTENT nor any attached source material is available, create a single slide with the title and the text "No content provided." + + {{{this.GetDocumentTaskDescription()}}} + {{{this.PromptImportantAspects()}}} + + # Layouts + Every slide uses one of the layouts LAYOUTS lists. A layout offers slots, listed in reading order with their place on the slide and how much text fits. + - Choose for each slide the layout whose slots suit its content, and vary the layouts where the content allows. + - Fill only slots the layout offers, and stay within the stated lines and characters. Spread content over more slides rather than overfilling one. + - A label is a short text, e.g., a heading above a text or the source below a picture. + - Set "starts_chapter" to true on each slide which opens a new part of the presentation. Where a layout is meant for chapters or sections, use it for these slides. + {{{this.PromptChosenLayouts()}}} + {{{this.PromptTemplateSlides()}}} + + # Pictures + {{{this.PromptPictures()}}} + + # Slides + {{{this.PromptSlideCount()}}} + - Every slide has a clear, concise, and thematically meaningful title. + + # Bullet points (per text slot) + {{{this.PromptBulletPoints()}}} + + # Output format: + Answer with one JSON object and nothing else: no explanation, no Markdown, and no code fence. + { + "title": "", + "slides": [ + { + "layout": "", + "starts_chapter": false, + "title": "", + "subtitle": "", + "texts": [["", { "text": "", "level": 1 }]], + "labels": ["