mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-18 03:17:59 +00:00
Added tool calling support (#731)
Co-authored-by: krut_ni <nils.kruthoff@dlr.de> Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
266 files changed
+11186
-740
No files matched your search
@@ -175,6 +175,12 @@
|
||||
<ProfileSelection MarginLeft="" @bind-CurrentProfile="@this.CurrentProfile"/>
|
||||
}
|
||||
|
||||
@* No selection where the assistant's own rules already name the tools: *@
|
||||
@if (this.SettingsManager.AreToolsEnabled() && this.AssistantManagedToolIds is null && this.SettingsManager.IsToolSelectionVisible(this.Component))
|
||||
{
|
||||
<ToolSelection Component="@this.Component" LLMProvider="@this.ProviderSettings" SelectedToolIds="@this.SelectedToolIds" SelectedToolIdsChanged="@this.SelectedToolIdsChanged" Disabled="@this.IsProcessing" />
|
||||
}
|
||||
|
||||
<MudSpacer />
|
||||
<HalluzinationReminder ContainerClass="my-0 ml-2"/>
|
||||
</MudStack>
|
||||
|
||||
@@ -6,6 +6,7 @@ using AIStudio.Tools.AIJobs;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
using AIStudio.Tools.Media;
|
||||
using AIStudio.Tools.Services;
|
||||
using AIStudio.Tools.ToolCallingSystem;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
@@ -27,6 +28,9 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
[Inject]
|
||||
protected RustService RustService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected ToolRegistry ToolRegistry { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected NavigationManager NavigationManager { get; init; } = null!;
|
||||
@@ -127,8 +131,10 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
protected virtual bool HasSettingsPanel => typeof(TSettings) != typeof(NoSettingsPanel);
|
||||
|
||||
protected HashSet<string> SelectedToolIds = [];
|
||||
|
||||
private readonly Timer formChangeTimer = new(TimeSpan.FromSeconds(1.6));
|
||||
|
||||
|
||||
protected MudForm? Form;
|
||||
protected CancellationTokenSource? CancellationTokenSource;
|
||||
private bool isDisposed;
|
||||
@@ -185,6 +191,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(this.Component);
|
||||
this.CurrentProfile = this.SettingsManager.GetPreselectedProfile(this.Component);
|
||||
this.CurrentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component);
|
||||
this.SelectedToolIds = this.SettingsManager.GetDefaultToolIds(this.Component);
|
||||
await this.OnDefaultsAppliedAsync();
|
||||
this.assistantSessionKey = new(this.Component, this.AssistantSessionInstanceId);
|
||||
await this.AttachAssistantSessionIfAvailable();
|
||||
@@ -236,6 +243,10 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
private async Task Start()
|
||||
{
|
||||
await this.RefreshProviderSelectionFromConfigurationAsync();
|
||||
if (this.ProviderSettings == Settings.Provider.NONE)
|
||||
return;
|
||||
|
||||
if (this.MediaTranscriptionService.IsBusy(this.CurrentMediaImportOwner))
|
||||
return;
|
||||
|
||||
@@ -357,6 +368,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
ChatId = Guid.NewGuid(),
|
||||
Name = string.Format(this.TB("Assistant - {0}"), this.Title),
|
||||
Blocks = [],
|
||||
RuntimeComponent = this.Component,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -373,16 +385,71 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
ChatId = chatId,
|
||||
Name = name,
|
||||
Blocks = [],
|
||||
RuntimeComponent = this.Component,
|
||||
};
|
||||
|
||||
return chatId;
|
||||
}
|
||||
|
||||
private Task RefreshProviderSelectionFromConfigurationAsync()
|
||||
{
|
||||
this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(this.Component, this.ProviderSettings.Id);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected virtual void ResetProviderAndProfileSelection()
|
||||
{
|
||||
this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(this.Component);
|
||||
this.CurrentProfile = this.SettingsManager.GetPreselectedProfile(this.Component);
|
||||
this.CurrentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component);
|
||||
this.SelectedToolIds = this.SettingsManager.GetDefaultToolIds(this.Component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The tools this assistant runs with when its own rules name them, instead of asking the user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Null is the normal case: the user picks the tools. An assistant whose configuration already
|
||||
/// says which tools belong to a run — a document analysis policy, for instance — returns them
|
||||
/// here. Its tool selection then disappears from the footer, because there is nothing left to
|
||||
/// choose: whoever wrote the policy has decided, and a user working with a policy rolled out by
|
||||
/// their organization gets it as configured.
|
||||
/// </remarks>
|
||||
protected virtual IReadOnlySet<string>? AssistantManagedToolIds => null;
|
||||
|
||||
/// <summary>
|
||||
/// The tools this assistant may hand to a model with the provider it currently uses.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Whether the tools come from the assistant's own rules or from the user, the provider filter
|
||||
/// always has the last word: a tool asking for more confidence than the selected provider has
|
||||
/// never reaches the model, no matter who put it on the list. That filter belongs here rather
|
||||
/// than into the stored selection, because a provider with too little confidence must not cost
|
||||
/// the user a tool for good.
|
||||
/// </remarks>
|
||||
protected HashSet<string> GetRunnableToolIds()
|
||||
{
|
||||
if (this.AssistantManagedToolIds is not null)
|
||||
return this.ToolRegistry.FilterToolIdsForProvider(this.ProviderSettings, this.AssistantManagedToolIds);
|
||||
|
||||
// What the user cannot see, the assistant does not use:
|
||||
if (!this.SettingsManager.IsToolSelectionVisible(this.Component))
|
||||
return [];
|
||||
|
||||
return this.ToolRegistry.FilterToolIdsForProvider(this.ProviderSettings, this.SelectedToolIds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes over a changed tool selection, no matter where the user made it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The footer offers one; an assistant may instead put the tools next to the setting they
|
||||
/// belong to, as the batch processing does with its instructions. Both end up here.
|
||||
/// </remarks>
|
||||
protected Task SelectedToolIdsChanged(HashSet<string> updatedToolIds)
|
||||
{
|
||||
this.SelectedToolIds = ToolSelectionRules.NormalizeSelection(updatedToolIds);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected DateTimeOffset AddUserRequest(string request, bool hideContentFromUser = false, params List<FileAttachment> attachments)
|
||||
@@ -443,6 +510,10 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
{
|
||||
this.ChatThread.Blocks.Add(this.ResultingContentBlock);
|
||||
this.ChatThread.SelectedProvider = this.ProviderSettings.Id;
|
||||
this.ChatThread.RuntimeComponent = this.Component;
|
||||
this.ChatThread.SelectedToolIds = [..this.SelectedToolIds];
|
||||
this.ChatThread.RuntimeSelectedToolIds = this.GetRunnableToolIds();
|
||||
this.ChatThread.RuntimeToolsAreAssistantManaged = this.AssistantManagedToolIds is not null;
|
||||
}
|
||||
|
||||
this.IsProcessing = true;
|
||||
@@ -911,6 +982,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
state.Set(RESULTING_CONTENT_BLOCK_STATE_KEY, this.ResultingContentBlock);
|
||||
state.Set(INPUT_ISSUES_STATE_KEY, this.InputIssues);
|
||||
state.Set(IS_PROCESSING_STATE_KEY, this.IsProcessing);
|
||||
state.Set(SELECTED_TOOL_IDS_STATE_KEY, this.SelectedToolIds);
|
||||
this.CaptureCustomAssistantSessionState(state);
|
||||
|
||||
return state.ToDictionary();
|
||||
@@ -938,6 +1010,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
reader.Restore(RESULTING_CONTENT_BLOCK_STATE_KEY, value => this.ResultingContentBlock = value);
|
||||
reader.Restore(INPUT_ISSUES_STATE_KEY, value => this.InputIssues = value);
|
||||
reader.Restore(IS_PROCESSING_STATE_KEY, value => this.IsProcessing = value);
|
||||
reader.Restore(SELECTED_TOOL_IDS_STATE_KEY, value => this.SelectedToolIds = ToolSelectionRules.NormalizeSelection(value));
|
||||
this.RestoreCustomAssistantSessionState(reader);
|
||||
}
|
||||
|
||||
@@ -948,4 +1021,4 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
protected virtual void RestoreCustomAssistantSessionState(AssistantSessionStateReader state) { }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ public abstract class AssistantLowerBase : MSGComponentBase
|
||||
protected static readonly AssistantSessionStateKey<ContentBlock?> RESULTING_CONTENT_BLOCK_STATE_KEY = new(nameof(ResultingContentBlock));
|
||||
protected static readonly AssistantSessionStateKey<string[]> INPUT_ISSUES_STATE_KEY = new(nameof(InputIssues));
|
||||
protected static readonly AssistantSessionStateKey<bool> IS_PROCESSING_STATE_KEY = new(nameof(IsProcessing));
|
||||
protected static readonly AssistantSessionStateKey<HashSet<string>> SELECTED_TOOL_IDS_STATE_KEY = new("SelectedToolIds");
|
||||
|
||||
protected AIStudio.Settings.Provider ProviderSettings = Settings.Provider.NONE;
|
||||
protected bool InputIsValid;
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
<ReadFileContent Text="@T("Load prompt from file")" @bind-FileContent="@this.freePrompt" EnableDragDrop="true" Layer="@DropLayers.ASSISTANTS" CatchAllDocuments="true" Disabled="@this.isProcessingBatch"/>
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.freePrompt" Validation="@this.ValidateFreePrompt" Immediate="@true" Disabled="@this.isProcessingBatch" Label="@T("What should the AI do with each document?")" HelperText="@T("These instructions are applied to every single document of the batch run.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="5" AutoGrow="@true" MaxLines="26" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
|
||||
<ToolSelectionField Component="@this.Component" SelectedToolIds="@this.SelectedToolIds" SelectedToolIdsChanged="@this.SelectedToolIdsChanged" Disabled="@this.isProcessingBatch" Label="@T("Tools for this batch run")" Help="@T("The AI may use these tools while working on each document. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when it is selected here.")"/>
|
||||
}
|
||||
else if (this.promptSource is BatchProcessingPromptSource.FILE_IMPORT)
|
||||
{
|
||||
@@ -65,6 +67,8 @@ else if (this.promptSource is BatchProcessingPromptSource.FILE_IMPORT)
|
||||
<MudJustifiedText Typo="Typo.body2" Class="mb-3">
|
||||
@T("The content of the selected file is used as the instructions for every single document of the batch run.")
|
||||
</MudJustifiedText>
|
||||
|
||||
<ToolSelectionField Component="@this.Component" SelectedToolIds="@this.SelectedToolIds" SelectedToolIdsChanged="@this.SelectedToolIdsChanged" Disabled="@this.isProcessingBatch" Label="@T("Tools for this batch run")" Help="@T("The AI may use these tools while working on each document. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when it is selected here.")"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -99,6 +103,12 @@ else
|
||||
@this.selectedPolicy.PolicyDescription
|
||||
</MudJustifiedText>
|
||||
}
|
||||
|
||||
@* Read-only: the policy decides its tools, and this run follows the policy. *@
|
||||
@if (this.selectedPolicy is not null)
|
||||
{
|
||||
<ToolSelectionField Component="@this.Component" SelectedToolIds="@this.PolicyToolIds" ReadOnly="@true" Label="@T("Tools of this policy")" Help="@T("These tools are part of the selected policy and cannot be changed here. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when the policy permits it.")"/>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +195,15 @@ else
|
||||
</MudAlert>
|
||||
}
|
||||
|
||||
@*
|
||||
Only for a policy run: where the user picks the tools themselves, the selection field already
|
||||
shows what is locked, and they can simply switch a blocked tool off.
|
||||
*@
|
||||
@if (this.promptSource is BatchProcessingPromptSource.POLICY)
|
||||
{
|
||||
<ManagedToolsWarning Component="@this.Component" ToolIds="@this.PolicyToolIds" ProviderSettings="@this.ProviderSettings"/>
|
||||
}
|
||||
|
||||
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProviderWithBatchState" Disabled="@this.isProcessingBatch" ExplicitMinimumConfidence="@this.GetMinimumConfidenceLevel()"/>
|
||||
|
||||
@if (this.fileResults.Count > 0)
|
||||
|
||||
+7
-5
@@ -106,9 +106,9 @@ public partial class AssistantBatchProcessing
|
||||
private async Task WriteLogAsync(string resolvedOutputDirectory)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(CsvWriter.ToRow(LOG_SEPARATOR, T("File"), T("Time"), T("Model"), T("Status"), T("Details")));
|
||||
sb.AppendLine(CsvWriter.ToRow(LOG_SEPARATOR, T("File"), T("Time"), T("Model"), T("Status"), T("Details"), T("Tools used")));
|
||||
foreach (var fileResult in this.fileResults.Where(x => x.Status is not BatchProcessingFileStatus.QUEUED and not BatchProcessingFileStatus.PROCESSING))
|
||||
sb.AppendLine(CsvWriter.ToRow(LOG_SEPARATOR, fileResult.RelativePath, fileResult.ProcessedAt.ToString(TIME_FORMAT, CultureInfo.InvariantCulture), fileResult.ModelName, fileResult.Status.ToString(), fileResult.Message));
|
||||
sb.AppendLine(CsvWriter.ToRow(LOG_SEPARATOR, fileResult.RelativePath, fileResult.ProcessedAt.ToString(TIME_FORMAT, CultureInfo.InvariantCulture), fileResult.ModelName, fileResult.Status.ToString(), fileResult.Message, fileResult.UsedTools));
|
||||
|
||||
await this.WriteCsvFileAsync(Path.Join(resolvedOutputDirectory, LOG_FILENAME), sb.ToString());
|
||||
}
|
||||
@@ -176,7 +176,9 @@ public partial class AssistantBatchProcessing
|
||||
try
|
||||
{
|
||||
var content = await File.ReadAllTextAsync(logFilePath);
|
||||
var rows = BatchProcessingCsv.ParseWithDetectedSeparator(content, 5, LOG_SEPARATOR, '|');
|
||||
// A log written before the tools column existed has five fields. It stays
|
||||
// readable, so that a run started with an earlier version can be continued:
|
||||
var rows = BatchProcessingCsv.ParseWithDetectedSeparator(content, [6, 5], LOG_SEPARATOR, '|');
|
||||
|
||||
// The first row is the header, which we skip:
|
||||
foreach (var row in rows.Skip(1))
|
||||
@@ -184,7 +186,7 @@ public partial class AssistantBatchProcessing
|
||||
if (row.Count < 5 || string.IsNullOrWhiteSpace(row[0]))
|
||||
continue;
|
||||
|
||||
entries[row[0]] = new BatchProcessingLogEntry(row[0], row[1], row[2], row[3], row[4]);
|
||||
entries[row[0]] = new BatchProcessingLogEntry(row[0], row[1], row[2], row[3], row[4], row.Count > 5 ? row[5] : string.Empty);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -213,7 +215,7 @@ public partial class AssistantBatchProcessing
|
||||
|
||||
var content = await File.ReadAllTextAsync(resultsFilePath);
|
||||
var configuredSeparator = this.csvSeparator.Character(this.customCsvSeparator);
|
||||
var rows = BatchProcessingCsv.ParseWithDetectedSeparator(content, 2, configuredSeparator, ';', '|', ',', '\t');
|
||||
var rows = BatchProcessingCsv.ParseWithDetectedSeparator(content, [2], configuredSeparator, ';', '|', ',', '\t');
|
||||
foreach (var row in rows.Skip(1))
|
||||
{
|
||||
if (row.Count < 2 || string.IsNullOrWhiteSpace(row[0]))
|
||||
|
||||
+45
-2
@@ -1,6 +1,7 @@
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools.ToolCallingSystem;
|
||||
|
||||
namespace AIStudio.Assistants.BatchProcessing;
|
||||
|
||||
@@ -86,18 +87,34 @@ public partial class AssistantBatchProcessing
|
||||
""";
|
||||
}
|
||||
|
||||
private async Task<string> CallAIAsync(string fileName, string fileContent, CancellationToken token)
|
||||
/// <param name="fileName">The name of the document being processed.</param>
|
||||
/// <param name="fileContent">The content handed to the model.</param>
|
||||
/// <param name="token">The cancellation token.</param>
|
||||
/// <returns>The answer of the model, and which tools it used to get there.</returns>
|
||||
private async Task<(string Answer, string UsedTools)> CallAIAsync(string fileName, string fileContent, CancellationToken token)
|
||||
{
|
||||
//
|
||||
// Every file of the batch gets the tools the user picked for the job. The batch builds its
|
||||
// own throwaway thread per file instead of going through the assistant's own thread, so it
|
||||
// has to hand the tools over itself.
|
||||
//
|
||||
var chatThread = new ChatThread
|
||||
{
|
||||
IncludeDateTime = false,
|
||||
SelectedProvider = this.ProviderSettings.Id,
|
||||
SelectedProfile = Profile.NO_PROFILE.Id,
|
||||
SelectedToolIds = [..this.SelectedToolIds],
|
||||
SystemPrompt = this.SystemPrompt,
|
||||
WorkspaceId = Guid.Empty,
|
||||
ChatId = Guid.NewGuid(),
|
||||
Name = this.Title,
|
||||
Blocks = [],
|
||||
RuntimeComponent = this.Component,
|
||||
RuntimeSelectedToolIds = this.GetRunnableToolIds(),
|
||||
|
||||
// Always true here, unlike in the assistant base: a batch run takes its tools from the
|
||||
// selected policy or from its own field, never from the tool selection in the footer.
|
||||
RuntimeToolsAreAssistantManaged = true,
|
||||
};
|
||||
|
||||
var userPrompt = new ContentText
|
||||
@@ -123,6 +140,32 @@ public partial class AssistantBatchProcessing
|
||||
});
|
||||
|
||||
await aiText.CreateFromProviderAsync(this.ProviderSettings.CreateProvider(), this.ProviderSettings.Model, userPrompt, chatThread, token);
|
||||
return aiText.Text.RemoveThinkTags().Trim();
|
||||
return (aiText.Text.RemoveThinkTags().Trim(), this.SummarizeToolUsage(aiText));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sums up the tool calls of one document for the log.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Names each tool once with how often it ran, because a model may search
|
||||
/// several times for the same document. A call that failed or was blocked
|
||||
/// is named with its outcome: for judging an answer it matters whether a
|
||||
/// tool delivered or came back empty-handed.
|
||||
/// </remarks>
|
||||
private string SummarizeToolUsage(ContentText aiText) => string.Join(", ", aiText.ToolInvocations
|
||||
.GroupBy(invocation => (invocation.ToolName, invocation.Status))
|
||||
.OrderBy(group => group.Key.ToolName, StringComparer.OrdinalIgnoreCase)
|
||||
.Select(group => this.FormatToolUsage(group.Key.ToolName, group.Key.Status, group.Count())));
|
||||
|
||||
private string FormatToolUsage(string toolName, ToolInvocationTraceStatus status, int count)
|
||||
{
|
||||
var nameWithCount = count > 1 ? $"{toolName} ({count}x)" : toolName;
|
||||
return status switch
|
||||
{
|
||||
ToolInvocationTraceStatus.ERROR => $"{nameWithCount} [{this.T("failed")}]",
|
||||
ToolInvocationTraceStatus.BLOCKED => $"{nameWithCount} [{this.T("blocked")}]",
|
||||
|
||||
_ => nameWithCount,
|
||||
};
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -70,6 +70,7 @@ public partial class AssistantBatchProcessing
|
||||
fileResult.Status = BatchProcessingFileStatus.DONE;
|
||||
fileResult.Message = logEntry.Details;
|
||||
fileResult.ModelName = logEntry.Model;
|
||||
fileResult.UsedTools = logEntry.UsedTools;
|
||||
fileResult.ResultText = previousResults.GetValueOrDefault(relativePath, string.Empty);
|
||||
|
||||
if (DateTimeOffset.TryParseExact(logEntry.Time, TIME_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var processedAt))
|
||||
@@ -194,7 +195,7 @@ public partial class AssistantBatchProcessing
|
||||
string aiAnswer;
|
||||
try
|
||||
{
|
||||
aiAnswer = await this.CallAIAsync(fileResult.FileName, fileContent, token);
|
||||
(aiAnswer, fileResult.UsedTools) = await this.CallAIAsync(fileResult.FileName, fileContent, token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,24 @@ public partial class AssistantBatchProcessing : AssistantBaseCore<SettingsDialog
|
||||
|
||||
protected override Tools.Components Component => Tools.Components.BATCH_PROCESSING_ASSISTANT;
|
||||
|
||||
/// <summary>
|
||||
/// The tools a run uses, taken from wherever the instructions come from.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Never from the footer: the tools belong to the instructions, and that is where they are
|
||||
/// chosen. Working from a document analysis policy means following it, tools included, so
|
||||
/// there is nothing left to pick. With instructions of one's own, the field next to them
|
||||
/// decides.
|
||||
/// </remarks>
|
||||
protected override IReadOnlySet<string> AssistantManagedToolIds => this.promptSource is BatchProcessingPromptSource.POLICY
|
||||
? this.PolicyToolIds
|
||||
: this.SelectedToolIds;
|
||||
|
||||
/// <summary>
|
||||
/// The tools of the selected policy, or none while no policy is selected.
|
||||
/// </summary>
|
||||
private HashSet<string> PolicyToolIds => this.selectedPolicy is null ? [] : [..this.selectedPolicy.AllowedToolIds];
|
||||
|
||||
protected override string Title => T("Batch Processing Assistant");
|
||||
|
||||
protected override string Description => T("Process all documents and media files of a folder in one batch run: documents are converted to Markdown, while audio and video files are transcribed automatically, before their content is sent to the AI along with your instructions. You choose whether each answer is stored as its own Markdown file or whether all answers are collected in one CSV results table. A log records what happened to every file, so a run which was interrupted or produced errors can be continued later. A single failing file never stops the entire run.");
|
||||
|
||||
@@ -99,7 +99,12 @@ public static class BatchProcessingCsv
|
||||
/// content with it. Preferred separators are used as fallbacks for files
|
||||
/// whose first record does not reveal a valid separator.
|
||||
/// </summary>
|
||||
public static List<List<string>> ParseWithDetectedSeparator(string content, int expectedNumFields, params char[] preferredSeparators)
|
||||
/// <remarks>
|
||||
/// Several accepted field counts allow a file written by an earlier version
|
||||
/// to be read as well. The log gained a column, and a run started with the
|
||||
/// previous version must still be continuable.
|
||||
/// </remarks>
|
||||
public static List<List<string>> ParseWithDetectedSeparator(string content, IReadOnlyList<int> acceptedNumFields, params char[] preferredSeparators)
|
||||
{
|
||||
var firstRecord = ReadFirstRecord(content);
|
||||
var candidates = new List<char>();
|
||||
@@ -135,7 +140,7 @@ public static class BatchProcessingCsv
|
||||
foreach (var separator in candidates)
|
||||
{
|
||||
var header = Parse(firstRecord, separator);
|
||||
if (header.Count is 1 && header[0].Count == expectedNumFields)
|
||||
if (header.Count is 1 && acceptedNumFields.Contains(header[0].Count))
|
||||
return Parse(content, separator);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,4 +56,14 @@ public sealed class BatchProcessingFileResult
|
||||
/// The time when the processing of this file finished.
|
||||
/// </summary>
|
||||
public DateTimeOffset ProcessedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The tools the model used for this file, ready to be read in the log.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Recorded per file, because the model decides per document whether it
|
||||
/// needs a tool at all. Without this, a batch run gives no clue why one
|
||||
/// answer is better informed than the next.
|
||||
/// </remarks>
|
||||
public string UsedTools { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -3,7 +3,11 @@ namespace AIStudio.Assistants.BatchProcessing;
|
||||
/// <summary>
|
||||
/// One row of the log of a previous batch run.
|
||||
/// </summary>
|
||||
public sealed record BatchProcessingLogEntry(string RelativePath, string Time, string Model, string Status, string Details)
|
||||
/// <remarks>
|
||||
/// The tools column arrived later than the rest. A log written before it existed
|
||||
/// leaves it empty, which is also what a run without any tool call looks like.
|
||||
/// </remarks>
|
||||
public sealed record BatchProcessingLogEntry(string RelativePath, string Time, string Model, string Status, string Details, string UsedTools = "")
|
||||
{
|
||||
public bool WasSuccessful => string.Equals(this.Status, nameof(BatchProcessingFileStatus.DONE), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
@@ -39,6 +39,7 @@
|
||||
@bind-ProfileId="@this.launcherProfileId"
|
||||
@bind-ChatTemplateId="@this.launcherChatTemplateId"
|
||||
@bind-DataSourceIds="@this.launcherDataSourceIds"
|
||||
@bind-ToolIds="@this.launcherToolIds"
|
||||
ValidateWorkspaceName="@this.ValidateLauncherWorkspaceName"/>
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.PluginSystem.Assistants;
|
||||
using AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||
using AIStudio.Tools.Services;
|
||||
using AIStudio.Tools.ToolCallingSystem;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||
|
||||
@@ -101,6 +102,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
|
||||
private string launcherProfileId = string.Empty;
|
||||
private string launcherChatTemplateId = string.Empty;
|
||||
private IEnumerable<string> launcherDataSourceIds = [];
|
||||
private HashSet<string> launcherToolIds = [];
|
||||
private IEnumerable<AssistantComponentType> selectedAssistantComponents = [];
|
||||
private CommonLanguages selectedOutputLanguage = CommonLanguages.AS_IS;
|
||||
private string customOutputLanguage = string.Empty;
|
||||
@@ -138,6 +140,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
|
||||
private static readonly AssistantSessionStateKey<string> LAUNCHER_PROFILE_ID_STATE_KEY = new(nameof(launcherProfileId));
|
||||
private static readonly AssistantSessionStateKey<string> LAUNCHER_CHAT_TEMPLATE_ID_STATE_KEY = new(nameof(launcherChatTemplateId));
|
||||
private static readonly AssistantSessionStateKey<List<string>> LAUNCHER_DATA_SOURCE_IDS_STATE_KEY = new(nameof(launcherDataSourceIds));
|
||||
private static readonly AssistantSessionStateKey<HashSet<string>> LAUNCHER_TOOL_IDS_STATE_KEY = new(nameof(launcherToolIds));
|
||||
private static readonly AssistantSessionStateKey<List<AssistantComponentType>> SELECTED_ASSISTANT_COMPONENTS_STATE_KEY = new(nameof(selectedAssistantComponents));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_OUTPUT_LANGUAGE_STATE_KEY = new(nameof(selectedOutputLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_OUTPUT_LANGUAGE_STATE_KEY = new(nameof(customOutputLanguage));
|
||||
@@ -243,6 +246,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
|
||||
this.launcherProfileId = string.Empty;
|
||||
this.launcherChatTemplateId = string.Empty;
|
||||
this.launcherDataSourceIds = [];
|
||||
this.launcherToolIds = [];
|
||||
this.selectedAssistantComponents = [];
|
||||
this.selectedOutputLanguage = CommonLanguages.AS_IS;
|
||||
this.customOutputLanguage = string.Empty;
|
||||
@@ -279,6 +283,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
|
||||
state.Set(LAUNCHER_PROFILE_ID_STATE_KEY, this.launcherProfileId);
|
||||
state.Set(LAUNCHER_CHAT_TEMPLATE_ID_STATE_KEY, this.launcherChatTemplateId);
|
||||
state.SetList(LAUNCHER_DATA_SOURCE_IDS_STATE_KEY, this.launcherDataSourceIds);
|
||||
state.SetHashSet(LAUNCHER_TOOL_IDS_STATE_KEY, this.launcherToolIds);
|
||||
state.SetList(SELECTED_ASSISTANT_COMPONENTS_STATE_KEY, this.selectedAssistantComponents);
|
||||
state.Set(SELECTED_OUTPUT_LANGUAGE_STATE_KEY, this.selectedOutputLanguage);
|
||||
state.Set(CUSTOM_OUTPUT_LANGUAGE_STATE_KEY, this.customOutputLanguage);
|
||||
@@ -320,6 +325,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
|
||||
state.Restore(LAUNCHER_PROFILE_ID_STATE_KEY, value => this.launcherProfileId = value);
|
||||
state.Restore(LAUNCHER_CHAT_TEMPLATE_ID_STATE_KEY, value => this.launcherChatTemplateId = value);
|
||||
state.Restore(LAUNCHER_DATA_SOURCE_IDS_STATE_KEY, value => this.launcherDataSourceIds = value);
|
||||
state.Restore(LAUNCHER_TOOL_IDS_STATE_KEY, value => this.launcherToolIds = ToolSelectionRules.NormalizeSelection(value));
|
||||
state.Restore(SELECTED_ASSISTANT_COMPONENTS_STATE_KEY, value => this.selectedAssistantComponents = value);
|
||||
state.Restore(SELECTED_OUTPUT_LANGUAGE_STATE_KEY, value => this.selectedOutputLanguage = value);
|
||||
state.Restore(CUSTOM_OUTPUT_LANGUAGE_STATE_KEY, value => this.customOutputLanguage = value);
|
||||
@@ -543,12 +549,14 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
|
||||
return null;
|
||||
|
||||
var dataSourceIds = this.launcherDataSourceIds.Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
var toolIds = ToolSelectionRules.NormalizeSelection(this.launcherToolIds).ToArray();
|
||||
return new(
|
||||
this.launcherWorkspaceName.Trim(),
|
||||
NullIfEmpty(this.launcherProviderId),
|
||||
NullIfEmpty(this.launcherProfileId),
|
||||
NullIfEmpty(this.launcherChatTemplateId),
|
||||
dataSourceIds.Length == 0 ? null : dataSourceIds);
|
||||
dataSourceIds.Length == 0 ? null : dataSourceIds,
|
||||
toolIds.Length == 0 ? null : toolIds);
|
||||
}
|
||||
|
||||
private void CreateChatLauncherChanged(bool createLauncher)
|
||||
|
||||
@@ -8,5 +8,6 @@ internal sealed class AssistantBuilderAssistantMetadata
|
||||
public string? SystemPrompt { get; init; }
|
||||
public string? SubmitText { get; init; }
|
||||
public bool? AllowAiStudioProfiles { get; init; }
|
||||
public string[]? ToolIds { get; init; }
|
||||
public AssistantBuilderChatLaunchMetadata? Launch { get; init; }
|
||||
}
|
||||
@@ -7,4 +7,5 @@ internal sealed class AssistantBuilderChatLaunchMetadata
|
||||
public string? ProfileId { get; init; }
|
||||
public string? ChatTemplateId { get; init; }
|
||||
public string[]? DataSourceIds { get; init; }
|
||||
public string[]? ToolIds { get; init; }
|
||||
}
|
||||
@@ -90,6 +90,15 @@
|
||||
},
|
||||
"allow_ai_studio_profiles": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"tool_ids": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -156,6 +165,15 @@
|
||||
"const": "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tool_ids": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace AIStudio.Assistants.Builder;
|
||||
|
||||
/// <summary>
|
||||
/// The three texts a model writes for a direct chat launcher.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A launcher has no system prompt, no form, and no prompt builder, and its chat settings come
|
||||
/// straight from the Builder form. That leaves nothing for a model to write except the names a
|
||||
/// person reads, so it is asked for those alone and AI Studio writes the plugin.lua itself.
|
||||
/// </remarks>
|
||||
internal sealed class LauncherTextsResponse
|
||||
{
|
||||
public const string SCHEMA_VERSION_VALUE = "assistant_builder_launcher_texts_v1";
|
||||
|
||||
private static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
AllowTrailingCommas = false,
|
||||
ReadCommentHandling = JsonCommentHandling.Disallow,
|
||||
MaxDepth = 8,
|
||||
};
|
||||
|
||||
public string SchemaVersion { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The plugin name, shown on the plugins page.
|
||||
/// </summary>
|
||||
public string PluginName { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The title on the tile.
|
||||
/// </summary>
|
||||
public string Title { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The short description, used for both the plugin and the tile.
|
||||
/// </summary>
|
||||
public string Description { get; init; } = string.Empty;
|
||||
|
||||
public static bool TryParse(string modelResponse, out LauncherTextsResponse response, out LuaResponseParseError error, out string technicalDetails)
|
||||
{
|
||||
response = new();
|
||||
error = LuaResponseParseError.NONE;
|
||||
technicalDetails = string.Empty;
|
||||
|
||||
var json = LuaResponse.ExtractJson(modelResponse);
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
{
|
||||
error = LuaResponseParseError.MISSING_JSON_OBJECT;
|
||||
return false;
|
||||
}
|
||||
|
||||
LauncherTextsResponse? parsed;
|
||||
try
|
||||
{
|
||||
parsed = JsonSerializer.Deserialize<LauncherTextsResponse>(json, JSON_OPTIONS);
|
||||
}
|
||||
catch (JsonException e)
|
||||
{
|
||||
error = LuaResponseParseError.INVALID_JSON;
|
||||
technicalDetails = e.Message;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parsed is null)
|
||||
{
|
||||
error = LuaResponseParseError.EMPTY_JSON_OBJECT;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!string.Equals(parsed.SchemaVersion, SCHEMA_VERSION_VALUE, StringComparison.Ordinal))
|
||||
{
|
||||
error = LuaResponseParseError.UNSUPPORTED_SCHEMA_VERSION;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(parsed.PluginName) ||
|
||||
string.IsNullOrWhiteSpace(parsed.Title) ||
|
||||
string.IsNullOrWhiteSpace(parsed.Description))
|
||||
{
|
||||
error = LuaResponseParseError.INCOMPLETE_ASSISTANT_METADATA;
|
||||
return false;
|
||||
}
|
||||
|
||||
response = parsed;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -109,10 +109,15 @@ internal sealed partial class LuaResponse
|
||||
"FORM" => !string.IsNullOrWhiteSpace(assistant.SystemPrompt) &&
|
||||
!string.IsNullOrWhiteSpace(assistant.SubmitText) &&
|
||||
assistant.AllowAiStudioProfiles.HasValue &&
|
||||
IsValidToolIds(assistant.ToolIds) &&
|
||||
assistant.Launch is null,
|
||||
|
||||
// A launcher names its tools inside launch, so the same field one level up would be a
|
||||
// second, competing selection:
|
||||
"CHAT_LAUNCHER" => assistant.SystemPrompt is null &&
|
||||
assistant.SubmitText is null &&
|
||||
assistant.AllowAiStudioProfiles is null &&
|
||||
assistant.ToolIds is null &&
|
||||
IsValidChatLaunchMetadata(assistant.Launch),
|
||||
_ => false,
|
||||
};
|
||||
@@ -127,16 +132,36 @@ internal sealed partial class LuaResponse
|
||||
!IsOptionalGuid(launch.ChatTemplateId, allowEmpty: true))
|
||||
return false;
|
||||
|
||||
return launch.DataSourceIds is null ||
|
||||
launch.DataSourceIds.Length > 0 &&
|
||||
launch.DataSourceIds.All(id => Guid.TryParse(id, out var parsed) && parsed != Guid.Empty) &&
|
||||
launch.DataSourceIds.Distinct(StringComparer.OrdinalIgnoreCase).Count() == launch.DataSourceIds.Length;
|
||||
if (launch.DataSourceIds is not null &&
|
||||
(launch.DataSourceIds.Length == 0 ||
|
||||
!launch.DataSourceIds.All(id => Guid.TryParse(id, out var parsed) && parsed != Guid.Empty) ||
|
||||
launch.DataSourceIds.Distinct(StringComparer.OrdinalIgnoreCase).Count() != launch.DataSourceIds.Length))
|
||||
return false;
|
||||
|
||||
return IsValidToolIds(launch.ToolIds);
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// Tool IDs are plain names, so only their shape can be checked here. Whether the named tools
|
||||
/// exist is decided later, against the tools this AI Studio actually has.
|
||||
/// </remarks>
|
||||
private static bool IsValidToolIds(string[]? toolIds) =>
|
||||
toolIds is null ||
|
||||
toolIds.Length > 0 &&
|
||||
toolIds.All(id => !string.IsNullOrWhiteSpace(id)) &&
|
||||
toolIds.Distinct(StringComparer.Ordinal).Count() == toolIds.Length;
|
||||
|
||||
private static bool IsOptionalGuid(string? value, bool allowEmpty) => value is null ||
|
||||
Guid.TryParse(value, out var parsed) && (allowEmpty || parsed != Guid.Empty);
|
||||
|
||||
private static string ExtractJson(string input)
|
||||
/// <summary>
|
||||
/// Reads the first complete JSON object out of a model answer that may carry text around it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
internal static string ExtractJson(string input)
|
||||
{
|
||||
var start = input.IndexOf('{');
|
||||
if (start < 0)
|
||||
|
||||
@@ -13,26 +13,4 @@ public enum LuaResponseParseError
|
||||
INCOMPLETE_ASSISTANT_METADATA,
|
||||
MISSING_LUA,
|
||||
LUA_MISSING_ID,
|
||||
}
|
||||
|
||||
public static class LuaResponseParseErrorExtension
|
||||
{
|
||||
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(LuaResponseParseErrorExtension).Namespace, nameof(LuaResponseParseErrorExtension));
|
||||
|
||||
public static string GetMessage(this LuaResponseParseError parseError, string technicalDetails) => parseError switch
|
||||
{
|
||||
LuaResponseParseError.MISSING_JSON_OBJECT => TB("The model response is missing or unreadable."),
|
||||
LuaResponseParseError.INVALID_JSON => string.IsNullOrWhiteSpace(technicalDetails)
|
||||
? TB("The model returned an invalid response.")
|
||||
: string.Format(TB("The model returned an invalid response: {0}"), technicalDetails),
|
||||
LuaResponseParseError.EMPTY_JSON_OBJECT => TB("The model returned an empty JSON object."),
|
||||
LuaResponseParseError.UNSUPPORTED_SCHEMA_VERSION => TB("The model responded with an unsupported or deprecated JSON schema."),
|
||||
LuaResponseParseError.MISSING_PLUGIN_METADATA => TB("The model's answer is missing the plugin metadata."),
|
||||
LuaResponseParseError.MISSING_ASSISTANT_METADATA => TB("The model's answer is missing the assistant metadata."),
|
||||
LuaResponseParseError.INCOMPLETE_PLUGIN_METADATA => TB("The model's answer contains incomplete plugin metadata."),
|
||||
LuaResponseParseError.INCOMPLETE_ASSISTANT_METADATA => TB("The model's answer contains incomplete assistant metadata."),
|
||||
LuaResponseParseError.MISSING_LUA => TB("The model response does not contain the generated Lua plugin code."),
|
||||
LuaResponseParseError.LUA_MISSING_ID => TB("The generated Lua plugin code does not contain a readable plugin ID."),
|
||||
_ => TB("The model returned an unusable JSON response."),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace AIStudio.Assistants.Builder;
|
||||
|
||||
public static class LuaResponseParseErrorExtension
|
||||
{
|
||||
private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(LuaResponseParseError).Namespace, nameof(LuaResponseParseError));
|
||||
|
||||
public static string GetMessage(this LuaResponseParseError parseError, string technicalDetails) => parseError switch
|
||||
{
|
||||
LuaResponseParseError.MISSING_JSON_OBJECT => TB("The model response is missing or unreadable."),
|
||||
LuaResponseParseError.INVALID_JSON => string.IsNullOrWhiteSpace(technicalDetails)
|
||||
? TB("The model returned an invalid response.")
|
||||
: string.Format(TB("The model returned an invalid response: {0}"), technicalDetails),
|
||||
LuaResponseParseError.EMPTY_JSON_OBJECT => TB("The model returned an empty JSON object."),
|
||||
LuaResponseParseError.UNSUPPORTED_SCHEMA_VERSION => TB("The model responded with an unsupported or deprecated JSON schema."),
|
||||
LuaResponseParseError.MISSING_PLUGIN_METADATA => TB("The model's answer is missing the plugin metadata."),
|
||||
LuaResponseParseError.MISSING_ASSISTANT_METADATA => TB("The model's answer is missing the assistant metadata."),
|
||||
LuaResponseParseError.INCOMPLETE_PLUGIN_METADATA => TB("The model's answer contains incomplete plugin metadata."),
|
||||
LuaResponseParseError.INCOMPLETE_ASSISTANT_METADATA => TB("The model's answer contains incomplete assistant metadata."),
|
||||
LuaResponseParseError.MISSING_LUA => TB("The model response does not contain the generated Lua plugin code."),
|
||||
LuaResponseParseError.LUA_MISSING_ID => TB("The generated Lua plugin code does not contain a readable plugin ID."),
|
||||
_ => TB("The model returned an unusable JSON response."),
|
||||
};
|
||||
}
|
||||
@@ -106,7 +106,9 @@ else
|
||||
|
||||
<ConfigurationMinConfidenceSelection Disabled="@(() => this.IsNoPolicySelectedOrProtected)" RestrictToGlobalMinimumConfidence="true" SelectedValue="@(() => this.policyMinimumProviderConfidence)" SelectionUpdateAsync="@(async level => await this.PolicyMinimumConfidenceWasChangedAsync(level))" />
|
||||
|
||||
<ConfigurationProviderSelection Component="Components.DOCUMENT_ANALYSIS_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => this.IsNoPolicySelectedOrProtected)" SelectedValue="@(() => this.policyPreselectedProviderId)" SelectionUpdate="@(providerId => this.PolicyPreselectedProviderWasChanged(providerId))" ExplicitMinimumConfidence="@this.GetPolicyMinimumConfidenceLevel()"/>
|
||||
<ToolSelectionField Component="@this.Component" SelectedToolIds="@this.policyAllowedToolIds" SelectedToolIdsChanged="@this.PolicyAllowedToolsWasChangedAsync" Disabled="@this.IsNoPolicySelectedOrProtected" Label="@T("Tools this policy permits")" Help="@T("Only the tools selected here can be used by the AI for an analysis with this policy. Every tool still has to meet the confidence requirements of the selected provider, so a tool may remain unavailable even when this policy permits it.")"/>
|
||||
|
||||
<ConfigurationProviderSelection Component="Components.DOCUMENT_ANALYSIS_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => this.IsNoPolicySelectedOrProtected)" SelectedValue="@(() => this.policyPreselectedProviderId)" SelectionUpdate="@this.PolicyPreselectedProviderWasChanged" ExplicitMinimumConfidence="@this.GetPolicyMinimumConfidenceLevel()"/>
|
||||
|
||||
<ConfigurationSelect OptionDescription="@T("Preselect a profile")" Disabled="@(() => this.IsNoPolicySelected)" SelectedValue="@(() => this.policyPreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetComponentProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdateAsync="@(async selection => await this.PolicyPreselectedProfileWasChangedAsync(selection))" OptionHelp="@T("Choose whether the policy should use the app default profile, no profile, or a specific profile.")"/>
|
||||
|
||||
@@ -170,4 +172,7 @@ else
|
||||
</MudExpansionPanels>
|
||||
}
|
||||
|
||||
@* The warning sits right at the provider selection, because choosing another provider resolves it: *@
|
||||
<ManagedToolsWarning Component="@this.Component" ToolIds="@this.policyAllowedToolIds" ProviderSettings="@this.ProviderSettings"/>
|
||||
|
||||
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider" ExplicitMinimumConfidence="@this.GetPolicyMinimumConfidenceLevel()"/>
|
||||
+72
-4
@@ -23,7 +23,18 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
protected override Tools.Components Component => Tools.Components.DOCUMENT_ANALYSIS_ASSISTANT;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The policy decides which tools its analysis uses; the user does not pick them.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Two ways of working, one answer: someone writing a policy for themselves settles the tools
|
||||
/// while writing it, and a policy rolled out by an organization arrives ready to use, with the
|
||||
/// tools its authors tested it with. Either way there is nothing left for the user to switch,
|
||||
/// which is why the tool selection does not appear in this assistant.
|
||||
/// </remarks>
|
||||
protected override IReadOnlySet<string> AssistantManagedToolIds => this.policyAllowedToolIds;
|
||||
|
||||
protected override string Title => T("Document Analysis Assistant");
|
||||
|
||||
protected override string Description => T("The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted.");
|
||||
@@ -178,6 +189,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
this.policyAnalysisRules = string.Empty;
|
||||
this.policyOutputRules = string.Empty;
|
||||
this.policyMinimumProviderConfidence = ConfidenceLevel.NONE;
|
||||
this.policyAllowedToolIds = [];
|
||||
this.policyPreselectedProviderId = string.Empty;
|
||||
this.policyPreselectedProfile = ProfilePreselection.NoProfile;
|
||||
}
|
||||
@@ -205,6 +217,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
this.policyAnalysisRules = this.selectedPolicy.AnalysisRules;
|
||||
this.policyOutputRules = this.selectedPolicy.OutputRules;
|
||||
this.policyMinimumProviderConfidence = this.selectedPolicy.MinimumProviderConfidence;
|
||||
this.policyAllowedToolIds = [..this.selectedPolicy.AllowedToolIds];
|
||||
this.policyPreselectedProviderId = this.selectedPolicy.PreselectedProvider;
|
||||
this.policyPreselectedProfile = ProfilePreselection.FromStoredValue(this.selectedPolicy.PreselectedProfile);
|
||||
|
||||
@@ -262,6 +275,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
this.selectedPolicy.AnalysisRules = this.policyAnalysisRules;
|
||||
this.selectedPolicy.OutputRules = this.policyOutputRules;
|
||||
this.selectedPolicy.MinimumProviderConfidence = this.policyMinimumProviderConfidence;
|
||||
this.selectedPolicy.AllowedToolIds = [..this.policyAllowedToolIds];
|
||||
}
|
||||
|
||||
await this.SettingsManager.StoreSettings();
|
||||
@@ -276,6 +290,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
private string policyAnalysisRules = string.Empty;
|
||||
private string policyOutputRules = string.Empty;
|
||||
private ConfidenceLevel policyMinimumProviderConfidence = ConfidenceLevel.NONE;
|
||||
private HashSet<string> policyAllowedToolIds = [];
|
||||
private string policyPreselectedProviderId = string.Empty;
|
||||
private ProfilePreselection policyPreselectedProfile = ProfilePreselection.NoProfile;
|
||||
private HashSet<FileAttachment> loadedDocumentPaths = [];
|
||||
@@ -528,6 +543,15 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
return this.SettingsManager.GetAppPreselectedProfile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes over the tools this policy permits.
|
||||
/// </summary>
|
||||
private async Task PolicyAllowedToolsWasChangedAsync(HashSet<string> allowedToolIds)
|
||||
{
|
||||
this.policyAllowedToolIds = allowedToolIds;
|
||||
await this.AutoSave();
|
||||
}
|
||||
|
||||
private async Task PolicyMinimumConfidenceWasChangedAsync(ConfidenceLevel level)
|
||||
{
|
||||
this.policyMinimumProviderConfidence = level;
|
||||
@@ -813,10 +837,26 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
}
|
||||
|
||||
await this.AutoSave();
|
||||
await this.Form!.Validate();
|
||||
if (!this.InputIsValid)
|
||||
|
||||
//
|
||||
// Only what the export actually writes is checked. Validating the whole form would demand
|
||||
// a selected provider, which the export does not contain: it describes the policy, not the
|
||||
// way one user happens to run it.
|
||||
//
|
||||
var policyIssues = this.GetPolicyExportIssues();
|
||||
if (policyIssues.Count > 0)
|
||||
{
|
||||
await this.MessageBus.SendError(new (Icons.Material.Filled.Policy, this.T("The selected policy contains invalid data. Please fix the issues before exporting the policy.")));
|
||||
//
|
||||
// Name the issues in both places. A message saying only that something is invalid
|
||||
// leaves the user searching a long form, and leaves us without a clue in the log:
|
||||
//
|
||||
this.Logger.LogWarning(
|
||||
"Was not able to export the document analysis policy '{PolicyName}'. It has {IssueCount} validation issue(s): {Issues}",
|
||||
this.selectedPolicy?.PolicyName,
|
||||
policyIssues.Count,
|
||||
string.Join(" | ", policyIssues));
|
||||
|
||||
await this.MessageBus.SendError(new (Icons.Material.Filled.Policy, $"{this.T("The selected policy contains invalid data. Please fix the issues before exporting the policy.")} {string.Join(" ", policyIssues)}"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -824,6 +864,27 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
await this.RustService.CopyText2Clipboard(luaCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the fields the export writes, using the same rules the form applies to them.
|
||||
/// </summary>
|
||||
private List<string> GetPolicyExportIssues()
|
||||
{
|
||||
List<string> issues = [];
|
||||
foreach (var issue in new[]
|
||||
{
|
||||
this.ValidatePolicyName(this.policyName),
|
||||
this.ValidatePolicyDescription(this.policyDescription),
|
||||
this.ValidateAnalysisRules(this.policyAnalysisRules),
|
||||
this.ValidateOutputRules(this.policyOutputRules),
|
||||
})
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(issue))
|
||||
issues.Add(issue);
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
private string GenerateLuaPolicyExport()
|
||||
{
|
||||
if(this.selectedPolicy is null)
|
||||
@@ -832,6 +893,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
var preselectedProvider = string.IsNullOrWhiteSpace(this.selectedPolicy.PreselectedProvider) ? string.Empty : this.selectedPolicy.PreselectedProvider;
|
||||
var preselectedProfile = string.IsNullOrWhiteSpace(this.selectedPolicy.PreselectedProfile) ? string.Empty : this.selectedPolicy.PreselectedProfile;
|
||||
var id = string.IsNullOrWhiteSpace(this.selectedPolicy.Id) ? Guid.NewGuid().ToString() : this.selectedPolicy.Id;
|
||||
var allowedToolIds = string.Join(", ", this.selectedPolicy.AllowedToolIds.OrderBy(x => x, StringComparer.Ordinal).Select(x => LuaTools.ToLuaStringLiteral(x)));
|
||||
|
||||
return $$"""
|
||||
CONFIG["DOCUMENT_ANALYSIS_POLICIES"][#CONFIG["DOCUMENT_ANALYSIS_POLICIES"]+1] = {
|
||||
@@ -847,6 +909,12 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
-- Allowed values are: NONE, VERY_LOW, LOW, MODERATE, MEDIUM, HIGH
|
||||
["MinimumProviderConfidence"] = "{{this.selectedPolicy.MinimumProviderConfidence}}",
|
||||
|
||||
-- The tools an analysis with this policy may use, by tool ID.
|
||||
-- This is a limit, not a preselection: a tool which is not listed here cannot
|
||||
-- be used for this policy. An empty list means no tools. A listed tool must
|
||||
-- still meet the confidence requirements of the provider in use.
|
||||
["AllowedToolIds"] = { {{allowedToolIds}} },
|
||||
|
||||
-- Optional: preselect a provider or profile by ID.
|
||||
-- The IDs must exist in CONFIG["LLM_PROVIDERS"] or CONFIG["PROFILES"].
|
||||
["PreselectedProvider"] = "{{preselectedProvider}}",
|
||||
|
||||
@@ -35,6 +35,19 @@ else
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
@*
|
||||
The plugin names the tools, so there is nothing for the user to switch on or off. What is
|
||||
left is to say which tools run here, and to warn when the selected provider keeps one of
|
||||
them out of reach.
|
||||
*@
|
||||
@if (this.assistantToolIds is { Count: > 0 } toolIds && this.SettingsManager.AreToolsEnabled())
|
||||
{
|
||||
<MudPaper Class="pa-4 ma-4" Elevation="0">
|
||||
<ManagedToolsWarning Component="@this.Component" ToolIds="@toolIds" ProviderSettings="@this.ProviderSettings"/>
|
||||
<ToolSelectionField Component="@this.Component" SelectedToolIds="@toolIds" ReadOnly="@true" Label="@T("Tools of this assistant")" Help="@T("The author of this assistant chose these tools, so they cannot be changed here. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when this assistant names it.")"/>
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
@foreach (var component in this.RootComponent.Children)
|
||||
{
|
||||
@this.RenderComponent(component)
|
||||
|
||||
@@ -9,6 +9,7 @@ using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.PluginSystem.Assistants;
|
||||
using AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||
using AIStudio.Tools.Services;
|
||||
using AIStudio.Tools.ToolCallingSystem;
|
||||
using Lua;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
@@ -34,6 +35,13 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
protected override bool ShowProfileSelection => this.showFooterProfileSelection;
|
||||
protected override string SubmitText => this.submitText;
|
||||
protected override Func<Task> SubmitAction => this.Submit;
|
||||
|
||||
/// <remarks>
|
||||
/// A plugin that names its tools has decided for the user: its author wrote and tested the
|
||||
/// assistant with exactly these. Null keeps the footer selection for every other plugin.
|
||||
/// </remarks>
|
||||
protected override IReadOnlySet<string>? AssistantManagedToolIds => this.assistantToolIds;
|
||||
|
||||
protected override bool SubmitDisabled => this.isSecurityBlocked;
|
||||
// Dynamic assistants do not have dedicated settings yet. Their internal identity keeps their
|
||||
// session and media state separate while ComponentsExtensions derives their defaults from chat.
|
||||
@@ -50,6 +58,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
private bool allowProfiles = true;
|
||||
private string submitText = string.Empty;
|
||||
private bool showFooterProfileSelection = true;
|
||||
private HashSet<string>? assistantToolIds;
|
||||
private PluginAssistants? assistantPlugin;
|
||||
|
||||
private readonly AssistantState assistantState = new();
|
||||
@@ -69,6 +78,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
private static readonly AssistantSessionStateKey<bool> ALLOW_PROFILES_STATE_KEY = new(nameof(allowProfiles));
|
||||
private static readonly AssistantSessionStateKey<string> SUBMIT_TEXT_STATE_KEY = new(nameof(submitText));
|
||||
private static readonly AssistantSessionStateKey<bool> SHOW_FOOTER_PROFILE_SELECTION_STATE_KEY = new(nameof(showFooterProfileSelection));
|
||||
private static readonly AssistantSessionStateKey<HashSet<string>?> ASSISTANT_TOOL_IDS_STATE_KEY = new(nameof(assistantToolIds));
|
||||
private static readonly AssistantSessionStateKey<PluginAssistants?> ASSISTANT_PLUGIN_STATE_KEY = new(nameof(assistantPlugin));
|
||||
private static readonly AssistantSessionStateKey<AssistantState> ASSISTANT_STATE_STATE_KEY = new(nameof(assistantState));
|
||||
private static readonly AssistantSessionStateKey<Dictionary<string, string>> IMAGE_CACHE_STATE_KEY = new(nameof(imageCache));
|
||||
@@ -90,6 +100,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
state.Set(ALLOW_PROFILES_STATE_KEY, this.allowProfiles);
|
||||
state.Set(SUBMIT_TEXT_STATE_KEY, this.submitText);
|
||||
state.Set(SHOW_FOOTER_PROFILE_SELECTION_STATE_KEY, this.showFooterProfileSelection);
|
||||
state.Set(ASSISTANT_TOOL_IDS_STATE_KEY, this.assistantToolIds);
|
||||
state.Set(ASSISTANT_PLUGIN_STATE_KEY, this.assistantPlugin);
|
||||
state.Set(ASSISTANT_STATE_STATE_KEY, this.assistantState.Clone());
|
||||
state.SetDictionary(IMAGE_CACHE_STATE_KEY, this.imageCache);
|
||||
@@ -110,6 +121,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
state.Restore(ALLOW_PROFILES_STATE_KEY, value => this.allowProfiles = value);
|
||||
state.Restore(SUBMIT_TEXT_STATE_KEY, value => this.submitText = value);
|
||||
state.Restore(SHOW_FOOTER_PROFILE_SELECTION_STATE_KEY, value => this.showFooterProfileSelection = value);
|
||||
state.Restore(ASSISTANT_TOOL_IDS_STATE_KEY, value => this.assistantToolIds = value);
|
||||
state.Restore(ASSISTANT_PLUGIN_STATE_KEY, value => this.assistantPlugin = value);
|
||||
state.Restore(ASSISTANT_STATE_STATE_KEY, value => this.assistantState.CopyFrom(value));
|
||||
state.RestoreDictionary(IMAGE_CACHE_STATE_KEY, this.imageCache);
|
||||
@@ -159,6 +171,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
this.systemPrompt = pluginAssistant.SystemPrompt;
|
||||
this.submitText = pluginAssistant.SubmitText;
|
||||
this.allowProfiles = pluginAssistant.AllowProfiles;
|
||||
this.assistantToolIds = ReadPluginToolIds(pluginAssistant);
|
||||
this.showFooterProfileSelection = !pluginAssistant.HasEmbeddedProfileSelection;
|
||||
this.pluginPath = pluginAssistant.PluginPath;
|
||||
var pluginHash = pluginAssistant.ComputeAuditHash();
|
||||
@@ -353,6 +366,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
this.systemPrompt = updatedPlugin.SystemPrompt;
|
||||
this.submitText = updatedPlugin.SubmitText;
|
||||
this.allowProfiles = updatedPlugin.AllowProfiles;
|
||||
this.assistantToolIds = ReadPluginToolIds(updatedPlugin);
|
||||
this.showFooterProfileSelection = !updatedPlugin.HasEmbeddedProfileSelection;
|
||||
this.pluginPath = updatedPlugin.PluginPath;
|
||||
var pluginHash = updatedPlugin.ComputeAuditHash();
|
||||
@@ -369,6 +383,16 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Reads the tools this plugin names for its assistant.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An ID this installation does not know stays in the set on purpose: the tool may arrive with
|
||||
/// a plugin installed later, and dropping it here would silently turn a plugin that names tools
|
||||
/// into one that lets the user choose.
|
||||
/// </remarks>
|
||||
private static HashSet<string>? ReadPluginToolIds(PluginAssistants plugin) => plugin.AssistantToolIds is { } toolIds ? ToolSelectionRules.NormalizeSelection(toolIds) : null;
|
||||
|
||||
private string ResolveImageSource(AssistantImage image)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(image.Src))
|
||||
|
||||
@@ -343,6 +343,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING
|
||||
-- Name of the results table (optional)
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T1127380661"] = "Name of the results table (optional)"
|
||||
|
||||
-- These tools are part of the selected policy and cannot be changed here. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when the policy permits it.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T1133257227"] = "These tools are part of the selected policy and cannot be changed here. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when the policy permits it."
|
||||
|
||||
-- Your organization requires a pause of at least {0} seconds between files.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T1155517317"] = "Your organization requires a pause of at least {0} seconds between files."
|
||||
|
||||
@@ -391,6 +394,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING
|
||||
-- Which files should be processed? Separate multiple patterns with a semicolon, e.g., *.pdf;*.docx
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T1482642245"] = "Which files should be processed? Separate multiple patterns with a semicolon, e.g., *.pdf;*.docx"
|
||||
|
||||
-- blocked
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T1516072627"] = "blocked"
|
||||
|
||||
-- No matching files were found in the selected folder.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T1528532808"] = "No matching files were found in the selected folder."
|
||||
|
||||
@@ -445,6 +451,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING
|
||||
-- Configured instructions file: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T2215428124"] = "Configured instructions file: {0}"
|
||||
|
||||
-- Tools for this batch run
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T2247412388"] = "Tools for this batch run"
|
||||
|
||||
-- No usable transcription provider is configured.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T2282521655"] = "No usable transcription provider is configured."
|
||||
|
||||
@@ -553,6 +562,12 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING
|
||||
-- Time
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T3756319748"] = "Time"
|
||||
|
||||
-- failed
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T3769421748"] = "failed"
|
||||
|
||||
-- Tools used
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T3809968257"] = "Tools used"
|
||||
|
||||
-- Cancel the batch run
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T3830551741"] = "Cancel the batch run"
|
||||
|
||||
@@ -568,6 +583,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING
|
||||
-- Output
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T4000727844"] = "Output"
|
||||
|
||||
-- Tools of this policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T4031686919"] = "Tools of this policy"
|
||||
|
||||
-- Continue the previous batch run?
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T4037527734"] = "Continue the previous batch run?"
|
||||
|
||||
@@ -631,6 +649,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING
|
||||
-- A separate output folder is excluded from document discovery. This includes the default 'ai-results' folder, so results from an earlier run are not processed again. If the input folder itself is used for output, known batch result files are excluded instead.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T822136905"] = "A separate output folder is excluded from document discovery. This includes the default 'ai-results' folder, so results from an earlier run are not processed again. If the input folder itself is used for output, known batch result files are excluded instead."
|
||||
|
||||
-- The AI may use these tools while working on each document. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when it is selected here.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T967206794"] = "The AI may use these tools while working on each document. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when it is selected here."
|
||||
|
||||
-- Comma (,)
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::BATCHPROCESSINGCSVSEPARATOREXTENSIONS::T1676507543"] = "Comma (,)"
|
||||
|
||||
@@ -971,40 +992,40 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::ASSISTANTBUILDER::T911303749"] =
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::ASSISTANTBUILDER::T997013004"] = "Potentially Unsafe Assistant"
|
||||
|
||||
-- The generated Lua plugin code does not contain a readable plugin ID.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T1163279436"] = "The generated Lua plugin code does not contain a readable plugin ID."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T1163279436"] = "The generated Lua plugin code does not contain a readable plugin ID."
|
||||
|
||||
-- The model's answer is missing the assistant metadata.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T1389066899"] = "The model's answer is missing the assistant metadata."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T1389066899"] = "The model's answer is missing the assistant metadata."
|
||||
|
||||
-- The model's answer contains incomplete plugin metadata.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T181258566"] = "The model's answer contains incomplete plugin metadata."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T181258566"] = "The model's answer contains incomplete plugin metadata."
|
||||
|
||||
-- The model's answer contains incomplete assistant metadata.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T1863964049"] = "The model's answer contains incomplete assistant metadata."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T1863964049"] = "The model's answer contains incomplete assistant metadata."
|
||||
|
||||
-- The model returned an empty JSON object.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T2410202327"] = "The model returned an empty JSON object."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T2410202327"] = "The model returned an empty JSON object."
|
||||
|
||||
-- The model returned an unusable JSON response.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T2967613975"] = "The model returned an unusable JSON response."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T2967613975"] = "The model returned an unusable JSON response."
|
||||
|
||||
-- The model returned an invalid response.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T3368485003"] = "The model returned an invalid response."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T3368485003"] = "The model returned an invalid response."
|
||||
|
||||
-- The model response does not contain the generated Lua plugin code.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T3523772974"] = "The model response does not contain the generated Lua plugin code."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T3523772974"] = "The model response does not contain the generated Lua plugin code."
|
||||
|
||||
-- The model returned an invalid response: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T3546551801"] = "The model returned an invalid response: {0}"
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T3546551801"] = "The model returned an invalid response: {0}"
|
||||
|
||||
-- The model's answer is missing the plugin metadata.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T3731646796"] = "The model's answer is missing the plugin metadata."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T3731646796"] = "The model's answer is missing the plugin metadata."
|
||||
|
||||
-- The model response is missing or unreadable.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T3865942038"] = "The model response is missing or unreadable."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T3865942038"] = "The model response is missing or unreadable."
|
||||
|
||||
-- The model responded with an unsupported or deprecated JSON schema.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROR::T531597860"] = "The model responded with an unsupported or deprecated JSON schema."
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BUILDER::LUARESPONSEPARSEERROREXTENSION::T531597860"] = "The model responded with an unsupported or deprecated JSON schema."
|
||||
|
||||
-- Coding Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::ASSISTANTCODING::T1082499335"] = "Coding Assistant"
|
||||
@@ -1072,6 +1093,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
||||
-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents."
|
||||
|
||||
-- Only the tools selected here can be used by the AI for an analysis with this policy. Every tool still has to meet the confidence requirements of the selected provider, so a tool may remain unavailable even when this policy permits it.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1692505801"] = "Only the tools selected here can be used by the AI for an analysis with this policy. Every tool still has to meet the confidence requirements of the selected provider, so a tool may remain unavailable even when this policy permits it."
|
||||
|
||||
-- Yes, protect this policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy"
|
||||
|
||||
@@ -1153,6 +1177,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
||||
-- Delete this policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3119086260"] = "Delete this policy"
|
||||
|
||||
-- Tools this policy permits
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T31356122"] = "Tools this policy permits"
|
||||
|
||||
-- Policy {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Policy {0}"
|
||||
|
||||
@@ -1219,6 +1246,12 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
|
||||
-- Revise Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DYNAMIC::ASSISTANTDYNAMIC::T1070696505"] = "Revise Assistant"
|
||||
|
||||
-- Tools of this assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DYNAMIC::ASSISTANTDYNAMIC::T1456501183"] = "Tools of this assistant"
|
||||
|
||||
-- The author of this assistant chose these tools, so they cannot be changed here. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when this assistant names it.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DYNAMIC::ASSISTANTDYNAMIC::T1835492160"] = "The author of this assistant chose these tools, so they cannot be changed here. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when this assistant names it."
|
||||
|
||||
-- No assistant plugin are currently installed.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DYNAMIC::ASSISTANTDYNAMIC::T1913566603"] = "No assistant plugin are currently installed."
|
||||
|
||||
@@ -3193,21 +3226,42 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1183581066"] = "Edit Me
|
||||
-- Table {0} ({1})
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1340759627"] = "Table {0} ({1})"
|
||||
|
||||
-- Result
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1347088452"] = "Result"
|
||||
|
||||
-- Do you really want to remove this message?
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1347427447"] = "Do you really want to remove this message?"
|
||||
|
||||
-- Yes, remove the AI response and edit it
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1350385882"] = "Yes, remove the AI response and edit it"
|
||||
|
||||
-- Failed
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1434043348"] = "Failed"
|
||||
|
||||
-- Tool Calls ({0})
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1493057571"] = "Tool Calls ({0})"
|
||||
|
||||
-- Executed
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1564757972"] = "Executed"
|
||||
|
||||
-- Yes, regenerate it
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1603883875"] = "Yes, regenerate it"
|
||||
|
||||
-- No result
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1684269223"] = "No result"
|
||||
|
||||
-- Yes, remove it
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1820166585"] = "Yes, remove it"
|
||||
|
||||
-- Number of sources
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1848978959"] = "Number of sources"
|
||||
|
||||
-- Show {0} tool calls
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1981771421"] = "Show {0} tool calls"
|
||||
|
||||
-- Show tool call for {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T2004842583"] = "Show tool call for {0}"
|
||||
|
||||
-- Do you really want to edit this message? In order to edit this message, the AI response will be deleted.
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T2018431076"] = "Do you really want to edit this message? In order to edit this message, the AI response will be deleted."
|
||||
|
||||
@@ -3220,6 +3274,9 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T2308444540"] = "Regener
|
||||
-- Failed to export this message, because the file format '{0}' is unknown.
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T2544592344"] = "Failed to export this message, because the file format '{0}' is unknown."
|
||||
|
||||
-- Arguments
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T2738624831"] = "Arguments"
|
||||
|
||||
-- Export AI response
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T2822776450"] = "Export AI response"
|
||||
|
||||
@@ -3232,9 +3289,15 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3175548294"] = "Cannot
|
||||
-- Edit
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3267849393"] = "Edit"
|
||||
|
||||
-- Unknown
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3424652889"] = "Unknown"
|
||||
|
||||
-- Regenerate
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3587744975"] = "Regenerate"
|
||||
|
||||
-- Blocked
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3816336467"] = "Blocked"
|
||||
|
||||
-- Do you really want to regenerate this message?
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3878878761"] = "Do you really want to regenerate this message?"
|
||||
|
||||
@@ -3244,6 +3307,12 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4070211974"] = "Remove
|
||||
-- No, keep it
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4188329028"] = "No, keep it"
|
||||
|
||||
-- No tool calls
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4224149521"] = "No tool calls"
|
||||
|
||||
-- No arguments
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T931993614"] = "No arguments"
|
||||
|
||||
-- The file '{0}' is currently not available and was not sent.
|
||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T1432544573"] = "The file '{0}' is currently not available and was not sent."
|
||||
|
||||
@@ -3319,12 +3388,18 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T1841954939"
|
||||
-- Company approved
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T2036497459"] = "Company approved"
|
||||
|
||||
-- Uses 1 tool
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T2143098104"] = "Uses 1 tool"
|
||||
|
||||
-- Approved name
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T2282386733"] = "Approved name"
|
||||
|
||||
-- Required minimum
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T2354026284"] = "Required minimum"
|
||||
|
||||
-- Tools
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T2499909372"] = "Tools"
|
||||
|
||||
-- Audit provider
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T2757790517"] = "Audit provider"
|
||||
|
||||
@@ -3343,6 +3418,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T3240350158"
|
||||
-- Confidence
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T3243388657"] = "Confidence"
|
||||
|
||||
-- Uses {0} tools
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T3368476832"] = "Uses {0} tools"
|
||||
|
||||
-- Unknown
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T3424652889"] = "Unknown"
|
||||
|
||||
@@ -3562,14 +3640,14 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONMINCONFIDENCESELECTION::T252
|
||||
-- Select a minimum confidence level
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONMINCONFIDENCESELECTION::T2579793544"] = "Select a minimum confidence level"
|
||||
|
||||
-- You have selected 1 preview feature.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONMULTISELECT::T1384241824"] = "You have selected 1 preview feature."
|
||||
-- You have selected {0} items.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONMULTISELECT::T2530254201"] = "You have selected {0} items."
|
||||
|
||||
-- No preview features selected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONMULTISELECT::T2809641588"] = "No preview features selected."
|
||||
-- No items selected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONMULTISELECT::T3309488347"] = "No items selected."
|
||||
|
||||
-- You have selected {0} preview features.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONMULTISELECT::T3513450626"] = "You have selected {0} preview features."
|
||||
-- You have selected 1 item.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONMULTISELECT::T95098799"] = "You have selected 1 item."
|
||||
|
||||
-- Preselected provider
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T1469984996"] = "Preselected provider"
|
||||
@@ -3652,6 +3730,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCESELECTION::T700666808"] = "Mana
|
||||
-- Available Data Sources
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCESELECTION::T86053874"] = "Available Data Sources"
|
||||
|
||||
-- Tools (Optional)
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T1019749907"] = "Tools (Optional)"
|
||||
|
||||
-- These tools are preselected when the chat opens. Users can change the selection in the chat, and every tool has to meet the confidence requirements of the provider in use.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T1286170698"] = "These tools are preselected when the chat opens. Users can change the selection in the chat, and every tool has to meet the confidence requirements of the provider in use."
|
||||
|
||||
-- Chat provider
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T1648955896"] = "Chat provider"
|
||||
|
||||
@@ -3703,6 +3787,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::HALLUZINATIONREMINDER::T3528806904"] = "L
|
||||
-- Issues
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ISSUES::T3229841001"] = "Issues"
|
||||
|
||||
-- Some tools selected for this run are not fully configured and stay unused: {0}. Please complete their settings.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEDTOOLSWARNING::T1319635088"] = "Some tools selected for this run are not fully configured and stay unused: {0}. Please complete their settings."
|
||||
|
||||
-- Not all tools selected for this run can be used with the chosen AI provider: {0}. Please choose a provider with a higher confidence level to use all of them.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEDTOOLSWARNING::T2430645786"] = "Not all tools selected for this run can be used with the chosen AI provider: {0}. Please choose a provider with a higher confidence level to use all of them."
|
||||
|
||||
-- Tools were selected for this run, but the chosen model cannot use tools. It runs without them. Please choose a model which supports tools.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEDTOOLSWARNING::T3008114108"] = "Tools were selected for this run, but the chosen model cannot use tools. It runs without them. Please choose a model which supports tools."
|
||||
|
||||
-- Your Pandoc installation meets the requirements.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T1167365374"] = "Your Pandoc installation meets the requirements."
|
||||
|
||||
@@ -3982,6 +4075,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T2939928117"] = "Cleanup
|
||||
-- Hide web content options
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T3031774728"] = "Hide web content options"
|
||||
|
||||
-- The content of '{0}' could not be loaded: {1}
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T3073906267"] = "The content of '{0}' could not be loaded: {1}"
|
||||
|
||||
-- Please provide a valid HTTP or HTTPS URL.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T307442288"] = "Please provide a valid HTTP or HTTPS URL."
|
||||
|
||||
@@ -4168,6 +4264,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1364944735"]
|
||||
-- Additional root certificates are enabled
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1380446131"] = "Additional root certificates are enabled"
|
||||
|
||||
-- You have selected 1 preview feature.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1384241824"] = "You have selected 1 preview feature."
|
||||
|
||||
-- Select preview features
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1439783084"] = "Select preview features"
|
||||
|
||||
@@ -4252,6 +4351,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2655930524"]
|
||||
-- Path to a PEM file containing one or more root CA certificates. For Flatpak deployments, this file must be placed in a location that is readable inside the sandbox.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2700836219"] = "Path to a PEM file containing one or more root CA certificates. For Flatpak deployments, this file must be placed in a location that is readable inside the sandbox."
|
||||
|
||||
-- No preview features selected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2809641588"] = "No preview features selected."
|
||||
|
||||
-- This installation does not check for updates itself. Contact the person or organization that installed AI Studio for update information.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2918560776"] = "This installation does not check for updates itself. Contact the person or organization that installed AI Studio for update information."
|
||||
|
||||
@@ -4270,6 +4372,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3165555978"]
|
||||
-- External HTTPS certificates
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T348936513"] = "External HTTPS certificates"
|
||||
|
||||
-- You have selected {0} preview features.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3513450626"] = "You have selected {0} preview features."
|
||||
|
||||
-- Allowed hosts for additional root certificates
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3562495752"] = "Allowed hosts for additional root certificates"
|
||||
|
||||
@@ -4579,6 +4684,42 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T782238
|
||||
-- Export configuration
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T975426229"] = "Export configuration"
|
||||
|
||||
-- Settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T1258653480"] = "Settings"
|
||||
|
||||
-- Description
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T1725856265"] = "Description"
|
||||
|
||||
-- Icon
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T1759955728"] = "Icon"
|
||||
|
||||
-- This tool still needs to be configured.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T1958939818"] = "This tool still needs to be configured."
|
||||
|
||||
-- Missing required settings: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T2588115579"] = "Missing required settings: {0}"
|
||||
|
||||
-- Name
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T266367750"] = "Name"
|
||||
|
||||
-- No minimum confidence level chosen
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T2828607242"] = "No minimum confidence level chosen"
|
||||
|
||||
-- Minimum provider confidence
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3461070436"] = "Minimum provider confidence"
|
||||
|
||||
-- Configure global settings for each tool.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3728248397"] = "Configure global settings for each tool."
|
||||
|
||||
-- Tool Settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3730473128"] = "Tool Settings"
|
||||
|
||||
-- This tool has been disabled by your organization.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3794167684"] = "This tool has been disabled by your organization."
|
||||
|
||||
-- Status
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T6222351"] = "Status"
|
||||
|
||||
-- No transcription provider configured yet.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "No transcription provider configured yet."
|
||||
|
||||
@@ -4654,6 +4795,72 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::THIRDPARTYCOMPONENT::T1392042694"] = "Ope
|
||||
-- License:
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::THIRDPARTYCOMPONENT::T1908172666"] = "License:"
|
||||
|
||||
-- Tool selection is hidden
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T2096103917"] = "Tool selection is hidden"
|
||||
|
||||
-- You have selected 1 tool.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T2493128368"] = "You have selected 1 tool."
|
||||
|
||||
-- Choose which tools should be preselected for new runs of this assistant.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T2696618758"] = "Choose which tools should be preselected for new runs of this assistant."
|
||||
|
||||
-- Default tools for this assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T3253667950"] = "Default tools for this assistant"
|
||||
|
||||
-- Tool selection is visible
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T3384582069"] = "Tool selection is visible"
|
||||
|
||||
-- Show tool selection in this assistant?
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T3494508870"] = "Show tool selection in this assistant?"
|
||||
|
||||
-- You have selected {0} tools.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T3729156356"] = "You have selected {0} tools."
|
||||
|
||||
-- No tools selected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T3934845540"] = "No tools selected."
|
||||
|
||||
-- Default tools for chat
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T907403808"] = "Default tools for chat"
|
||||
|
||||
-- Choose which tools should be preselected for new chats.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLDEFAULTSCONFIGURATION::T948842182"] = "Choose which tools should be preselected for new chats."
|
||||
|
||||
-- Tool changes are locked while a response is running. Your current selection is shown below and applies again from the next message once the run is finished.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T1688023907"] = "Tool changes are locked while a response is running. Your current selection is shown below and applies again from the next message once the run is finished."
|
||||
|
||||
-- Tools allow the LLM to perform targeted additional actions such as web searches or reading web pages.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T1944689297"] = "Tools allow the LLM to perform targeted additional actions such as web searches or reading web pages."
|
||||
|
||||
-- Required settings are missing. Configure this tool before enabling it.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3119156561"] = "Required settings are missing. Configure this tool before enabling it."
|
||||
|
||||
-- Close
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3448155331"] = "Close"
|
||||
|
||||
-- This tool has been disabled by your organization.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3794167684"] = "This tool has been disabled by your organization."
|
||||
|
||||
-- No tools are available in this context.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3904490680"] = "No tools are available in this context."
|
||||
|
||||
-- This tool requires provider confidence {0}. The selected provider has {1}.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T4097602620"] = "This tool requires provider confidence {0}. The selected provider has {1}."
|
||||
|
||||
-- Tool Selection
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T749664565"] = "Tool Selection"
|
||||
|
||||
-- Select tools
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T998515990"] = "Select tools"
|
||||
|
||||
-- No tools selected
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTIONFIELD::T2892114594"] = "No tools selected"
|
||||
|
||||
-- 1 tool selected
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTIONFIELD::T4209882371"] = "1 tool selected"
|
||||
|
||||
-- {0} tools selected
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTIONFIELD::T807707919"] = "{0} tools selected"
|
||||
|
||||
-- You'll interact with the AI systems using your voice. To achieve this, we want to integrate voice input (speech-to-text) and output (text-to-speech). However, later on, it should also have a natural conversation flow, i.e., seamless conversation.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VISION::T1015366320"] = "You'll interact with the AI systems using your voice. To achieve this, we want to integrate voice input (speech-to-text) and output (text-to-speech). However, later on, it should also have a natural conversation flow, i.e., seamless conversation."
|
||||
|
||||
@@ -6424,6 +6631,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T2646845972"] = "Add"
|
||||
-- Additional API parameters
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T2728244552"] = "Additional API parameters"
|
||||
|
||||
-- Tool calling
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T2745173751"] = "Tool calling"
|
||||
|
||||
-- Invalid JSON: Add the parameters in proper JSON formatting, e.g., "temperature": 0.5. Remove trailing commas. The usual surrounding curly brackets {} must not be used, though.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T2765821959"] = "Invalid JSON: Add the parameters in proper JSON formatting, e.g., \"temperature\": 0.5. Remove trailing commas. The usual surrounding curly brackets {} must not be used, though."
|
||||
|
||||
@@ -6865,6 +7075,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGBATCHPROCESSING::T22
|
||||
-- The lower end of the random pause interval. AI Studio never allows less than 6 seconds.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGBATCHPROCESSING::T237774509"] = "The lower end of the random pause interval. AI Studio never allows less than 6 seconds."
|
||||
|
||||
-- A policy brings its own tools, so there is nothing to preselect here. You configure them with the policy in the Document Analysis Assistant.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGBATCHPROCESSING::T2391906382"] = "A policy brings its own tools, so there is nothing to preselect here. You configure them with the policy in the Document Analysis Assistant."
|
||||
|
||||
-- When enabled, new batch runs start with the defaults configured below.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGBATCHPROCESSING::T2592677194"] = "When enabled, new batch runs start with the defaults configured below."
|
||||
|
||||
@@ -7978,6 +8191,30 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T3547
|
||||
-- Preselect e-mail options?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T3832719342"] = "Preselect e-mail options?"
|
||||
|
||||
-- Save
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T1294818664"] = "Save"
|
||||
|
||||
-- Please configure the required settings: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T2412603418"] = "Please configure the required settings: {0}"
|
||||
|
||||
-- Not set
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3616903110"] = "Not set"
|
||||
|
||||
-- Tool Settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3730473128"] = "Tool Settings"
|
||||
|
||||
-- This tool has been disabled by your organization.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3794167684"] = "This tool has been disabled by your organization."
|
||||
|
||||
-- The selected tool could not be loaded.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3907843187"] = "The selected tool could not be loaded."
|
||||
|
||||
-- {0} Default: {1}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T403490413"] = "{0} Default: {1}"
|
||||
|
||||
-- Cancel
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T900713019"] = "Cancel"
|
||||
|
||||
-- Save
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SHORTCUTDIALOG::T1294818664"] = "Save"
|
||||
|
||||
@@ -10243,6 +10480,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T3
|
||||
-- The provided ASSISTANT lua table does not contain a valid system prompt.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T3402798667"] = "The provided ASSISTANT lua table does not contain a valid system prompt."
|
||||
|
||||
-- The ASSISTANT table contains invalid ToolIds. Expected a non-empty list of unique, non-empty tool IDs.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T3416855489"] = "The ASSISTANT table contains invalid ToolIds. Expected a non-empty list of unique, non-empty tool IDs."
|
||||
|
||||
-- The ASSISTANT table does not contain a valid system prompt.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T3723171842"] = "The ASSISTANT table does not contain a valid system prompt."
|
||||
|
||||
@@ -10708,6 +10948,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SECURITY::PROMPTINJECTIONGUARDSERVICE::T246048
|
||||
-- AI Studio removed suspicious instructions from {0} sources before using them.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SECURITY::PROMPTINJECTIONGUARDSERVICE::T3489536228"] = "AI Studio removed suspicious instructions from {0} sources before using them."
|
||||
|
||||
-- AI Studio could not check {0} sources for prompt injections. The content is used as it is.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SECURITY::PROMPTINJECTIONGUARDSERVICE::T3583030090"] = "AI Studio could not check {0} sources for prompt injections. The content is used as it is."
|
||||
|
||||
-- Chat attachment
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SECURITY::PROMPTINJECTIONSOURCEKINDEXTENSIONS::T1071345316"] = "Chat attachment"
|
||||
|
||||
@@ -10738,6 +10981,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T1
|
||||
-- The revision model did not return a usable answer.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T1411545143"] = "The revision model did not return a usable answer."
|
||||
|
||||
-- The revised assistant plugin asks for tools this AI Studio does not have: \"{0}\". Please try again.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T1427741438"] = "The revised assistant plugin asks for tools this AI Studio does not have: \\\"{0}\\\". Please try again."
|
||||
|
||||
-- Description
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T1725856265"] = "Description"
|
||||
|
||||
@@ -10759,6 +11005,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T2
|
||||
-- The current plugin.lua content is empty.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T2491968008"] = "The current plugin.lua content is empty."
|
||||
|
||||
-- Tools
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T2499909372"] = "Tools"
|
||||
|
||||
-- Inputs
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T2647381688"] = "Inputs"
|
||||
|
||||
@@ -10777,6 +11026,12 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T2
|
||||
-- UI Components
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T3053707933"] = "UI Components"
|
||||
|
||||
-- The generated assistant plugin asks for tools this AI Studio does not have: \"{0}\". Please try again.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T3058747041"] = "The generated assistant plugin asks for tools this AI Studio does not have: \\\"{0}\\\". Please try again."
|
||||
|
||||
-- The generated assistant plugin must be a form assistant, not a chat launcher.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T3203271639"] = "The generated assistant plugin must be a form assistant, not a chat launcher."
|
||||
|
||||
-- Assistant Plugin Revision
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T3245954919"] = "Assistant Plugin Revision"
|
||||
|
||||
@@ -10798,9 +11053,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T3
|
||||
-- The revised assistant metadata does not match the revised plugin.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T3578379466"] = "The revised assistant metadata does not match the revised plugin."
|
||||
|
||||
-- The generated assistant plugin does not match the selected chat launcher configuration.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T3631147451"] = "The generated assistant plugin does not match the selected chat launcher configuration."
|
||||
|
||||
-- Safety Notes
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T3633499050"] = "Safety Notes"
|
||||
|
||||
@@ -10831,6 +11083,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T4
|
||||
-- Prompt Strategy
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T410529216"] = "Prompt Strategy"
|
||||
|
||||
-- The generated chat launcher is not a valid assistant plugin.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T4182589474"] = "The generated chat launcher is not a valid assistant plugin."
|
||||
|
||||
-- The draft model did not return a usable answer.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T4183375977"] = "The draft model did not return a usable answer."
|
||||
|
||||
@@ -11149,6 +11404,165 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SOURCEEXTENSIONS::T4174900468"] = "Sources pro
|
||||
-- Sources provided by the AI
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SOURCEEXTENSIONS::T4261248356"] = "Sources provided by the AI"
|
||||
|
||||
-- Sources used by tools
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SOURCEEXTENSIONS::T535360212"] = "Sources used by tools"
|
||||
|
||||
-- The provider '{0}' returned an invalid tool calling response. Check the provider's tool calling configuration and see the logs for details.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::HARNESS::TOOLCALLINGMESSAGES::T2768311456"] = "The provider '{0}' returned an invalid tool calling response. Check the provider's tool calling configuration and see the logs for details."
|
||||
|
||||
-- The tool calling request failed with status code {0}. See the logs for details.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::HARNESS::TOOLCALLINGMESSAGES::T3117779001"] = "The tool calling request failed with status code {0}. See the logs for details."
|
||||
|
||||
-- Tool
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::ITOOLIMPLEMENTATION::T3517012711"] = "Tool"
|
||||
|
||||
-- Tool description
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::ITOOLIMPLEMENTATION::T4056470505"] = "Tool description"
|
||||
|
||||
-- Please select an LLM provider.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGAVAILABILITYEXTENSIONS::T1110311702"] = "Please select an LLM provider."
|
||||
|
||||
-- Tool calling support is not enabled by default for this model, but you can enable this capability in the expert settings of the provider if you are sure the model supports it.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGAVAILABILITYEXTENSIONS::T3805542503"] = "Tool calling support is not enabled by default for this model, but you can enable this capability in the expert settings of the provider if you are sure the model supports it."
|
||||
|
||||
-- Allowed private hosts must be host names only, without scheme or path.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T2196457612"] = "Allowed private hosts must be host names only, without scheme or path."
|
||||
|
||||
-- The web page was not loaded because private or VPN web pages require a High-confidence provider or a provider trusted by your organization's configuration.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T2563437007"] = "The web page was not loaded because private or VPN web pages require a High-confidence provider or a provider trusted by your organization's configuration."
|
||||
|
||||
-- Maximum Content Characters
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T2801581200"] = "Maximum Content Characters"
|
||||
|
||||
-- Allowed private host '{0}' is not valid.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T3089707139"] = "Allowed private host '{0}' is not valid."
|
||||
|
||||
-- Allowed Private Hosts
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T3415515539"] = "Allowed Private Hosts"
|
||||
|
||||
-- Timeout Seconds
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T3567699845"] = "Timeout Seconds"
|
||||
|
||||
-- Read Web Page
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T3612587998"] = "Read Web Page"
|
||||
|
||||
-- Load a web page and extract its readable content, links, and page details.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T3715690061"] = "Load a web page and extract its readable content, links, and page details."
|
||||
|
||||
-- (Optional) Host allowlist for private or VPN web pages. For security reasons, private or VPN web pages aren't allowed to be read by default. Separate host patterns with commas, such as example.de, *.example.de. Allowed private hosts require a High-confidence provider or a provider trusted by your organization's configuration. For allowed HTTPS internal hosts, AI Studio also tries the operating system's default sign-in automatically when the server responds with integrated authentication.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T3802894016"] = "(Optional) Host allowlist for private or VPN web pages. For security reasons, private or VPN web pages aren't allowed to be read by default. Separate host patterns with commas, such as example.de, *.example.de. Allowed private hosts require a High-confidence provider or a provider trusted by your organization's configuration. For allowed HTTPS internal hosts, AI Studio also tries the operating system's default sign-in automatically when the server responds with integrated authentication."
|
||||
|
||||
-- (Optional) HTTP timeout for loading a web page in seconds.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T4126164830"] = "(Optional) HTTP timeout for loading a web page in seconds."
|
||||
|
||||
-- The setting '{0}' must be a positive integer.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T4199432074"] = "The setting '{0}' must be a positive integer."
|
||||
|
||||
-- (Optional) Global truncation limit for extracted characters returned to the model.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::READWEBPAGETOOL::T900659180"] = "(Optional) Global truncation limit for extracted characters returned to the model."
|
||||
|
||||
-- The language to search in when the AI model does not ask for a specific one. This is required: without a language, many search engines return no results at all, and the search would come back empty without telling you why. Choose 'Any language' if you do not want to restrict the results.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T114991220"] = "The language to search in when the AI model does not ask for a specific one. This is required: without a language, many search engines return no results at all, and the search would come back empty without telling you why. Choose 'Any language' if you do not want to restrict the results."
|
||||
|
||||
-- Maximum Results
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T1273024715"] = "Maximum Results"
|
||||
|
||||
-- The setting '{0}' must be less than or equal to {1}.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T1391527409"] = "The setting '{0}' must be less than or equal to {1}."
|
||||
|
||||
-- All Pages Retrieval Timeout Seconds
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T1633427398"] = "All Pages Retrieval Timeout Seconds"
|
||||
|
||||
-- Optional minimum character budget reserved for each successfully retrieved website.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T1671995661"] = "Optional minimum character budget reserved for each successfully retrieved website."
|
||||
|
||||
-- A SearXNG URL is required.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T1746583720"] = "A SearXNG URL is required."
|
||||
|
||||
-- The total content budget must reserve at least {0} characters for each of up to {1} results.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T2124070269"] = "The total content budget must reserve at least {0} characters for each of up to {1} results."
|
||||
|
||||
-- Default Safe Search Policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T2514181501"] = "Default Safe Search Policy"
|
||||
|
||||
-- Default Language
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T2526826120"] = "Default Language"
|
||||
|
||||
-- The configured web search content budget is not valid.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T299004879"] = "The configured web search content budget is not valid."
|
||||
|
||||
-- The configured SearXNG URL is not a valid absolute URL.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3038368943"] = "The configured SearXNG URL is not a valid absolute URL."
|
||||
|
||||
-- Search Timeout Seconds
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3219072199"] = "Search Timeout Seconds"
|
||||
|
||||
-- Search the web with a configured SearXNG instance and retrieve the readable content of the best matching pages.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3361633224"] = "Search the web with a configured SearXNG instance and retrieve the readable content of the best matching pages."
|
||||
|
||||
-- Page Timeout Seconds
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3459475852"] = "Page Timeout Seconds"
|
||||
|
||||
-- Optional default maximum number of results returned to the model when the model does not provide a limit.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3603838271"] = "Optional default maximum number of results returned to the model when the model does not provide a limit."
|
||||
|
||||
-- Maximum Total Content Characters
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T366488298"] = "Maximum Total Content Characters"
|
||||
|
||||
-- Optional timeout for loading each individual result page in seconds.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3668086641"] = "Optional timeout for loading each individual result page in seconds."
|
||||
|
||||
-- Web Search
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3815068443"] = "Web Search"
|
||||
|
||||
-- Optional overall timeout for retrieving all result pages in seconds.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3854998169"] = "Optional overall timeout for retrieving all result pages in seconds."
|
||||
|
||||
-- Optional safe search policy sent to SearXNG when configured.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3967748757"] = "Optional safe search policy sent to SearXNG when configured."
|
||||
|
||||
-- Optional HTTP timeout for the SearXNG search request in seconds.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T408390115"] = "Optional HTTP timeout for the SearXNG search request in seconds."
|
||||
|
||||
-- Base URL of the SearXNG instance. You can enter either the instance root URL or the /search endpoint. The instance must have the JSON format enabled, which means 'json' has to be listed under 'search.formats' in its settings.yml. Public instances usually serve only the web interface and additionally block automated requests, so a self-hosted instance is the reliable option.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T4198847064"] = "Base URL of the SearXNG instance. You can enter either the instance root URL or the /search endpoint. The instance must have the JSON format enabled, which means 'json' has to be listed under 'search.formats' in its settings.yml. Public instances usually serve only the web interface and additionally block automated requests, so a self-hosted instance is the reliable option."
|
||||
|
||||
-- The setting '{0}' must be a positive integer.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T4199432074"] = "The setting '{0}' must be a positive integer."
|
||||
|
||||
-- Minimum Content Characters Budget Per Website
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T4200431837"] = "Minimum Content Characters Budget Per Website"
|
||||
|
||||
-- The setting '{0}' holds the value '{1}', which is not one of the available options. Please choose one of the offered values.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T68683294"] = "The setting '{0}' holds the value '{1}', which is not one of the available options. Please choose one of the offered values."
|
||||
|
||||
-- Optional total character budget shared by all retrieved pages.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T836062282"] = "Optional total character budget shared by all retrieved pages."
|
||||
|
||||
-- The configured SearXNG URL must start with http:// or https://.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T944878454"] = "The configured SearXNG URL must start with http:// or https://."
|
||||
|
||||
-- SearXNG URL
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T993547568"] = "SearXNG URL"
|
||||
|
||||
-- Using tools: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLRUNTIMESTATUS::T2834986024"] = "Using tools: {0}"
|
||||
|
||||
-- Using tool: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLRUNTIMESTATUS::T4185351801"] = "Using tool: {0}"
|
||||
|
||||
-- Moderate
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T177463328"] = "Moderate"
|
||||
|
||||
-- Strict
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T1834358932"] = "Strict"
|
||||
|
||||
-- Off
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T231126186"] = "Off"
|
||||
|
||||
-- Any language
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T747012729"] = "Any language"
|
||||
|
||||
-- The file path is null or empty and the file therefore can not be loaded.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::USERFILE::T932243993"] = "The file path is null or empty and the file therefore can not be loaded."
|
||||
|
||||
@@ -11290,11 +11704,17 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::PROVIDERVALIDATION::T649507886"] =
|
||||
-- Please select a model.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::PROVIDERVALIDATION::T818893091"] = "Please select a model."
|
||||
|
||||
-- Are you sure you want to delete the chat '{0}' in the workspace '{1}'?
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T1016188706"] = "Are you sure you want to delete the chat '{0}' in the workspace '{1}'?"
|
||||
|
||||
-- Unnamed workspace
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T1307384014"] = "Unnamed workspace"
|
||||
|
||||
-- Delete Chat
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T2244038752"] = "Delete Chat"
|
||||
|
||||
-- Are you sure you want to delete the temporary chat '{0}'?
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T3043761007"] = "Are you sure you want to delete the temporary chat '{0}'?"
|
||||
|
||||
-- Unnamed chat
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T3310482275"] = "Unnamed chat"
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Assistants.PromptOptimizer;
|
||||
|
||||
public sealed class PromptOptimizationRecommendations
|
||||
{
|
||||
[JsonPropertyName("clarity_and_directness")]
|
||||
public string ClarityAndDirectness { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("examples_and_context")]
|
||||
public string ExamplesAndContext { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("sequential_steps")]
|
||||
public string SequentialSteps { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("structure_with_markers")]
|
||||
public string StructureWithMarkers { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("role_definition")]
|
||||
public string RoleDefinition { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("language_choice")]
|
||||
public string LanguageChoice { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -9,25 +9,4 @@ public sealed class PromptOptimizationResult
|
||||
|
||||
[JsonPropertyName("recommendations")]
|
||||
public PromptOptimizationRecommendations Recommendations { get; set; } = new();
|
||||
}
|
||||
|
||||
public sealed class PromptOptimizationRecommendations
|
||||
{
|
||||
[JsonPropertyName("clarity_and_directness")]
|
||||
public string ClarityAndDirectness { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("examples_and_context")]
|
||||
public string ExamplesAndContext { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("sequential_steps")]
|
||||
public string SequentialSteps { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("structure_with_markers")]
|
||||
public string StructureWithMarkers { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("role_definition")]
|
||||
public string RoleDefinition { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("language_choice")]
|
||||
public string LanguageChoice { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public sealed partial class VisualBriefingStore
|
||||
: VisualBriefingBuildStatus.ACTIVE;
|
||||
matching.Failure = null;
|
||||
matching.UpdatedAtUtc = DateTimeOffset.UtcNow;
|
||||
await this.StoreBuildAtomicAsync(matching, token);
|
||||
await this.StoreBuildAtomicAsync(matching, overwrite: true, token);
|
||||
return (matching, true);
|
||||
}
|
||||
|
||||
@@ -56,10 +56,10 @@ public sealed partial class VisualBriefingStore
|
||||
{
|
||||
stale.Status = VisualBriefingBuildStatus.SUPERSEDED;
|
||||
stale.UpdatedAtUtc = DateTimeOffset.UtcNow;
|
||||
await this.StoreBuildAtomicAsync(stale, token);
|
||||
await this.StoreBuildAtomicAsync(stale, overwrite: true, token);
|
||||
}
|
||||
|
||||
await this.StoreBuildAtomicAsync(candidate, token, overwrite: false);
|
||||
await this.StoreBuildAtomicAsync(candidate, overwrite: false, token);
|
||||
return (candidate, false);
|
||||
}
|
||||
finally
|
||||
@@ -81,7 +81,7 @@ public sealed partial class VisualBriefingStore
|
||||
|
||||
try
|
||||
{
|
||||
await this.StoreBuildAtomicAsync(build, token);
|
||||
await this.StoreBuildAtomicAsync(build, overwrite: true, token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -372,12 +372,11 @@ public sealed partial class VisualBriefingStore
|
||||
/// Writes one build record atomically.
|
||||
/// </summary>
|
||||
/// <param name="build">The build record.</param>
|
||||
/// <param name="token">The cancellation token.</param>
|
||||
/// <param name="overwrite">Whether an existing record may be replaced.</param>
|
||||
private async Task StoreBuildAtomicAsync(
|
||||
VisualBriefingBuildRecord build,
|
||||
CancellationToken token,
|
||||
bool overwrite = true)
|
||||
/// <param name="token">The cancellation token.</param>
|
||||
private async Task StoreBuildAtomicAsync(VisualBriefingBuildRecord build,
|
||||
bool overwrite,
|
||||
CancellationToken token)
|
||||
{
|
||||
if (build.BuildVersion != VisualBriefingVersions.BUILD ||
|
||||
build.BuildId == Guid.Empty ||
|
||||
@@ -386,7 +385,7 @@ public sealed partial class VisualBriefingStore
|
||||
throw new InvalidDataException("The visual briefing build record is invalid.");
|
||||
|
||||
var json = JsonSerializer.Serialize(build, JSON_OPTIONS);
|
||||
await WriteTextAtomicAsync(this.BuildPath(build.BriefingId, build.BuildId), json, token, overwrite);
|
||||
await WriteTextAtomicAsync(this.BuildPath(build.BriefingId, build.BuildId), json, overwrite, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -22,7 +22,7 @@ public sealed partial class VisualBriefingStore
|
||||
try
|
||||
{
|
||||
this.LastSelectedBriefingId = briefingId;
|
||||
await WriteTextAtomicAsync(this.SelectionPath(), JsonSerializer.Serialize<Guid?>(briefingId), token);
|
||||
await WriteTextAtomicAsync(this.SelectionPath(), JsonSerializer.Serialize<Guid?>(briefingId), overwrite: true, token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -45,7 +45,7 @@ public sealed partial class VisualBriefingStore
|
||||
return;
|
||||
|
||||
this.LastSelectedBriefingId = null;
|
||||
await WriteTextAtomicAsync(this.SelectionPath(), JsonSerializer.Serialize<Guid?>(null), token);
|
||||
await WriteTextAtomicAsync(this.SelectionPath(), JsonSerializer.Serialize<Guid?>(null), overwrite: true, token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -456,7 +456,7 @@ public sealed partial class VisualBriefingStore
|
||||
private async Task StoreManifestAtomicAsync(VisualBriefingManifest manifest, CancellationToken token)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(manifest, JSON_OPTIONS);
|
||||
await WriteTextAtomicAsync(this.ManifestPath(manifest.BriefingId), json, token);
|
||||
await WriteTextAtomicAsync(this.ManifestPath(manifest.BriefingId), json, overwrite: true, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -59,7 +59,7 @@ public sealed partial class VisualBriefingStore
|
||||
committedBuild.Failure = null;
|
||||
committedBuild.UpdatedAtUtc = DateTimeOffset.UtcNow;
|
||||
|
||||
await this.StoreBuildAtomicAsync(committedBuild, token);
|
||||
await this.StoreBuildAtomicAsync(committedBuild, overwrite: true, token);
|
||||
}
|
||||
|
||||
foreach (var interruptedBuild in builds.Where(build => build.Status is VisualBriefingBuildStatus.ACTIVE))
|
||||
@@ -99,7 +99,7 @@ public sealed partial class VisualBriefingStore
|
||||
interruptedBuild.Status = VisualBriefingBuildStatus.FAILED;
|
||||
interruptedBuild.Failure = interruptedFailure;
|
||||
interruptedBuild.UpdatedAtUtc = DateTimeOffset.UtcNow;
|
||||
await this.StoreBuildAtomicAsync(interruptedBuild, token);
|
||||
await this.StoreBuildAtomicAsync(interruptedBuild, overwrite: true, token);
|
||||
}
|
||||
|
||||
var changed = manifest.Versions.RemoveAll(version =>
|
||||
@@ -166,7 +166,7 @@ public sealed partial class VisualBriefingStore
|
||||
matchingBuild.Status = VisualBriefingBuildStatus.COMPLETED;
|
||||
matchingBuild.Failure = null;
|
||||
matchingBuild.UpdatedAtUtc = DateTimeOffset.UtcNow;
|
||||
await this.StoreBuildAtomicAsync(matchingBuild, token);
|
||||
await this.StoreBuildAtomicAsync(matchingBuild, overwrite: true, token);
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
@@ -85,7 +85,7 @@ public sealed partial class VisualBriefingStore
|
||||
var source = manifest.Sources.FirstOrDefault(candidate => candidate.SourceId == sourceId)
|
||||
?? throw new InvalidOperationException("The media source does not exist in this briefing.");
|
||||
var transcriptPath = this.TranscriptPath(briefingId, source.SourceId);
|
||||
await WriteTextAtomicAsync(transcriptPath, transcript, token);
|
||||
await WriteTextAtomicAsync(transcriptPath, transcript, overwrite: true, token);
|
||||
source.TranscriptStatus = VisualBriefingTranscriptStatus.CURRENT;
|
||||
ApplyFileSnapshot(source, source.Path);
|
||||
manifest.ModifiedAtUtc = DateTimeOffset.UtcNow;
|
||||
|
||||
@@ -132,8 +132,7 @@ public sealed partial class VisualBriefingStore
|
||||
await WriteTextAtomicAsync(
|
||||
Path.Combine(this.VersionsDirectory(manifest.BriefingId), version.FileName),
|
||||
html,
|
||||
token,
|
||||
overwrite: false);
|
||||
overwrite: false, token);
|
||||
|
||||
manifest.Versions.Add(version);
|
||||
if (request.EditMode is not (VisualBriefingEditMode.CHANGE_DESIGN or VisualBriefingEditMode.RECOMPILE))
|
||||
@@ -357,7 +356,7 @@ public sealed partial class VisualBriefingStore
|
||||
var storedVersion = await this.OpenIntegrityCheckedVersionAsync(existing.BriefingId, knownRevision.RevisionId, token);
|
||||
if (storedVersion is null)
|
||||
{
|
||||
await WriteTextAtomicAsync(this.VersionPath(existing.BriefingId, knownRevision), html, token);
|
||||
await WriteTextAtomicAsync(this.VersionPath(existing.BriefingId, knownRevision), html, overwrite: true, token);
|
||||
var restoredHashes = ComputeSectionHashes(parts);
|
||||
knownRevision.DataHash = restoredHashes.DataHash;
|
||||
knownRevision.AssetHash = restoredHashes.AssetHash;
|
||||
@@ -415,8 +414,7 @@ public sealed partial class VisualBriefingStore
|
||||
await WriteTextAtomicAsync(
|
||||
Path.Combine(this.VersionsDirectory(existing.BriefingId), version.FileName),
|
||||
html,
|
||||
token,
|
||||
overwrite: false);
|
||||
overwrite: false, token);
|
||||
|
||||
existing.Versions.Add(version);
|
||||
existing.ModifiedAtUtc = DateTimeOffset.UtcNow;
|
||||
|
||||
@@ -107,17 +107,16 @@ public sealed partial class VisualBriefingStore(
|
||||
string json,
|
||||
CancellationToken token)
|
||||
{
|
||||
await WriteTextAtomicAsync(path, json, token, overwrite: false);
|
||||
await WriteTextAtomicAsync(path, json, overwrite: false, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines <c>WriteTextAtomicAsync</c> for the visual briefing feature.
|
||||
/// </summary>
|
||||
private static async Task WriteTextAtomicAsync(
|
||||
string targetPath,
|
||||
private static async Task WriteTextAtomicAsync(string targetPath,
|
||||
string content,
|
||||
CancellationToken token,
|
||||
bool overwrite = true)
|
||||
bool overwrite,
|
||||
CancellationToken token)
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetPath)!);
|
||||
var temporaryPath = $"{targetPath}.tmp-{Guid.NewGuid():N}";
|
||||
|
||||
Reference in new issue
Block a user