mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-04 20:47:22 +00:00
Added an optional notice for AI-generated content (#884)
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
1 parent
f5a257270e
commit
249fc778a2
26 files changed
+406
-46
No files matched your search
@@ -107,7 +107,7 @@
|
||||
</MudMenu>
|
||||
</MudTooltip>
|
||||
}
|
||||
<MudCopyClipboardButton Content="@this.Content" Type="@this.Type" Size="Size.Medium"/>
|
||||
<MudCopyClipboardButton Content="@this.Content" Type="@this.Type" Size="Size.Medium" IsAIGenerated="@this.GetsAIGeneratedContentDisclosure"/>
|
||||
</div>
|
||||
</CardHeaderActions>
|
||||
</MudCardHeader>
|
||||
|
||||
@@ -123,13 +123,27 @@ public partial class ContentBlockComponent : MSGComponentBase
|
||||
/// </remarks>
|
||||
[Parameter]
|
||||
public string? ExportFileName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether copying or exporting an AI answer of this block ends it with the notice that AI
|
||||
/// generated it, when that is switched on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An assistant whose answer is meant for another model rather than for a reader, such as the
|
||||
/// prompt optimizer, turns this off, the same way as for its "Copy result" button.
|
||||
/// </remarks>
|
||||
[Parameter]
|
||||
public bool AddsAIGeneratedContentDisclosure { get; set; } = true;
|
||||
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private RustService RustService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private AIGeneratedContentDisclosureService DisclosureService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime JsRuntime { get; init; } = null!;
|
||||
|
||||
@@ -165,6 +179,11 @@ public partial class ContentBlockComponent : MSGComponentBase
|
||||
/// </remarks>
|
||||
private bool CanExport => this.Content is { InitialRemoteWait: false, IsStreaming: false } && this.Content.TryGetMarkdownText(out _);
|
||||
|
||||
/// <summary>
|
||||
/// Whether this block leaves AI Studio with the notice that AI generated it, when that is switched on.
|
||||
/// </summary>
|
||||
private bool GetsAIGeneratedContentDisclosure => this.Role is ChatRole.AI && this.AddsAIGeneratedContentDisclosure;
|
||||
|
||||
/// <summary>
|
||||
/// The files this block holds, tables and code blocks, so that the export menu can offer each of them.
|
||||
/// </summary>
|
||||
@@ -755,7 +774,7 @@ public partial class ContentBlockComponent : MSGComponentBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports the entire message.
|
||||
/// Exports the entire message, ending with the notice that AI generated it when that is switched on.
|
||||
/// </summary>
|
||||
private async Task ExportDocument(FileExportFormat format)
|
||||
{
|
||||
@@ -765,10 +784,11 @@ public partial class ContentBlockComponent : MSGComponentBase
|
||||
// The format itself knows who writes it, so we do not have to keep a list of formats
|
||||
// here which would fall out of sync with the one in FileExportFormatExtensions.
|
||||
//
|
||||
var disclosureService = this.GetsAIGeneratedContentDisclosure ? this.DisclosureService : null;
|
||||
if (format.UsesPandoc())
|
||||
await PandocExport.ToDocument(this.RustService, this.PandocAvailability, this.EffectiveExportTitle, format, this.Content, this.ExportFileName);
|
||||
await PandocExport.ToDocument(this.RustService, this.PandocAvailability, disclosureService, this.EffectiveExportTitle, format, this.Content, this.ExportFileName);
|
||||
else if (this.Content.TryGetExportMarkdown(out var markdown))
|
||||
await PlainFileExport.ToFile(this.RustService, this.EffectiveExportTitle, format, markdown, this.ExportFileName);
|
||||
await PlainFileExport.ToFile(this.RustService, this.EffectiveExportTitle, format, disclosureService?.AddDisclosureToMarkdown(markdown) ?? markdown, this.ExportFileName);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException e)
|
||||
{
|
||||
@@ -780,6 +800,11 @@ public partial class ContentBlockComponent : MSGComponentBase
|
||||
/// Exports one file out of the message, along with the sources the answer rests on wherever its
|
||||
/// format has room for them.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Unlike the entire message, the file never gets the notice that AI generated it. It is meant for
|
||||
/// a program as often as for a reader, a table or a web page for instance, and one sentence more
|
||||
/// would break most of them.
|
||||
/// </remarks>
|
||||
private async Task ExportFile(MessageFile file)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -113,19 +113,5 @@ public static class IContentExtensions
|
||||
/// <param name="sources">The source list as SourceExtensions.ToExportMarkdown writes it, or an
|
||||
/// empty string when there are no sources.</param>
|
||||
/// <returns>The text followed by its sources.</returns>
|
||||
private static string AppendSources(string markdown, string sources)
|
||||
{
|
||||
if (sources.Length == 0)
|
||||
return markdown;
|
||||
|
||||
if (markdown.Length == 0)
|
||||
return sources;
|
||||
|
||||
//
|
||||
// The blank line is not cosmetic: it ends a paragraph, a list, a table, or a block quote, so
|
||||
// that the heading of the source list stands on its own instead of being pulled into the
|
||||
// last block of the answer.
|
||||
//
|
||||
return $"{Markdown.CloseOpenCodeFence(markdown)}{Environment.NewLine}{Environment.NewLine}{sources}";
|
||||
}
|
||||
private static string AppendSources(string markdown, string sources) => Markdown.AppendBlock(markdown, sources);
|
||||
}
|
||||
Reference in new issue
Block a user