mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-11-23 09:30:21 +00:00
Merge 2d28105865 into 8b0ee49ba9
This commit is contained in:
commit
9df7d8aed6
@ -0,0 +1,99 @@
|
||||
@attribute [Route(Routes.ASSISTANT_DOCUMENT_ANALYSIS)]
|
||||
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogDocumentAnalysis>
|
||||
|
||||
@using AIStudio.Settings.DataModel
|
||||
|
||||
<PreviewPrototype/>
|
||||
<div class="mb-6"></div>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mb-3">
|
||||
@T("Document analysis policies")
|
||||
</MudText>
|
||||
|
||||
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||
@T("Here you have the option to save different policies for various document analysis assistants and switch between them.")
|
||||
</MudJustifiedText>
|
||||
|
||||
@if(this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Count is 0)
|
||||
{
|
||||
<MudText Typo="Typo.body1" Class="mb-3">
|
||||
@T("You have not yet added any document analysis policies.")
|
||||
</MudText>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudList T="DataDocumentAnalysisPolicy" Class="mb-1" SelectedValue="@this.selectedPolicy" SelectedValueChanged="@this.SelectedPolicyChanged">
|
||||
@foreach (var policy in this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies)
|
||||
{
|
||||
<MudListItem T="DataDocumentAnalysisPolicy" Icon="@Icons.Material.Filled.Policy" Value="@policy">
|
||||
@policy.PolicyName
|
||||
</MudListItem>
|
||||
}
|
||||
</MudList>
|
||||
}
|
||||
|
||||
<MudStack Row="@true" Class="mt-1">
|
||||
<MudButton OnClick="@this.AddPolicy" Variant="Variant.Filled" Color="Color.Primary">
|
||||
@T("Add policy")
|
||||
</MudButton>
|
||||
<MudButton OnClick="@this.RemovePolicy" Disabled="@(this.selectedPolicy?.IsProtected ?? true)" Variant="Variant.Filled" Color="Color.Error">
|
||||
@T("Delete this policy")
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
|
||||
<MudExpansionPanels Class="mb-3 mt-6" MultiExpansion="@false">
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Policy" HeaderText="@(T("Policy definition") + $": {this.selectedPolicy?.PolicyName}")" IsExpanded="@(!this.selectedPolicy?.IsProtected ?? true)">
|
||||
<MudText Typo="Typo.h4" Class="mb-1">
|
||||
@T("Common settings")
|
||||
</MudText>
|
||||
|
||||
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyName" Validation="@this.ValidatePolicyName" Immediate="@true" Label="@T("Policy name")" HelperText="@T("Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio.")" Counter="60" MaxLength="60" Variant="Variant.Outlined" Margin="Margin.Normal" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3" OnKeyUp="() => this.PolicyNameWasChanged()"/>
|
||||
|
||||
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyDescription" Validation="@this.ValidatePolicyDescription" Immediate="@true" Label="@T("Policy description")" HelperText="@T("Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio.")" Counter="512" MaxLength="512" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||
|
||||
<MudTextSwitch Disabled="@(this.IsNoPolicySelected || (this.selectedPolicy?.IsManaged ?? true))" Label="@T("Would you like to protect this policy so that you cannot accidentally edit or delete it?")" Value="@this.policyIsProtected" ValueChanged="async state => await this.PolicyProtectionWasChanged(state)" LabelOn="@T("Yes, protect this policy")" LabelOff="@T("No, the policy can be edited")" />
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mt-6 mb-1">
|
||||
@T("Input and output rules")
|
||||
</MudText>
|
||||
|
||||
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyAnalysisRules" Validation="@this.ValidateAnalysisRules" Immediate="@true" Label="@T("Analysis rules")" HelperText="@T("Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="5" AutoGrow="@true" MaxLines="26" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||
|
||||
<ReadFileContent Text="@T("Load analysis rules from document")" @bind-FileContent="@this.policyAnalysisRules"/>
|
||||
|
||||
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyOutputRules" Validation="@this.ValidateOutputRules" Immediate="@true" Label="@T("Output rules")" HelperText="@T("Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="5" AutoGrow="@true" MaxLines="26" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||
|
||||
<ReadFileContent Text="@T("Load output rules from document")" @bind-FileContent="@this.policyOutputRules"/>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mt-6 mb-1">
|
||||
@T("Preparation for enterprise distribution")
|
||||
</MudText>
|
||||
|
||||
<MudTooltip Text="@T("Not implemented yet.")">
|
||||
<MudButton StartIcon="@Icons.Material.Filled.FileDownload" Disabled="true" Variant="Variant.Filled" Color="Color.Primary" OnClick="@this.ExportPolicyAsConfiguration">
|
||||
@T("Export policy as configuration section")
|
||||
</MudButton>
|
||||
</MudTooltip>
|
||||
</ExpansionPanel>
|
||||
|
||||
<MudDivider Style="height: 0.25ch; margin: 1rem 0;" Class="mt-6" />
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.DocumentScanner" HeaderText="@(T("Document analysis") + $": {this.selectedPolicy?.PolicyName}")" IsExpanded="@(this.selectedPolicy?.IsProtected ?? false)">
|
||||
<MudText Typo="Typo.h4" Class="mb-1">
|
||||
@T("Description")
|
||||
</MudText>
|
||||
|
||||
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||
@this.selectedPolicy?.PolicyDescription
|
||||
</MudJustifiedText>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mb-1 mt-6">
|
||||
@T("Documents for the analysis")
|
||||
</MudText>
|
||||
|
||||
<AttachDocuments Name="Document Analysis Files Drop" @bind-DocumentPaths="@this.loadedDocumentPaths" CatchAllDocuments="true"/>
|
||||
|
||||
</ExpansionPanel>
|
||||
</MudExpansionPanels>
|
||||
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
||||
@ -0,0 +1,366 @@
|
||||
using System.Text;
|
||||
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||
|
||||
namespace AIStudio.Assistants.DocumentAnalysis;
|
||||
|
||||
public partial class DocumentAnalysisAssistant : AssistantBaseCore<SettingsDialogDocumentAnalysis>
|
||||
{
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
public override Tools.Components Component => Tools.Components.DOCUMENT_ANALYSIS_ASSISTANT;
|
||||
|
||||
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.");
|
||||
|
||||
protected override string SystemPrompt
|
||||
{
|
||||
get
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append("# Task description");
|
||||
sb.AppendLine();
|
||||
|
||||
if (this.loadedDocumentPaths.Count > 1)
|
||||
{
|
||||
sb.Append($"Your task is to analyse {this.loadedDocumentPaths.Count} documents.");
|
||||
sb.Append("Different Documents are divided by a horizontal rule in markdown formatting followed by the name of the document.");
|
||||
sb.AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append("Your task is to analyse a single document.");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
var taskDescription = """
|
||||
The analysis should be done using the policy analysis rules.
|
||||
The output should be formatted according to the policy output rules.
|
||||
The rule sets should be followed strictly.
|
||||
Only use information given in the documents or in the policy.
|
||||
Never add any information of your own to it.
|
||||
Keep your answers precise, professional and factual.
|
||||
Only answer with the correctly formatted analysis result and do not add any opening or closing remarks.
|
||||
Answer in the language that is used by the policy or is stated in the output rules.
|
||||
""";
|
||||
|
||||
sb.Append(taskDescription);
|
||||
sb.AppendLine();
|
||||
|
||||
sb.Append(this.PromptGetActivePolicy());
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons => [];
|
||||
|
||||
protected override bool ShowEntireChatThread => true;
|
||||
|
||||
protected override bool ShowSendTo => true;
|
||||
|
||||
protected override string SubmitText => T("Analyze documents");
|
||||
|
||||
protected override Func<Task> SubmitAction => this.Analyze;
|
||||
|
||||
protected override bool SubmitDisabled => (this.IsNoPolicySelected || this.loadedDocumentPaths.Count==0);
|
||||
|
||||
protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with
|
||||
{
|
||||
SystemPrompt = SystemPrompts.DEFAULT,
|
||||
};
|
||||
|
||||
protected override void ResetForm()
|
||||
{
|
||||
if (!this.MightPreselectValues())
|
||||
{
|
||||
this.policyName = string.Empty;
|
||||
this.policyDescription = string.Empty;
|
||||
this.policyIsProtected = false;
|
||||
this.policyAnalysisRules = string.Empty;
|
||||
this.policyOutputRules = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool MightPreselectValues()
|
||||
{
|
||||
if (this.selectedPolicy is not null)
|
||||
{
|
||||
this.policyName = this.selectedPolicy.PolicyName;
|
||||
this.policyDescription = this.selectedPolicy.PolicyDescription;
|
||||
this.policyIsProtected = this.selectedPolicy.IsProtected;
|
||||
this.policyAnalysisRules = this.selectedPolicy.AnalysisRules;
|
||||
this.policyOutputRules = this.selectedPolicy.OutputRules;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override async Task OnFormChange()
|
||||
{
|
||||
await this.AutoSave();
|
||||
}
|
||||
|
||||
#region Overrides of AssistantBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
this.selectedPolicy = this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.FirstOrDefault();
|
||||
if(this.selectedPolicy is null)
|
||||
{
|
||||
await this.AddPolicy();
|
||||
this.selectedPolicy = this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.First();
|
||||
}
|
||||
|
||||
var receivedDeferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_DOCUMENT_ANALYSIS_ASSISTANT).FirstOrDefault();
|
||||
if (receivedDeferredContent is not null)
|
||||
this.deferredContent = receivedDeferredContent;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task AutoSave(bool force = false)
|
||||
{
|
||||
if(this.selectedPolicy is null)
|
||||
return;
|
||||
|
||||
if(!force && this.selectedPolicy.IsProtected)
|
||||
return;
|
||||
|
||||
if(!force && this.policyIsProtected)
|
||||
return;
|
||||
|
||||
this.selectedPolicy.PreselectedProvider = this.providerSettings.Id;
|
||||
|
||||
this.selectedPolicy.PolicyName = this.policyName;
|
||||
this.selectedPolicy.PolicyDescription = this.policyDescription;
|
||||
this.selectedPolicy.IsProtected = this.policyIsProtected;
|
||||
this.selectedPolicy.AnalysisRules = this.policyAnalysisRules;
|
||||
this.selectedPolicy.OutputRules = this.policyOutputRules;
|
||||
|
||||
await this.SettingsManager.StoreSettings();
|
||||
}
|
||||
|
||||
private DataDocumentAnalysisPolicy? selectedPolicy;
|
||||
private bool policyIsProtected;
|
||||
private string policyName = string.Empty;
|
||||
private string policyDescription = string.Empty;
|
||||
private string policyAnalysisRules = string.Empty;
|
||||
private string policyOutputRules = string.Empty;
|
||||
#warning Use deferred content for document analysis
|
||||
private string deferredContent = string.Empty;
|
||||
private HashSet<string> loadedDocumentPaths = [];
|
||||
|
||||
private bool IsNoPolicySelectedOrProtected => this.selectedPolicy is null || this.selectedPolicy.IsProtected;
|
||||
|
||||
private bool IsNoPolicySelected => this.selectedPolicy is null;
|
||||
|
||||
private void SelectedPolicyChanged(DataDocumentAnalysisPolicy? policy)
|
||||
{
|
||||
this.selectedPolicy = policy;
|
||||
this.ResetForm();
|
||||
}
|
||||
|
||||
private async Task AddPolicy()
|
||||
{
|
||||
this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Add(new ()
|
||||
{
|
||||
PolicyName = string.Format(T("Policy {0}"), DateTimeOffset.UtcNow),
|
||||
});
|
||||
|
||||
await this.SettingsManager.StoreSettings();
|
||||
}
|
||||
|
||||
private async Task RemovePolicy()
|
||||
{
|
||||
if(this.selectedPolicy is null)
|
||||
return;
|
||||
|
||||
if(this.selectedPolicy.IsProtected)
|
||||
return;
|
||||
|
||||
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||
{
|
||||
{ x => x.Message, string.Format(T("Are you sure you want to delete the document analysis policy '{0}'?"), this.selectedPolicy.PolicyName) },
|
||||
};
|
||||
|
||||
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Delete document analysis policy"), dialogParameters, DialogOptions.FULLSCREEN);
|
||||
var dialogResult = await dialogReference.Result;
|
||||
if (dialogResult is null || dialogResult.Canceled)
|
||||
return;
|
||||
|
||||
this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Remove(this.selectedPolicy);
|
||||
this.selectedPolicy = null;
|
||||
this.ResetForm();
|
||||
|
||||
await this.SettingsManager.StoreSettings();
|
||||
this.form?.ResetValidation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the policy name was changed by typing.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is used to update the policy name in the selected policy.
|
||||
/// Otherwise, the users would be confused when they change the name and the changes are not reflected in the UI.
|
||||
/// </remarks>
|
||||
private void PolicyNameWasChanged()
|
||||
{
|
||||
if(this.selectedPolicy is null)
|
||||
return;
|
||||
|
||||
if(this.selectedPolicy.IsProtected)
|
||||
return;
|
||||
|
||||
this.selectedPolicy.PolicyName = this.policyName;
|
||||
}
|
||||
|
||||
private async Task PolicyProtectionWasChanged(bool state)
|
||||
{
|
||||
if(this.selectedPolicy is null)
|
||||
return;
|
||||
|
||||
this.policyIsProtected = state;
|
||||
this.selectedPolicy.IsProtected = state;
|
||||
await this.AutoSave(true);
|
||||
}
|
||||
|
||||
private string? ValidatePolicyName(string name)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(name))
|
||||
return T("Please provide a name for your policy. This name will be used to identify the policy in AI Studio.");
|
||||
|
||||
if(name.Length is > 60 or < 6)
|
||||
return T("The name of your policy must be between 6 and 60 characters long.");
|
||||
|
||||
if(this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Where(n => n != this.selectedPolicy).Any(n => n.PolicyName == name))
|
||||
return T("A policy with this name already exists. Please choose a different name.");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidatePolicyDescription(string description)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(description))
|
||||
return T("Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.");
|
||||
|
||||
if(description.Length is < 32 or > 512)
|
||||
return T("The description of your policy must be between 32 and 512 characters long.");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateAnalysisRules(string analysisRules)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(analysisRules))
|
||||
return T("Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateOutputRules(string outputRules)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(outputRules))
|
||||
return T("Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis.");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string PromptGetActivePolicy()
|
||||
{
|
||||
return $"""
|
||||
# Policy
|
||||
The policy is defined as follows:
|
||||
|
||||
## Policy name
|
||||
{this.policyName}
|
||||
|
||||
## Policy description
|
||||
{this.policyDescription}
|
||||
|
||||
## Policy analysis rules
|
||||
{this.policyAnalysisRules}
|
||||
|
||||
## Policy output rules
|
||||
{this.policyOutputRules}
|
||||
""";
|
||||
}
|
||||
|
||||
private async Task<string> PromptLoadDocumentsContent()
|
||||
{
|
||||
if (this.loadedDocumentPaths.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
var count = 1;
|
||||
foreach(var documentPath in this.loadedDocumentPaths)
|
||||
{
|
||||
sb.Append("---");
|
||||
sb.AppendLine();
|
||||
sb.Append($"Document {count} file path: {documentPath}");
|
||||
sb.AppendLine();
|
||||
sb.Append($"Document {count} content:");
|
||||
sb.AppendLine();
|
||||
|
||||
var fileContent = await this.RustService.ReadArbitraryFileData(documentPath, int.MaxValue);
|
||||
sb.Append($"""
|
||||
```
|
||||
{fileContent}
|
||||
```
|
||||
""");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine();
|
||||
count += 1;
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private async Task Analyze()
|
||||
{
|
||||
// if (this.IsNoPolicySelectedOrProtected)
|
||||
// return;
|
||||
|
||||
await this.AutoSave();
|
||||
await this.form!.Validate();
|
||||
if (!this.inputIsValid)
|
||||
return;
|
||||
|
||||
this.CreateChatThread();
|
||||
|
||||
var userRequest = this.AddUserRequest(
|
||||
$"""
|
||||
{await this.PromptLoadDocumentsContent()}
|
||||
""", hideContentFromUser:true);
|
||||
|
||||
await this.AddAIResponseAsync(userRequest);
|
||||
}
|
||||
|
||||
private async Task ExportPolicyAsConfiguration()
|
||||
{
|
||||
return;
|
||||
|
||||
# warning Implement the export function
|
||||
// do not allow the export of a protected policy
|
||||
if (this.IsNoPolicySelectedOrProtected)
|
||||
return;
|
||||
|
||||
await this.AutoSave();
|
||||
await this.form!.Validate();
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
@attribute [Route(Routes.ASSISTANT_ERI)]
|
||||
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogERIServer>
|
||||
|
||||
@using AIStudio.Settings.DataModel
|
||||
@using MudExtensions
|
||||
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogERIServer>
|
||||
|
||||
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||
@T("You can imagine it like this: Hypothetically, when Wikipedia implemented the ERI, it would vectorize all pages using an embedding method. All of Wikipedia’s data would remain with Wikipedia, including the vector database (decentralized approach). Then, any AI Studio user could add Wikipedia as a data source to significantly reduce the hallucination of the LLM in knowledge questions.")
|
||||
|
||||
@ -382,6 +382,120 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T
|
||||
-- None
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T810547195"] = "None"
|
||||
|
||||
-- Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1182372158"] = "Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio."
|
||||
|
||||
-- No, the policy can be edited
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1286595725"] = "No, the policy can be edited"
|
||||
|
||||
-- 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."
|
||||
|
||||
-- Not implemented yet.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1568777658"] = "Not implemented yet."
|
||||
|
||||
-- Input and output rules
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Input and output rules"
|
||||
|
||||
-- Description
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1725856265"] = "Description"
|
||||
|
||||
-- Yes, protect this policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy"
|
||||
|
||||
-- Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1786783201"] = "Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio."
|
||||
|
||||
-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy."
|
||||
|
||||
-- Common settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings"
|
||||
|
||||
-- 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.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "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."
|
||||
|
||||
-- Document analysis policies
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2064879144"] = "Document analysis policies"
|
||||
|
||||
-- Load output rules from document
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2168201568"] = "Load output rules from document"
|
||||
|
||||
-- The name of your policy must be between 6 and 60 characters long.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "The name of your policy must be between 6 and 60 characters long."
|
||||
|
||||
-- Policy definition
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2491168104"] = "Policy definition"
|
||||
|
||||
-- Export policy as configuration section
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2556564432"] = "Export policy as configuration section"
|
||||
|
||||
-- Are you sure you want to delete the document analysis policy '{0}'?
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2582525917"] = "Are you sure you want to delete the document analysis policy '{0}'?"
|
||||
|
||||
-- Document analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2708005534"] = "Document analysis"
|
||||
|
||||
-- Policy name
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name"
|
||||
|
||||
-- Analyze documents
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2894951609"] = "Analyze documents"
|
||||
|
||||
-- Documents for the analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3030664641"] = "Documents for the analysis"
|
||||
|
||||
-- Analysis rules
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3108719748"] = "Analysis rules"
|
||||
|
||||
-- Delete this policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3119086260"] = "Delete this policy"
|
||||
|
||||
-- Policy {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Policy {0}"
|
||||
|
||||
-- The description of your policy must be between 32 and 512 characters long.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "The description of your policy must be between 32 and 512 characters long."
|
||||
|
||||
-- Add policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3357792182"] = "Add policy"
|
||||
|
||||
-- You have not yet added any document analysis policies.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3394850216"] = "You have not yet added any document analysis policies."
|
||||
|
||||
-- Document Analysis Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T348883878"] = "Document Analysis Assistant"
|
||||
|
||||
-- A policy with this name already exists. Please choose a different name.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3584374593"] = "A policy with this name already exists. Please choose a different name."
|
||||
|
||||
-- Load analysis rules from document
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3813558135"] = "Load analysis rules from document"
|
||||
|
||||
-- Output rules
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3918193587"] = "Output rules"
|
||||
|
||||
-- Preparation for enterprise distribution
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T39557294"] = "Preparation for enterprise distribution"
|
||||
|
||||
-- Please provide a name for your policy. This name will be used to identify the policy in AI Studio.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4040507702"] = "Please provide a name for your policy. This name will be used to identify the policy in AI Studio."
|
||||
|
||||
-- Delete document analysis policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4293094335"] = "Delete document analysis policy"
|
||||
|
||||
-- Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T652187065"] = "Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis."
|
||||
|
||||
-- Policy description
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Policy description"
|
||||
|
||||
-- Would you like to protect this policy so that you cannot accidentally edit or delete it?
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T80597472"] = "Would you like to protect this policy so that you cannot accidentally edit or delete it?"
|
||||
|
||||
-- Here you have the option to save different policies for various document analysis assistants and switch between them.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Here you have the option to save different policies for various document analysis assistants and switch between them."
|
||||
|
||||
-- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input."
|
||||
|
||||
@ -1369,6 +1483,27 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Export C
|
||||
-- Open Settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Settings"
|
||||
|
||||
-- Drag and drop files here or click to attach documents.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T1647829151"] = "Drag and drop files here or click to attach documents."
|
||||
|
||||
-- Pandoc Load Document Preview
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2686523471"] = "Pandoc Load Document Preview"
|
||||
|
||||
-- Videos are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2928927510"] = "Videos are not supported yet"
|
||||
|
||||
-- Images are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T298062956"] = "Images are not supported yet"
|
||||
|
||||
-- Clear file list
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T3759696136"] = "Clear file list"
|
||||
|
||||
-- Executables are not allowed
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T4167762413"] = "Executables are not allowed"
|
||||
|
||||
-- Select a file to attach
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T595772870"] = "Select a file to attach"
|
||||
|
||||
-- Changelog
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHANGELOG::T3017574265"] = "Changelog"
|
||||
|
||||
@ -1672,6 +1807,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T185447014"] = "Pandoc I
|
||||
-- Pandoc may be required for importing files.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2596465560"] = "Pandoc may be required for importing files."
|
||||
|
||||
-- Videos are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos are not supported yet"
|
||||
|
||||
-- Images are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Images are not supported yet"
|
||||
|
||||
@ -2980,6 +3118,21 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T504404155"] = "Accept the ter
|
||||
-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and archive," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T523908375"] = "Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking \"Accept GPL and archive,\" you agree to the terms of the GPL license. Software under GPL is free of charge and free to use."
|
||||
|
||||
-- Test how Pandoc loads your document. See the raw content it produces before further processing.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T1481857352"] = "Test how Pandoc loads your document. See the raw content it produces before further processing."
|
||||
|
||||
-- Content Loaded by Pandoc
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2147198279"] = "Content Loaded by Pandoc"
|
||||
|
||||
-- This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2156541074"] = "This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected."
|
||||
|
||||
-- Load document
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2394358670"] = "Load document"
|
||||
|
||||
-- Cancel
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T900713019"] = "Cancel"
|
||||
|
||||
-- Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T1458195391"] = "Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally."
|
||||
|
||||
@ -3625,6 +3778,33 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473
|
||||
-- Local Directory
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory"
|
||||
|
||||
-- Assistant: Document Analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistant: Document Analysis"
|
||||
|
||||
-- Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1870328357"] = "Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function."
|
||||
|
||||
-- Would you like to preselect one of your profiles?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2221665527"] = "Would you like to preselect one of your profiles?"
|
||||
|
||||
-- Preselect document analysis options?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Preselect document analysis options?"
|
||||
|
||||
-- When enabled, you can preselect some document analysis options.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2301091111"] = "When enabled, you can preselect some document analysis options."
|
||||
|
||||
-- No document analysis options are preselected
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "No document analysis options are preselected"
|
||||
|
||||
-- Close
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3448155331"] = "Close"
|
||||
|
||||
-- Document analysis options are preselected
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3945756386"] = "Document analysis options are preselected"
|
||||
|
||||
-- Preselect one of your profiles?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T4004501229"] = "Preselect one of your profiles?"
|
||||
|
||||
-- When enabled, you can preselect some ERI server options.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options."
|
||||
|
||||
@ -4501,6 +4681,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T986578435"] = "Install Pandoc"
|
||||
-- Get coding and debugging support from an LLM.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1243850917"] = "Get coding and debugging support from an LLM."
|
||||
|
||||
-- Analyze a document regarding defined rules and extract key information.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1271524187"] = "Analyze a document regarding defined rules and extract key information."
|
||||
|
||||
-- Business
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T131837803"] = "Business"
|
||||
|
||||
@ -4546,6 +4729,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2547582747"] = "Synonyms"
|
||||
-- Find synonyms for a given word or phrase.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2712131461"] = "Find synonyms for a given word or phrase."
|
||||
|
||||
-- Document Analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2770149758"] = "Document Analysis"
|
||||
|
||||
-- AI Studio Development
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2830810750"] = "AI Studio Development"
|
||||
|
||||
@ -5068,6 +5254,9 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1587
|
||||
-- Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files
|
||||
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1847148141"] = "Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files"
|
||||
|
||||
-- Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents
|
||||
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1848209619"] = "Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents"
|
||||
|
||||
-- Plugins: Preview of our plugin system where you can extend the functionality of the app
|
||||
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2056842933"] = "Plugins: Preview of our plugin system where you can extend the functionality of the app"
|
||||
|
||||
@ -5188,6 +5377,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2684676843"] = "Text Su
|
||||
-- Synonym Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2921123194"] = "Synonym Assistant"
|
||||
|
||||
-- Document Analysis Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T348883878"] = "Document Analysis Assistant"
|
||||
|
||||
-- Translation Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T3887962308"] = "Translation Assistant"
|
||||
|
||||
@ -5638,6 +5830,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::RAG::RAGPROCESSES::AISRCSELWITHRETCTXVAL::T377
|
||||
-- Executable Files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2217313358"] = "Executable Files"
|
||||
|
||||
-- All Video Files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2850789856"] = "All Video Files"
|
||||
|
||||
-- PDF Files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T3108466742"] = "PDF Files"
|
||||
|
||||
|
||||
20
app/MindWork AI Studio/Components/AttachDocuments.razor
Normal file
20
app/MindWork AI Studio/Components/AttachDocuments.razor
Normal file
@ -0,0 +1,20 @@
|
||||
@inherits MSGComponentBase
|
||||
|
||||
<div @onmouseenter="@this.OnMouseEnter" @onmouseleave="@this.OnMouseLeave">
|
||||
<MudLink OnClick="@(() => this.AddFilesManually())" Style="text-decoration: none;">
|
||||
<MudPaper Height="20em" Outlined="true" Class="@this.dragClass" Style="overflow-y: auto;">
|
||||
<MudText Typo="Typo.h6">
|
||||
@T("Drag and drop files here or click to attach documents.")
|
||||
</MudText>
|
||||
@foreach (var fileInfo in this.DocumentPaths.Select(file => new FileInfo(file)))
|
||||
{
|
||||
<MudBadge Origin="Origin.TopCenter" Icon="@Icons.Material.Filled.Search" Color="Color.Primary" Overlap="true" Bordered="true" OnClick="@(() => this.InvestigateFile(@fileInfo))">
|
||||
<MudChip T="string" Color="Color.Dark" Text="@fileInfo.Name" tabindex="-1" Icon="@Icons.Material.Filled.Search" OnClick="@(() => this.InvestigateFile(@fileInfo))" OnClose="@(() => this.RemoveDocumentPathFromDocumentPaths(@fileInfo))"/>
|
||||
</MudBadge>
|
||||
}
|
||||
</MudPaper>
|
||||
</MudLink>
|
||||
<MudButton OnClick="@(async () => await this.ClearAllFiles())" Variant="Variant.Filled" Color="Color.Info" Class="mt-2" StartIcon="@Icons.Material.Filled.Delete">
|
||||
@T("Clear file list")
|
||||
</MudButton>
|
||||
</div>
|
||||
185
app/MindWork AI Studio/Components/AttachDocuments.razor.cs
Normal file
185
app/MindWork AI Studio/Components/AttachDocuments.razor.cs
Normal file
@ -0,0 +1,185 @@
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Tools.Rust;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
|
||||
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||
|
||||
public partial class AttachDocuments : MSGComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public HashSet<string> DocumentPaths { get; set; } = [];
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<HashSet<string>> DocumentPathsChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<HashSet<string>, Task> OnChange { get; set; } = _ => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Catch all documents that are hovered over the AI Studio window and not only over the drop zone.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool CatchAllDocuments { get; set; }
|
||||
|
||||
[Inject]
|
||||
private ILogger<AttachDocuments> Logger { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private RustService RustService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
#region Overrides of MSGComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
this.ApplyFilters([], [ Event.TAURI_EVENT_RECEIVED ]);
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
protected override async Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
|
||||
{
|
||||
switch (triggeredEvent)
|
||||
{
|
||||
case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_HOVERED }:
|
||||
if(!this.isComponentHovered && !this.CatchAllDocuments)
|
||||
{
|
||||
this.Logger.LogDebug("Attach documents component '{Name}' is not hovered, ignoring file drop hovered event.", this.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
this.SetDragClass();
|
||||
this.StateHasChanged();
|
||||
break;
|
||||
|
||||
case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_DROPPED, Payload: var paths }:
|
||||
if(!this.isComponentHovered && !this.CatchAllDocuments)
|
||||
{
|
||||
this.Logger.LogDebug("Attach documents component '{Name}' is not hovered, ignoring file drop dropped event.", this.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var path in paths)
|
||||
{
|
||||
if(!await this.IsFileExtensionValid(path))
|
||||
continue;
|
||||
|
||||
this.DocumentPaths.Add(path);
|
||||
}
|
||||
|
||||
await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths);
|
||||
await this.OnChange(this.DocumentPaths);
|
||||
this.StateHasChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private const string DEFAULT_DRAG_CLASS = "relative rounded-lg border-2 border-dashed pa-4 mt-4 mud-width-full mud-height-full";
|
||||
|
||||
private string dragClass = DEFAULT_DRAG_CLASS;
|
||||
|
||||
private bool isComponentHovered;
|
||||
|
||||
private async Task AddFilesManually()
|
||||
{
|
||||
var selectedFile = await this.RustService.SelectFile(T("Select a file to attach"));
|
||||
if (selectedFile.UserCancelled)
|
||||
return;
|
||||
|
||||
if (!File.Exists(selectedFile.SelectedFilePath))
|
||||
return;
|
||||
|
||||
if (!await this.IsFileExtensionValid(selectedFile.SelectedFilePath))
|
||||
return;
|
||||
|
||||
this.DocumentPaths.Add(selectedFile.SelectedFilePath);
|
||||
await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths);
|
||||
await this.OnChange(this.DocumentPaths);
|
||||
}
|
||||
|
||||
private async Task<bool> IsFileExtensionValid(string selectedFile)
|
||||
{
|
||||
var ext = Path.GetExtension(selectedFile).TrimStart('.');
|
||||
if (Array.Exists(FileTypeFilter.Executables.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.AppBlocking, this.T("Executables are not allowed")));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Array.Exists(FileTypeFilter.AllImages.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.ImageNotSupported, this.T("Images are not supported yet")));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Array.Exists(FileTypeFilter.AllVideos.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.FeaturedVideo, this.T("Videos are not supported yet")));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task ClearAllFiles()
|
||||
{
|
||||
this.DocumentPaths.Clear();
|
||||
await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths);
|
||||
await this.OnChange(this.DocumentPaths);
|
||||
}
|
||||
|
||||
private void SetDragClass() => this.dragClass = $"{DEFAULT_DRAG_CLASS} mud-border-primary border-4";
|
||||
|
||||
private void ClearDragClass() => this.dragClass = DEFAULT_DRAG_CLASS;
|
||||
|
||||
private void OnMouseEnter(EventArgs _)
|
||||
{
|
||||
this.Logger.LogDebug("Attach documents component '{Name}' is hovered.", this.Name);
|
||||
this.isComponentHovered = true;
|
||||
this.SetDragClass();
|
||||
this.StateHasChanged();
|
||||
}
|
||||
|
||||
private void OnMouseLeave(EventArgs _)
|
||||
{
|
||||
this.Logger.LogDebug("Attach documents component '{Name}' is no longer hovered.", this.Name);
|
||||
this.isComponentHovered = false;
|
||||
this.ClearDragClass();
|
||||
this.StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task RemoveDocumentPathFromDocumentPaths(FileInfo file)
|
||||
{
|
||||
this.DocumentPaths.Remove(file.ToString());
|
||||
|
||||
await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths);
|
||||
await this.OnChange(this.DocumentPaths);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The user might want to check what the Pandoc integration actually extracts from his file and therefore gives the LLM as input.
|
||||
/// </summary>
|
||||
/// <param name="file">The file to check.</param>
|
||||
private async Task InvestigateFile(FileInfo file)
|
||||
{
|
||||
# warning Implement Investigation of file
|
||||
|
||||
var dialogParameters = new DialogParameters<PandocDocumentCheckDialog>{};
|
||||
|
||||
var dialogReference = await this.DialogService.ShowAsync<PandocDocumentCheckDialog>(T("Pandoc Load Document Preview"), dialogParameters, DialogOptions.FULLSCREEN);
|
||||
var dialogResult = await dialogReference.Result;
|
||||
if (dialogResult is null || dialogResult.Canceled)
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,11 @@
|
||||
@inherits MSGComponentBase
|
||||
<MudButton StartIcon="@Icons.Material.Filled.Description" OnClick="async () => await this.SelectFile()" Variant="Variant.Filled" Class="mb-3">
|
||||
@if (string.IsNullOrWhiteSpace(this.Text))
|
||||
{
|
||||
@T("Use file content as input")
|
||||
}
|
||||
else
|
||||
{
|
||||
@this.Text
|
||||
}
|
||||
</MudButton>
|
||||
@ -10,6 +10,9 @@ namespace AIStudio.Components;
|
||||
|
||||
public partial class ReadFileContent : MSGComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public string FileContent { get; set; } = string.Empty;
|
||||
|
||||
@ -47,6 +50,12 @@ public partial class ReadFileContent : MSGComponentBase
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.Exists(FileTypeFilter.AllVideos.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.FeaturedVideo, this.T("Videos are not supported yet")));
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that Pandoc is installed and ready:
|
||||
var pandocState = await Pandoc.CheckAvailabilityAsync(this.RustService, showSuccessMessage: false);
|
||||
if (!pandocState.IsAvailable)
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
@inherits MSGComponentBase
|
||||
|
||||
|
||||
<MudDialog>
|
||||
<DialogContent>
|
||||
<PreviewPrototype/>
|
||||
|
||||
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||
@T("Test how Pandoc loads your document. See the raw content it produces before further processing.")
|
||||
</MudJustifiedText>
|
||||
|
||||
<ReadFileContent Text="@T("Load document")" @bind-FileContent="@this.documentContent"/>
|
||||
|
||||
<MudTextField
|
||||
T="string"
|
||||
@bind-Text="@this.documentContent"
|
||||
AdornmentIcon="@Icons.Material.Filled.Article"
|
||||
Adornment="Adornment.Start"
|
||||
Immediate="@true"
|
||||
Label="@T("Content Loaded by Pandoc")"
|
||||
Variant="Variant.Outlined"
|
||||
Lines="6"
|
||||
AutoGrow="@true"
|
||||
MaxLines="25"
|
||||
Class="mt-10"
|
||||
HelperText="@T("This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected.")"
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="@this.Cancel" Variant="Variant.Filled">
|
||||
@T("Cancel")
|
||||
</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
@ -0,0 +1,20 @@
|
||||
using System.Formats.Asn1;
|
||||
using AIStudio.Components;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Dialogs;
|
||||
|
||||
/// <summary>
|
||||
/// Check how your file will be loaded by Pandoc.
|
||||
/// </summary>
|
||||
public partial class PandocDocumentCheckDialog : MSGComponentBase
|
||||
{
|
||||
[CascadingParameter]
|
||||
private IMudDialogInstance MudDialog { get; set; } = null!;
|
||||
|
||||
|
||||
private string documentContent = string.Empty;
|
||||
|
||||
private void Cancel() => this.MudDialog.Cancel();
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
@using AIStudio.Settings
|
||||
@inherits SettingsDialogBase
|
||||
|
||||
<MudDialog>
|
||||
<TitleContent>
|
||||
<PreviewPrototype/>
|
||||
<MudText Typo="Typo.h6" Class="d-flex align-center">
|
||||
<MudIcon Icon="@Icons.Material.Filled.DocumentScanner" Class="mr-2"/>
|
||||
@T("Assistant: Document Analysis")
|
||||
</MudText>
|
||||
</TitleContent>
|
||||
<DialogContent>
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<ConfigurationOption OptionDescription="@T("Preselect document analysis options?")" LabelOn="@T("Document analysis options are preselected")" LabelOff="@T("No document analysis options are preselected")" State="@(() => this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.ERI.PreselectOptions = updatedState)" OptionHelp="@T("When enabled, you can preselect some document analysis options.")"/>
|
||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.ERI.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.ERI.MinimumProviderConfidence = selectedValue)"/>
|
||||
<ConfigurationSelect OptionDescription="@T("Preselect one of your profiles?")" Disabled="@(() => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.ERI.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.ERI.PreselectedProfile = selectedValue)" OptionHelp="@T("Would you like to preselect one of your profiles?")"/>
|
||||
|
||||
<MudText Typo="Typo.body1" Class="mb-3">
|
||||
@T("Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function.")
|
||||
</MudText>
|
||||
</MudPaper>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="@this.Close" Variant="Variant.Filled">
|
||||
@T("Close")
|
||||
</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
@ -0,0 +1,3 @@
|
||||
namespace AIStudio.Dialogs.Settings;
|
||||
|
||||
public partial class SettingsDialogDocumentAnalysis : SettingsDialogBase;
|
||||
@ -61,6 +61,12 @@
|
||||
<ProjectReference Include="..\SourceCodeRules\SourceCodeRules\SourceCodeRules.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Dialogs\PandocDocumentCheckDialog.razor.cs">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Read the meta data file -->
|
||||
<Target Name="ReadMetaData" BeforeTargets="BeforeBuild">
|
||||
<Error Text="The ../../metadata.txt file was not found!" Condition="!Exists('../../metadata.txt')" />
|
||||
|
||||
@ -26,6 +26,12 @@
|
||||
</MudText>
|
||||
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
|
||||
<AssistantBlock TSettings="SettingsDialogWritingEMails" Name="@T("E-Mail")" Description="@T("Generate an e-mail for a given context.")" Icon="@Icons.Material.Filled.Email" Link="@Routes.ASSISTANT_EMAIL"/>
|
||||
|
||||
@if (PreviewFeatures.PRE_DOCUMENT_ANALYSIS_2025.IsEnabled(this.SettingsManager))
|
||||
{
|
||||
<AssistantBlock TSettings="SettingsDialogDocumentAnalysis" Name="@T("Document Analysis")" Description="@T("Analyze a document regarding defined rules and extract key information.")" Icon="@Icons.Material.Filled.DocumentScanner" Link="@Routes.ASSISTANT_DOCUMENT_ANALYSIS"/>
|
||||
}
|
||||
|
||||
<AssistantBlock TSettings="SettingsDialogMyTasks" Name="@T("My Tasks")" Description="@T("Analyze a text or an email for tasks you need to complete.")" Icon="@Icons.Material.Filled.Task" Link="@Routes.ASSISTANT_MY_TASKS"/>
|
||||
<AssistantBlock TSettings="SettingsDialogAgenda" Name="@T("Agenda Planner")" Description="@T("Generate an agenda for a given meeting, seminar, etc.")" Icon="@Icons.Material.Filled.CalendarToday" Link="@Routes.ASSISTANT_AGENDA"/>
|
||||
<AssistantBlock TSettings="SettingsDialogJobPostings" Name="@T("Job Posting")" Description="@T("Generate a job posting for a given job description.")" Icon="@Icons.Material.Filled.Work" Link="@Routes.ASSISTANT_JOB_POSTING"/>
|
||||
|
||||
@ -384,6 +384,120 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T
|
||||
-- None
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T810547195"] = "Keine"
|
||||
|
||||
-- Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1182372158"] = "Bitte geben Sie eine kurze Beschreibung Ihres Regelwerks an. Beschreiben oder erklären Sie, was das Regelwerk bewirkt. Diese Beschreibung wird den Benutzern in AI Studio angezeigt."
|
||||
|
||||
-- No, the policy can be edited
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1286595725"] = "Nein, das Regelwerk kann bearbeitet werden."
|
||||
|
||||
-- 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"] = "Bitte geben Sie eine Beschreibung Ihrer Analysekriterien an. Diese Regeln werden verwendet, um die KI anzuweisen, wie die Dokumente analysiert werden sollen."
|
||||
|
||||
-- Not implemented yet.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1568777658"] = "Noch nicht implementiert."
|
||||
|
||||
-- Analysis and output rules
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Analyse- und Ausgaberegeln"
|
||||
|
||||
-- Description
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1725856265"] = "Beschreibung"
|
||||
|
||||
-- Yes, protect this policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Ja, dieses Regelwerk schützen"
|
||||
|
||||
-- Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1786783201"] = "Bitte geben Sie Ihrem Regelwerk einen Namen, der den beabsichtigten Zweck beschreibt. Der Name wird den Nutzern in AI Studio angezeigt."
|
||||
|
||||
-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Bitte geben Sie eine Beschreibung für Ihr Regelwerk an. Diese Beschreibung wird verwendet, um Benutzer über den Zweck Ihres Regelwerks zur Dokumentenanalyse zu informieren."
|
||||
|
||||
-- Common settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Allgemeine Einstellungen"
|
||||
|
||||
-- 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.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "Der Assistent für Dokumentenanalysen hilft Ihnen dabei, Informationen aus Dokumenten basierend auf vordefinierten Regelwerken zu analysieren und zu extrahieren. Sie können Regelwerke für die Dokumentenanalyse erstellen, bearbeiten und verwalten, die festlegen, wie Dokumente verarbeitet werden und welche Informationen extrahiert werden sollen. Einige Regelwerke könnten durch Ihre Organisation geschützt sein und können nicht geändert oder gelöscht werden."
|
||||
|
||||
-- Document analysis policies
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2064879144"] = "Regelwerke zur Dokumentenanalyse"
|
||||
|
||||
-- Load output rules from document
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2168201568"] = "Regeln für die Ausgabe aus einem Dokument laden"
|
||||
|
||||
-- The name of your policy must be between 6 and 60 characters long.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "Der Name Ihres Regelwerks muss zwischen 6 und 60 Zeichen lang sein."
|
||||
|
||||
-- Policy definition
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2491168104"] = "Definition des Regelwerks"
|
||||
|
||||
-- Export policy as configuration section
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2556564432"] = "Exportieren Sie das Regelwerk als Konfigurationsabschnitt"
|
||||
|
||||
-- Are you sure you want to delete the document analysis policy '{0}'?
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2582525917"] = "Möchten Sie das Regelwerk '{0}' wirklich löschen?"
|
||||
|
||||
-- Document analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2708005534"] = "Dokumentenanalyse"
|
||||
|
||||
-- Policy name
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Name des Regelwerks"
|
||||
|
||||
-- Analyze documents
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2894951609"] = "Dokumente analysieren"
|
||||
|
||||
-- Documents for the analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3030664641"] = "Dokumente für die Analyse"
|
||||
|
||||
-- Analysis rules
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3108719748"] = "Regeln zur Analyse"
|
||||
|
||||
-- Delete this policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3119086260"] = "Dieses Regelwerk löschen"
|
||||
|
||||
-- Policy {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Regelwerk {0}"
|
||||
|
||||
-- The description of your policy must be between 32 and 512 characters long.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "Die Beschreibung des Regelwerks muss zwischen 32 und 512 Zeichen lang sein."
|
||||
|
||||
-- Add policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3357792182"] = "Regelwerk hinzufügen"
|
||||
|
||||
-- You have not yet added any document analysis policies.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3394850216"] = "Sie haben keine Regelwerke zur Dokumentenanalyse hinzugefügt."
|
||||
|
||||
-- Document Analysis Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T348883878"] = "Assistent für die Analyse von Dokumenten"
|
||||
|
||||
-- A policy with this name already exists. Please choose a different name.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3584374593"] = "Ein Regelwerk mit diesem Namen existiert bereits. Bitte wählen Sie einen anderen Namen."
|
||||
|
||||
-- Load analysis rules from document
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3813558135"] = "Regeln für die Analyse aus einem Dokument laden"
|
||||
|
||||
-- Output rules
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3918193587"] = "Regeln für die Ausgabe"
|
||||
|
||||
-- Preparation for enterprise distribution
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T39557294"] = "Vorbereitung für den Unternehmenseinsatz"
|
||||
|
||||
-- Please provide a name for your policy. This name will be used to identify the policy in AI Studio.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4040507702"] = "Bitte geben Sie einen Namen für Ihr Regelwerk an. Dieser Name wird verwendet, um das Regelwerk in AI Studio zu identifizieren."
|
||||
|
||||
-- Delete document analysis policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4293094335"] = "Regelwerk löschen"
|
||||
|
||||
-- Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T652187065"] = "Bitte geben Sie eine Beschreibung der Regeln für die Ausgabe an. Diese Regeln werden verwendet, um die KI anzuweisen, wie die Ausgabe der Analyse formatiert werden soll."
|
||||
|
||||
-- Policy description
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Regelwerkbeschreibung"
|
||||
|
||||
-- Would you like to protect this policy so that you cannot accidentally edit or delete it?
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T80597472"] = "Möchten Sie dieses Regelwerk schützen, damit Sie es nicht versehentlich bearbeiten oder löschen können?"
|
||||
|
||||
-- Here you have the option to save different policies for various document analysis assistants and switch between them.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Hier haben Sie die Möglichkeit, verschiedene Regelwerke für unterschiedliche Dokumentenanalysen zu speichern und zwischen ihnen zu wechseln."
|
||||
|
||||
-- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Geben Sie eine Liste von Stichpunkten sowie einige Basisinformationen für eine E-Mail ein. Der Assistent erstellt anschließend eine E-Mail auf Grundlage ihrer Angaben."
|
||||
|
||||
@ -1371,6 +1485,27 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Chat in
|
||||
-- Open Settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Einstellungen öffnen"
|
||||
|
||||
-- Drag and drop files here or click to attach documents.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T1647829151"] = "Dateien hierher ziehen und ablegen oder klicken, um Dokumente anzuhängen."
|
||||
|
||||
-- Pandoc Load Document Preview
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2686523471"] = "Pandoc-Dokumentvorschau"
|
||||
|
||||
-- Videos are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2928927510"] = "Videos werden noch nicht unterstützt."
|
||||
|
||||
-- Images are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T298062956"] = "Bilder werden noch nicht unterstützt."
|
||||
|
||||
-- Clear file list
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T3759696136"] = "Dateiliste löschen"
|
||||
|
||||
-- Executables are not allowed
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T4167762413"] = "Ausführbare Dateien sind nicht erlaubt"
|
||||
|
||||
-- Select a file to attach
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T595772870"] = "Datei zum Anhängen auswählen"
|
||||
|
||||
-- Changelog
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHANGELOG::T3017574265"] = "Änderungsprotokoll"
|
||||
|
||||
@ -1576,7 +1711,7 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T527187983"] = "
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T986578435"] = "Pandoc installieren"
|
||||
|
||||
-- Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1057189794"] = "Da mein Arbeitgeber sowohl Windows als auch Linux am Arbeitsplatz nutzt, wollte ich eine plattformübergreifende Lösung, die nahtlos auf allen wichtigen Betriebssystemen, einschließlich macOS, funktioniert. Außerdem wollte ich zeigen, dass es möglich ist, moderne, effiziente und plattformübergreifende Anwendungen zu erstellen, ohne auf Software-Balast, wie z.B. das Electron-Framework, zurückzugreifen. Die Kombination aus .NET und Rust mit Tauri hat sich dabei als hervorragender Technologiestapel für den Bau solch robuster Anwendungen erwiesen."
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1057189794"] = "Da mein Arbeitgeber sowohl Windows als auch Linux am Arbeitsplatz nutzt, wollte ich eine plattformübergreifende Lösung, die nahtlos auf allen wichtigen Betriebssystemen, einschließlich macOS, funktioniert. Außerdem wollte ich zeigen, dass es möglich ist, moderne, effiziente und plattformübergreifende Anwendungen zu erstellen, ohne auf Software-Ballast, wie z.B. das Electron-Framework, zurückzugreifen. Die Kombination aus .NET und Rust mit Tauri hat sich dabei als hervorragender Technologiestapel für den Bau solch robuster Anwendungen erwiesen."
|
||||
|
||||
-- Limitations of Existing Solutions
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1086130692"] = "Einschränkungen bestehender Lösungen"
|
||||
@ -1674,6 +1809,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T185447014"] = "Pandoc-I
|
||||
-- Pandoc may be required for importing files.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2596465560"] = "Pandoc wird möglicherweise zum Importieren von Dateien benötigt."
|
||||
|
||||
-- Videos are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos werden noch nicht unterstützt."
|
||||
|
||||
-- Images are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Bilder werden derzeit nicht unterstützt"
|
||||
|
||||
@ -2982,6 +3120,21 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T504404155"] = "Akzeptieren Si
|
||||
-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept the GPL and download the archive," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T523908375"] = "Pandoc wird unter der GNU General Public License v2 (GPL) vertrieben. Wenn Sie auf „GPL akzeptieren und Archiv herunterladen“ klicken, stimmen Sie den Bedingungen der GPL-Lizenz zu. Software unter der GPL ist kostenlos und frei nutzbar."
|
||||
|
||||
-- Test how Pandoc loads your document. See the raw content it produces before further processing.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T1481857352"] = "Testen Sie, wie Pandoc Ihr Dokument lädt, und überprüfen Sie ob der Inhalt korrekt geladen wird."
|
||||
|
||||
-- Content Loaded by Pandoc
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2147198279"] = "Von Pandoc geladener Inhalt"
|
||||
|
||||
-- This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2156541074"] = "Das ist der Inhalt, den Pandoc aus Ihrem Dokument geladen hat – einschließlich Überschriften, Listen und Formatierung. Überprüfen Sie damit, ob Ihr Dokument wie erwartet geladen wird."
|
||||
|
||||
-- Load document
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2394358670"] = "Dokument laden"
|
||||
|
||||
-- Cancel
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T900713019"] = "Abbrechen"
|
||||
|
||||
-- Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T1458195391"] = "Teilen Sie der KI mit, was sie machen soll. Was sind ihre Ziele oder was möchten Sie erreichen? Zum Beispiel, dass die KI Sie duzt."
|
||||
|
||||
@ -3627,6 +3780,33 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473
|
||||
-- Local Directory
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Lokaler Ordner"
|
||||
|
||||
-- Assistant: Document Analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistent: Dokumentenanalyse"
|
||||
|
||||
-- Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1870328357"] = "Die meisten Optionen für die Analyse von Dokumenten können im Assistenten angepasst und direkt gespeichert werden. Dafür verfügt der Assistent über eine automatische Speicherfunktion."
|
||||
|
||||
-- Would you like to preselect one of your profiles?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2221665527"] = "Möchten Sie eines Ihrer Profile vorab auswählen?"
|
||||
|
||||
-- Preselect document analysis options?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Dokumentenanalyse-Optionen vorab auswählen?"
|
||||
|
||||
-- When enabled, you can preselect some document analysis options.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2301091111"] = "Wenn aktiviert, können Sie einige Dokumentanalyse-Optionen vorab auswählen."
|
||||
|
||||
-- No document analysis options are preselected
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "Keine Dokumentenanalyse-Optionen sind vorausgewählt."
|
||||
|
||||
-- Close
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3448155331"] = "Schließen"
|
||||
|
||||
-- Document analysis options are preselected
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3945756386"] = "Dokumentenanalyse-Optionen sind vorausgewählt."
|
||||
|
||||
-- Preselect one of your profiles?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T4004501229"] = "Eines Ihrer Profile vorauswählen?"
|
||||
|
||||
-- When enabled, you can preselect some ERI server options.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "Wenn aktiviert, können Sie einige ERI-Serveroptionen vorauswählen."
|
||||
|
||||
@ -4503,6 +4683,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T986578435"] = "Pandoc installieren"
|
||||
-- Get coding and debugging support from an LLM.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1243850917"] = "Erhalten Sie Unterstützung beim Programmieren und Debuggen durch ein KI-Modell."
|
||||
|
||||
-- Analyze a document regarding defined rules and extract key information.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1271524187"] = "Analysiere ein Dokument hinsichtlich festgelegter Regeln und extrahiere wichtige Informationen."
|
||||
|
||||
-- Business
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T131837803"] = "Business"
|
||||
|
||||
@ -4548,6 +4731,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2547582747"] = "Synonyme"
|
||||
-- Find synonyms for a given word or phrase.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2712131461"] = "Finde Synonyme für ein angegebenes Wort oder eine Phrase."
|
||||
|
||||
-- Document Analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2770149758"] = "Dokumentenanalyse"
|
||||
|
||||
-- AI Studio Development
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2830810750"] = "AI Studio Entwicklung"
|
||||
|
||||
@ -4702,7 +4888,7 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T617579208"] = "Kostenlos"
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T649448159"] = "Unabhängigkeit"
|
||||
|
||||
-- No bloatware
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T858047957"] = "Keinen unnötigen Software-Balast"
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T858047957"] = "Keinen unnötigen Software-Ballast"
|
||||
|
||||
-- Here's what makes MindWork AI Studio stand out:
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T873851215"] = "Das zeichnet MindWork AI Studio aus:"
|
||||
@ -5070,6 +5256,9 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1587
|
||||
-- Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files
|
||||
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1847148141"] = "PDF-Dateien einlesen: Vorschau unseres PDF-Lesesystems, mit dem Sie Text aus PDF-Dateien einlesen können"
|
||||
|
||||
-- Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents
|
||||
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1848209619"] = "Dokumentenanalyse: Vorschau auf unsere Dokumentenanalyse, mit dem Sie Informationen aus Dokumenten analysieren und extrahieren können."
|
||||
|
||||
-- Plugins: Preview of our plugin system where you can extend the functionality of the app
|
||||
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2056842933"] = "Plugins: Vorschau auf unser Pluginsystems, mit dem Sie die Funktionalität der App erweitern können"
|
||||
|
||||
@ -5190,6 +5379,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2684676843"] = "Texte z
|
||||
-- Synonym Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2921123194"] = "Synonym-Assistent"
|
||||
|
||||
-- Document Analysis Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T348883878"] = "Dokumentenanalyse-Assistent"
|
||||
|
||||
-- Translation Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T3887962308"] = "Übersetzungs-Assistent"
|
||||
|
||||
@ -5640,6 +5832,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::RAG::RAGPROCESSES::AISRCSELWITHRETCTXVAL::T377
|
||||
-- Executable Files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2217313358"] = "Ausführbare Dateien"
|
||||
|
||||
-- All Video Files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2850789856"] = "Alle Videodateien"
|
||||
|
||||
-- PDF Files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T3108466742"] = "PDF-Dateien"
|
||||
|
||||
|
||||
@ -384,6 +384,120 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T
|
||||
-- None
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T810547195"] = "None"
|
||||
|
||||
-- Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1182372158"] = "Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio."
|
||||
|
||||
-- No, the policy can be edited
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1286595725"] = "No, the policy can be edited"
|
||||
|
||||
-- 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."
|
||||
|
||||
-- Not implemented yet.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1568777658"] = "Not implemented yet."
|
||||
|
||||
-- Analysis and output rules
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Analysis and output rules"
|
||||
|
||||
-- Description
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1725856265"] = "Description"
|
||||
|
||||
-- Yes, protect this policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy"
|
||||
|
||||
-- Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1786783201"] = "Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio."
|
||||
|
||||
-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy."
|
||||
|
||||
-- Common settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings"
|
||||
|
||||
-- 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.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "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."
|
||||
|
||||
-- Document analysis policies
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2064879144"] = "Document analysis policies"
|
||||
|
||||
-- Load output rules from document
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2168201568"] = "Load output rules from document"
|
||||
|
||||
-- The name of your policy must be between 6 and 60 characters long.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "The name of your policy must be between 6 and 60 characters long."
|
||||
|
||||
-- Policy definition
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2491168104"] = "Policy definition"
|
||||
|
||||
-- Export policy as configuration section
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2556564432"] = "Export policy as configuration section"
|
||||
|
||||
-- Are you sure you want to delete the document analysis policy '{0}'?
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2582525917"] = "Are you sure you want to delete the document analysis policy '{0}'?"
|
||||
|
||||
-- Document analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2708005534"] = "Document analysis"
|
||||
|
||||
-- Policy name
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name"
|
||||
|
||||
-- Analyze documents
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2894951609"] = "Analyze documents"
|
||||
|
||||
-- Documents for the analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3030664641"] = "Documents for the analysis"
|
||||
|
||||
-- Analysis rules
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3108719748"] = "Analysis rules"
|
||||
|
||||
-- Delete this policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3119086260"] = "Delete this policy"
|
||||
|
||||
-- Policy {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Policy {0}"
|
||||
|
||||
-- The description of your policy must be between 32 and 512 characters long.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "The description of your policy must be between 32 and 512 characters long."
|
||||
|
||||
-- Add policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3357792182"] = "Add policy"
|
||||
|
||||
-- You have not yet added any document analysis policies.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3394850216"] = "You have not yet added any document analysis policies."
|
||||
|
||||
-- Document Analysis Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T348883878"] = "Document Analysis Assistant"
|
||||
|
||||
-- A policy with this name already exists. Please choose a different name.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3584374593"] = "A policy with this name already exists. Please choose a different name."
|
||||
|
||||
-- Load analysis rules from document
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3813558135"] = "Load analysis rules from document"
|
||||
|
||||
-- Output rules
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3918193587"] = "Output rules"
|
||||
|
||||
-- Preparation for enterprise distribution
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T39557294"] = "Preparation for enterprise distribution"
|
||||
|
||||
-- Please provide a name for your policy. This name will be used to identify the policy in AI Studio.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4040507702"] = "Please provide a name for your policy. This name will be used to identify the policy in AI Studio."
|
||||
|
||||
-- Delete document analysis policy
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4293094335"] = "Delete document analysis policy"
|
||||
|
||||
-- Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T652187065"] = "Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis."
|
||||
|
||||
-- Policy description
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Policy description"
|
||||
|
||||
-- Would you like to protect this policy so that you cannot accidentally edit or delete it?
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T80597472"] = "Would you like to protect this policy so that you cannot accidentally edit or delete it?"
|
||||
|
||||
-- Here you have the option to save different policies for various document analysis assistants and switch between them.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Here you have the option to save different policies for various document analysis assistants and switch between them."
|
||||
|
||||
-- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input."
|
||||
|
||||
@ -1371,6 +1485,27 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Export C
|
||||
-- Open Settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Settings"
|
||||
|
||||
-- Drag and drop files here or click to attach documents.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T1647829151"] = "Drag and drop files here or click to attach documents."
|
||||
|
||||
-- Pandoc Load Document Preview
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2686523471"] = "Pandoc Load Document Preview"
|
||||
|
||||
-- Videos are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2928927510"] = "Videos are not supported yet"
|
||||
|
||||
-- Images are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T298062956"] = "Images are not supported yet"
|
||||
|
||||
-- Clear file list
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T3759696136"] = "Clear file list"
|
||||
|
||||
-- Executables are not allowed
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T4167762413"] = "Executables are not allowed"
|
||||
|
||||
-- Select a file to attach
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T595772870"] = "Select a file to attach"
|
||||
|
||||
-- Changelog
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHANGELOG::T3017574265"] = "Changelog"
|
||||
|
||||
@ -1674,6 +1809,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T185447014"] = "Pandoc I
|
||||
-- Pandoc may be required for importing files.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2596465560"] = "Pandoc may be required for importing files."
|
||||
|
||||
-- Videos are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos are not supported yet"
|
||||
|
||||
-- Images are not supported yet
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Images are not supported yet"
|
||||
|
||||
@ -2982,6 +3120,21 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T504404155"] = "Accept the ter
|
||||
-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept the GPL and download the archive," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T523908375"] = "Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking \"Accept the GPL and download the archive,\" you agree to the terms of the GPL license. Software under GPL is free of charge and free to use."
|
||||
|
||||
-- Test how Pandoc loads your document. See the raw content it produces before further processing.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T1481857352"] = "Test how Pandoc loads your document. See the raw content it produces before further processing."
|
||||
|
||||
-- Content Loaded by Pandoc
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2147198279"] = "Content Loaded by Pandoc"
|
||||
|
||||
-- This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2156541074"] = "This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected."
|
||||
|
||||
-- Load document
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2394358670"] = "Load document"
|
||||
|
||||
-- Cancel
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T900713019"] = "Cancel"
|
||||
|
||||
-- Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T1458195391"] = "Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally."
|
||||
|
||||
@ -3627,6 +3780,33 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473
|
||||
-- Local Directory
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory"
|
||||
|
||||
-- Assistant: Document Analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistant: Document Analysis"
|
||||
|
||||
-- Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1870328357"] = "Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function."
|
||||
|
||||
-- Would you like to preselect one of your profiles?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2221665527"] = "Would you like to preselect one of your profiles?"
|
||||
|
||||
-- Preselect document analysis options?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Preselect document analysis options?"
|
||||
|
||||
-- When enabled, you can preselect some document analysis options.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2301091111"] = "When enabled, you can preselect some document analysis options."
|
||||
|
||||
-- No document analysis options are preselected
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "No document analysis options are preselected"
|
||||
|
||||
-- Close
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3448155331"] = "Close"
|
||||
|
||||
-- Document analysis options are preselected
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3945756386"] = "Document analysis options are preselected"
|
||||
|
||||
-- Preselect one of your profiles?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T4004501229"] = "Preselect one of your profiles?"
|
||||
|
||||
-- When enabled, you can preselect some ERI server options.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options."
|
||||
|
||||
@ -4503,6 +4683,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T986578435"] = "Install Pandoc"
|
||||
-- Get coding and debugging support from an LLM.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1243850917"] = "Get coding and debugging support from an LLM."
|
||||
|
||||
-- Analyze a document regarding defined rules and extract key information.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1271524187"] = "Analyze a document regarding defined rules and extract key information."
|
||||
|
||||
-- Business
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T131837803"] = "Business"
|
||||
|
||||
@ -4548,6 +4731,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2547582747"] = "Synonyms"
|
||||
-- Find synonyms for a given word or phrase.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2712131461"] = "Find synonyms for a given word or phrase."
|
||||
|
||||
-- Document Analysis
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2770149758"] = "Document Analysis"
|
||||
|
||||
-- AI Studio Development
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2830810750"] = "AI Studio Development"
|
||||
|
||||
@ -5070,6 +5256,9 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1587
|
||||
-- Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files
|
||||
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1847148141"] = "Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files"
|
||||
|
||||
-- Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents
|
||||
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1848209619"] = "Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents"
|
||||
|
||||
-- Plugins: Preview of our plugin system where you can extend the functionality of the app
|
||||
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2056842933"] = "Plugins: Preview of our plugin system where you can extend the functionality of the app"
|
||||
|
||||
@ -5190,6 +5379,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2684676843"] = "Text Su
|
||||
-- Synonym Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2921123194"] = "Synonym Assistant"
|
||||
|
||||
-- Document Analysis Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T348883878"] = "Document Analysis Assistant"
|
||||
|
||||
-- Translation Assistant
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T3887962308"] = "Translation Assistant"
|
||||
|
||||
@ -5640,6 +5832,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::RAG::RAGPROCESSES::AISRCSELWITHRETCTXVAL::T377
|
||||
-- Executable Files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2217313358"] = "Executable Files"
|
||||
|
||||
-- All Video Files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2850789856"] = "All Video Files"
|
||||
|
||||
-- PDF Files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T3108466742"] = "PDF Files"
|
||||
|
||||
|
||||
@ -133,6 +133,11 @@ internal sealed class Program
|
||||
builder.Services.AddHostedService<UpdateService>();
|
||||
builder.Services.AddHostedService<TemporaryChatService>();
|
||||
builder.Services.AddHostedService<EnterpriseEnvironmentService>();
|
||||
|
||||
// ReSharper disable AccessToDisposedClosure
|
||||
builder.Services.AddHostedService<RustService>(_ => rust);
|
||||
// ReSharper restore AccessToDisposedClosure
|
||||
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents()
|
||||
.AddHubOptions(options =>
|
||||
|
||||
@ -27,5 +27,6 @@ public sealed partial class Routes
|
||||
public const string ASSISTANT_BIAS = "/assistant/bias-of-the-day";
|
||||
public const string ASSISTANT_ERI = "/assistant/eri";
|
||||
public const string ASSISTANT_AI_STUDIO_I18N = "/assistant/ai-studio/i18n";
|
||||
public const string ASSISTANT_DOCUMENT_ANALYSIS = "/assistant/document-analysis";
|
||||
// ReSharper restore InconsistentNaming
|
||||
}
|
||||
@ -85,6 +85,8 @@ public sealed class Data
|
||||
|
||||
public DataERI ERI { get; init; } = new();
|
||||
|
||||
public DataDocumentAnalysis DocumentAnalysis { get; init; } = new();
|
||||
|
||||
public DataTextSummarizer TextSummarizer { get; init; } = new();
|
||||
|
||||
public DataTextContentCleaner TextContentCleaner { get; init; } = new();
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
public sealed class DataDocumentAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// Configured document analysis policies.
|
||||
/// </summary>
|
||||
public List<DataDocumentAnalysisPolicy> Policies { get; set; } = [];
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
using AIStudio.Provider;
|
||||
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
public sealed class DataDocumentAnalysisPolicy
|
||||
{
|
||||
/// <summary>
|
||||
/// Preselect the policy name?
|
||||
/// </summary>
|
||||
public string PolicyName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Preselect the policy description?
|
||||
/// </summary>
|
||||
public string PolicyDescription { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Is this policy protected? If so, it cannot be deleted or modified by the user.
|
||||
/// </summary>
|
||||
public bool IsProtected { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is this a managed policy? Managed policies are created and managed by the organization
|
||||
/// and cannot be modified or deleted by the user.
|
||||
/// </summary>
|
||||
public bool IsManaged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The rules for the document analysis policy.
|
||||
/// </summary>
|
||||
public string AnalysisRules { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The rules for the output of the document analysis, e.g., the desired format, structure, etc.
|
||||
/// </summary>
|
||||
public string OutputRules { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum confidence level required for a provider to be considered.
|
||||
/// </summary>
|
||||
public ConfidenceLevel MinimumProviderConfidence { get; set; } = ConfidenceLevel.NONE;
|
||||
|
||||
/// <summary>
|
||||
/// Which LLM provider should be preselected?
|
||||
/// </summary>
|
||||
public string PreselectedProvider { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Preselect a profile?
|
||||
/// </summary>
|
||||
public string PreselectedProfile { get; set; } = string.Empty;
|
||||
}
|
||||
@ -11,4 +11,5 @@ public enum PreviewFeatures
|
||||
|
||||
PRE_PLUGINS_2025,
|
||||
PRE_READ_PDF_2025,
|
||||
PRE_DOCUMENT_ANALYSIS_2025,
|
||||
}
|
||||
@ -13,6 +13,7 @@ public static class PreviewFeaturesExtensions
|
||||
|
||||
PreviewFeatures.PRE_PLUGINS_2025 => TB("Plugins: Preview of our plugin system where you can extend the functionality of the app"),
|
||||
PreviewFeatures.PRE_READ_PDF_2025 => TB("Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files"),
|
||||
PreviewFeatures.PRE_DOCUMENT_ANALYSIS_2025 => TB("Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents"),
|
||||
|
||||
_ => TB("Unknown preview feature")
|
||||
};
|
||||
|
||||
@ -20,6 +20,7 @@ public static class PreviewVisibilityExtensions
|
||||
if (visibility >= PreviewVisibility.PROTOTYPE)
|
||||
{
|
||||
features.Add(PreviewFeatures.PRE_RAG_2024);
|
||||
features.Add(PreviewFeatures.PRE_DOCUMENT_ANALYSIS_2025);
|
||||
}
|
||||
|
||||
if (visibility >= PreviewVisibility.EXPERIMENTAL)
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
@ -9,6 +10,9 @@ namespace AIStudio.Settings;
|
||||
/// <remarks>
|
||||
/// When the target enum value does not exist, the value will be the default value.
|
||||
/// This converter handles enum values as property names and values.
|
||||
/// <br/><br/>
|
||||
/// We assume that enum names are in UPPER_SNAKE_CASE, and the JSON strings may be
|
||||
/// in any case style (e.g., camelCase, PascalCase, snake_case, UPPER_SNAKE_CASE, etc.)
|
||||
/// </remarks>
|
||||
public sealed class TolerantEnumConverter : JsonConverter<object>
|
||||
{
|
||||
@ -16,30 +20,46 @@ public sealed class TolerantEnumConverter : JsonConverter<object>
|
||||
|
||||
public override bool CanConvert(Type typeToConvert) => typeToConvert.IsEnum;
|
||||
|
||||
public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
public override object? Read(ref Utf8JsonReader reader, Type enumType, JsonSerializerOptions options)
|
||||
{
|
||||
// Is this token a string?
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
// Try to use that string as the name of the enum value:
|
||||
if (Enum.TryParse(typeToConvert, reader.GetString(), out var result))
|
||||
return result;
|
||||
var text = reader.GetString();
|
||||
|
||||
// In any other case, we will return the default enum value:
|
||||
LOG.LogWarning($"Cannot read '{reader.GetString()}' as '{typeToConvert.Name}' enum; token type: {reader.TokenType}");
|
||||
return Activator.CreateInstance(typeToConvert);
|
||||
// Convert the text to UPPER_SNAKE_CASE:
|
||||
text = ConvertToUpperSnakeCase(text);
|
||||
|
||||
// Try to parse the enum value:
|
||||
if (Enum.TryParse(enumType, text, out var result))
|
||||
return result;
|
||||
}
|
||||
|
||||
public override object ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
// In any other case, we will return the default enum value:
|
||||
LOG.LogWarning($"Cannot read '{reader.GetString()}' as '{enumType.Name}' enum; token type: {reader.TokenType}");
|
||||
return Activator.CreateInstance(enumType);
|
||||
}
|
||||
|
||||
public override object ReadAsPropertyName(ref Utf8JsonReader reader, Type enumType, JsonSerializerOptions options)
|
||||
{
|
||||
// Is this token a property name?
|
||||
if (reader.TokenType == JsonTokenType.PropertyName)
|
||||
{
|
||||
// Try to use that property name as the name of the enum value:
|
||||
if (Enum.TryParse(typeToConvert, reader.GetString(), out var result))
|
||||
var text = reader.GetString();
|
||||
|
||||
// Convert the text to UPPER_SNAKE_CASE:
|
||||
text = ConvertToUpperSnakeCase(text);
|
||||
|
||||
// Try to parse the enum value:
|
||||
if (Enum.TryParse(enumType, text, out var result))
|
||||
return result;
|
||||
}
|
||||
|
||||
// In any other case, we will return the default enum value:
|
||||
LOG.LogWarning($"Cannot read '{reader.GetString()}' as '{typeToConvert.Name}' enum; token type: {reader.TokenType}");
|
||||
return Activator.CreateInstance(typeToConvert)!;
|
||||
LOG.LogWarning($"Cannot read '{reader.GetString()}' as '{enumType.Name}' enum; token type: {reader.TokenType}");
|
||||
return Activator.CreateInstance(enumType)!;
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
|
||||
@ -51,4 +71,44 @@ public sealed class TolerantEnumConverter : JsonConverter<object>
|
||||
{
|
||||
writer.WritePropertyName(value.ToString()!);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to UPPER_SNAKE_CASE.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to convert.</param>
|
||||
/// <returns>The converted text as UPPER_SNAKE_CASE.</returns>
|
||||
private static string ConvertToUpperSnakeCase(string? text)
|
||||
{
|
||||
// Handle null or empty strings:
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
return string.Empty;
|
||||
|
||||
// Create a string builder with the same length as the
|
||||
// input text. We will add underscores as needed, which
|
||||
// may increase the length -- we cannot predict how many
|
||||
// underscores will be added, so we just start with the
|
||||
// original length:
|
||||
var sb = new StringBuilder(text.Length);
|
||||
|
||||
// State to track if the last character was lowercase.
|
||||
// This helps to determine when to add underscores:
|
||||
var lastCharWasLowerCase = false;
|
||||
|
||||
// Iterate through each character in the input text:
|
||||
foreach(var c in text)
|
||||
{
|
||||
// If the current character is uppercase and the last
|
||||
// character was lowercase, we need to add an underscore:
|
||||
if (char.IsUpper(c) && lastCharWasLowerCase)
|
||||
sb.Append('_');
|
||||
|
||||
// Append the uppercase version of the current character:
|
||||
sb.Append(char.ToUpperInvariant(c));
|
||||
|
||||
// Keep track of whether the current character is lowercase:
|
||||
lastCharWasLowerCase = char.IsLower(c);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,7 @@ public enum Components
|
||||
JOB_POSTING_ASSISTANT,
|
||||
BIAS_DAY_ASSISTANT,
|
||||
ERI_ASSISTANT,
|
||||
DOCUMENT_ANALYSIS_ASSISTANT,
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
I18N_ASSISTANT,
|
||||
|
||||
@ -42,10 +42,11 @@ public static class ComponentsExtensions
|
||||
Components.JOB_POSTING_ASSISTANT => TB("Job Posting Assistant"),
|
||||
Components.ERI_ASSISTANT => TB("ERI Server"),
|
||||
Components.I18N_ASSISTANT => TB("Localization Assistant"),
|
||||
Components.DOCUMENT_ANALYSIS_ASSISTANT => TB("Document Analysis Assistant"),
|
||||
|
||||
Components.CHAT => TB("New Chat"),
|
||||
|
||||
_ => Enum.GetName(typeof(Components), component)!,
|
||||
_ => Enum.GetName(component)!,
|
||||
};
|
||||
|
||||
public static ComponentsData GetData(this Components destination) => destination switch
|
||||
@ -62,6 +63,7 @@ public static class ComponentsExtensions
|
||||
Components.SYNONYMS_ASSISTANT => new(Event.SEND_TO_SYNONYMS_ASSISTANT, Routes.ASSISTANT_SYNONYMS),
|
||||
Components.MY_TASKS_ASSISTANT => new(Event.SEND_TO_MY_TASKS_ASSISTANT, Routes.ASSISTANT_MY_TASKS),
|
||||
Components.JOB_POSTING_ASSISTANT => new(Event.SEND_TO_JOB_POSTING_ASSISTANT, Routes.ASSISTANT_JOB_POSTING),
|
||||
Components.DOCUMENT_ANALYSIS_ASSISTANT => new(Event.SEND_TO_DOCUMENT_ANALYSIS_ASSISTANT, Routes.ASSISTANT_DOCUMENT_ANALYSIS),
|
||||
|
||||
Components.CHAT => new(Event.SEND_TO_CHAT, Routes.CHAT),
|
||||
|
||||
@ -85,6 +87,9 @@ public static class ComponentsExtensions
|
||||
Components.BIAS_DAY_ASSISTANT => settingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions ? settingsManager.ConfigurationData.BiasOfTheDay.MinimumProviderConfidence : default,
|
||||
Components.ERI_ASSISTANT => settingsManager.ConfigurationData.ERI.PreselectOptions ? settingsManager.ConfigurationData.ERI.MinimumProviderConfidence : default,
|
||||
|
||||
#warning Add minimum confidence for DOCUMENT_ANALYSIS_ASSISTANT:
|
||||
//Components.DOCUMENT_ANALYSIS_ASSISTANT => settingsManager.ConfigurationData.DocumentAnalysis.PreselectOptions ? settingsManager.ConfigurationData.DocumentAnalysis.MinimumProviderConfidence : default,
|
||||
|
||||
_ => default,
|
||||
};
|
||||
|
||||
@ -109,6 +114,9 @@ public static class ComponentsExtensions
|
||||
Components.ERI_ASSISTANT => settingsManager.ConfigurationData.ERI.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.ERI.PreselectedProvider) : null,
|
||||
Components.I18N_ASSISTANT => settingsManager.ConfigurationData.I18N.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.I18N.PreselectedProvider) : null,
|
||||
|
||||
#warning Add preselected provider for DOCUMENT_ANALYSIS_ASSISTANT:
|
||||
//Components.DOCUMENT_ANALYSIS_ASSISTANT => settingsManager.ConfigurationData.DocumentAnalysis.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.DocumentAnalysis.PreselectedProvider) : null,
|
||||
|
||||
Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Chat.PreselectedProvider) : null,
|
||||
|
||||
Components.AGENT_TEXT_CONTENT_CLEANER => settingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider) : null,
|
||||
@ -123,6 +131,8 @@ public static class ComponentsExtensions
|
||||
|
||||
public static Profile PreselectedProfile(this Components component, SettingsManager settingsManager) => component switch
|
||||
{
|
||||
#warning Add preselected profile for DOCUMENT_ANALYSIS_ASSISTANT:
|
||||
// Components.DOCUMENT_ANALYSIS_ASSISTANT => settingsManager.ConfigurationData.DocumentAnalysis.PreselectOptions ? settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.DocumentAnalysis.PreselectedProfile) : default,
|
||||
Components.AGENDA_ASSISTANT => settingsManager.ConfigurationData.Agenda.PreselectOptions ? settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Agenda.PreselectedProfile) ?? Profile.NO_PROFILE : Profile.NO_PROFILE,
|
||||
Components.CODING_ASSISTANT => settingsManager.ConfigurationData.Coding.PreselectOptions ? settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Coding.PreselectedProfile) ?? Profile.NO_PROFILE : Profile.NO_PROFILE,
|
||||
Components.EMAIL_ASSISTANT => settingsManager.ConfigurationData.EMail.PreselectOptions ? settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.EMail.PreselectedProfile) ?? Profile.NO_PROFILE : Profile.NO_PROFILE,
|
||||
|
||||
@ -14,6 +14,7 @@ public enum Event
|
||||
SHOW_ERROR,
|
||||
SHOW_WARNING,
|
||||
SHOW_SUCCESS,
|
||||
TAURI_EVENT_RECEIVED,
|
||||
|
||||
// Update events:
|
||||
USER_SEARCH_FOR_UPDATE,
|
||||
@ -47,4 +48,5 @@ public enum Event
|
||||
SEND_TO_SYNONYMS_ASSISTANT,
|
||||
SEND_TO_MY_TASKS_ASSISTANT,
|
||||
SEND_TO_JOB_POSTING_ASSISTANT,
|
||||
SEND_TO_DOCUMENT_ANALYSIS_ASSISTANT,
|
||||
}
|
||||
14
app/MindWork AI Studio/Tools/EventHandlers.cs
Normal file
14
app/MindWork AI Studio/Tools/EventHandlers.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Tools;
|
||||
|
||||
/// <summary>
|
||||
/// Add handling for more DOM events to Blazor components.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See https://learn.microsoft.com/en-us/aspnet/core/blazor/components/event-handling. It is important
|
||||
/// that this class is named EventHandlers.
|
||||
/// </remarks>
|
||||
[EventHandler("onmouseenter", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)]
|
||||
[EventHandler("onmouseleave", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)]
|
||||
public static class EventHandlers;
|
||||
@ -19,7 +19,9 @@ public readonly record struct FileTypeFilter(string FilterName, string[] FilterE
|
||||
|
||||
public static FileTypeFilter AllOffice => new(TB("All Office Files"), ["docx", "xlsx", "pptx", "doc", "xls", "ppt", "pdf"]);
|
||||
|
||||
public static FileTypeFilter AllImages => new(TB("All Image Files"), ["jpg", "jpeg", "png", "gif", "bmp", "tiff"]);
|
||||
public static FileTypeFilter AllImages => new(TB("All Image Files"), ["jpg", "jpeg", "png", "gif", "bmp", "tiff", "svg", "webp", "heic"]);
|
||||
|
||||
public static FileTypeFilter AllVideos => new(TB("All Video Files"), ["mp4", "avi", "mkv", "mov", "wmv", "flv", "webm"]);
|
||||
|
||||
public static FileTypeFilter Executables => new(TB("Executable Files"), ["exe", "app", "bin", "appimage"]);
|
||||
}
|
||||
8
app/MindWork AI Studio/Tools/Rust/TauriEvent.cs
Normal file
8
app/MindWork AI Studio/Tools/Rust/TauriEvent.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>
|
||||
/// The data structure for a Tauri event sent from the Rust backend to the C# frontend.
|
||||
/// </summary>
|
||||
/// <param name="EventType">The type of the Tauri event.</param>
|
||||
/// <param name="Payload">The payload of the Tauri event.</param>
|
||||
public readonly record struct TauriEvent(TauriEventType EventType, List<string> Payload);
|
||||
18
app/MindWork AI Studio/Tools/Rust/TauriEventType.cs
Normal file
18
app/MindWork AI Studio/Tools/Rust/TauriEventType.cs
Normal file
@ -0,0 +1,18 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>
|
||||
/// The type of Tauri events we can receive.
|
||||
/// </summary>
|
||||
public enum TauriEventType
|
||||
{
|
||||
NONE,
|
||||
PING,
|
||||
UNKNOWN,
|
||||
|
||||
WINDOW_FOCUSED,
|
||||
WINDOW_NOT_FOCUSED,
|
||||
|
||||
FILE_DROP_HOVERED,
|
||||
FILE_DROP_DROPPED,
|
||||
FILE_DROP_CANCELED,
|
||||
}
|
||||
77
app/MindWork AI Studio/Tools/Services/RustService.Events.cs
Normal file
77
app/MindWork AI Studio/Tools/Services/RustService.Events.cs
Normal file
@ -0,0 +1,77 @@
|
||||
using System.Text.Json;
|
||||
|
||||
using AIStudio.Tools.Rust;
|
||||
|
||||
namespace AIStudio.Tools.Services;
|
||||
|
||||
public partial class RustService
|
||||
{
|
||||
/// <summary>
|
||||
/// Consume the Tauri event stream and forward relevant events to the message bus.
|
||||
/// </summary>
|
||||
/// <param name="stopToken">Cancellation token to stop the stream.</param>
|
||||
private async Task StartStreamTauriEvents(CancellationToken stopToken)
|
||||
{
|
||||
// Outer try-catch to handle cancellation:
|
||||
try
|
||||
{
|
||||
while (!stopToken.IsCancellationRequested)
|
||||
{
|
||||
// Inner try-catch to handle streaming issues:
|
||||
try
|
||||
{
|
||||
// Open the event stream:
|
||||
await using var stream = await this.http.GetStreamAsync("/events", stopToken);
|
||||
|
||||
|
||||
// Read events line by line:
|
||||
using var reader = new StreamReader(stream);
|
||||
|
||||
// Read until the end of the stream or cancellation:
|
||||
while(!reader.EndOfStream && !stopToken.IsCancellationRequested)
|
||||
{
|
||||
// Read the next line of JSON from the stream:
|
||||
var line = await reader.ReadLineAsync(stopToken);
|
||||
|
||||
// Skip empty lines:
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
|
||||
// Deserialize the Tauri event:
|
||||
var tauriEvent = JsonSerializer.Deserialize<TauriEvent>(line, this.jsonRustSerializerOptions);
|
||||
|
||||
// Forward relevant events to the message bus:
|
||||
if (tauriEvent != default && tauriEvent.EventType
|
||||
is not TauriEventType.NONE
|
||||
and not TauriEventType.UNKNOWN
|
||||
and not TauriEventType.PING)
|
||||
{
|
||||
this.logger!.LogDebug("Received Tauri event {EventType} with {NumPayloadItems} payload items.", tauriEvent.EventType, tauriEvent.Payload.Count);
|
||||
await MessageBus.INSTANCE.SendMessage(null, Event.TAURI_EVENT_RECEIVED, tauriEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The cancellation token was triggered, exit the loop:
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Some other error occurred, log it and retry after a delay:
|
||||
catch (Exception e)
|
||||
{
|
||||
this.logger!.LogError("Error while streaming Tauri events: {Message}", e.Message);
|
||||
await Task.Delay(TimeSpan.FromSeconds(3), stopToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The cancellation token was triggered, exit the method:
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
|
||||
this.logger!.LogWarning("Stopped streaming Tauri events.");
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,10 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
|
||||
using AIStudio.Settings;
|
||||
|
||||
using Version = System.Version;
|
||||
|
||||
// ReSharper disable NotAccessedPositionalProperty.Local
|
||||
|
||||
namespace AIStudio.Tools.Services;
|
||||
@ -8,13 +12,14 @@ namespace AIStudio.Tools.Services;
|
||||
/// <summary>
|
||||
/// Calling Rust functions.
|
||||
/// </summary>
|
||||
public sealed partial class RustService : IDisposable
|
||||
public sealed partial class RustService : BackgroundService
|
||||
{
|
||||
private readonly HttpClient http;
|
||||
|
||||
private readonly JsonSerializerOptions jsonRustSerializerOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
Converters = { new TolerantEnumConverter() },
|
||||
};
|
||||
|
||||
private ILogger<RustService>? logger;
|
||||
@ -59,11 +64,24 @@ public sealed partial class RustService : IDisposable
|
||||
this.encryptor = encryptionService;
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
#region Overrides of BackgroundService
|
||||
|
||||
public void Dispose()
|
||||
/// <summary>
|
||||
/// The main execution loop of the Rust service as a background thread.
|
||||
/// </summary>
|
||||
/// <param name="stopToken">The cancellation token to stop the service.</param>
|
||||
protected override async Task ExecuteAsync(CancellationToken stopToken)
|
||||
{
|
||||
this.logger?.LogInformation("The Rust service was initialized.");
|
||||
|
||||
// Start consuming Tauri events:
|
||||
await this.StartStreamTauriEvents(stopToken);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
this.http.Dispose();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -24,24 +24,24 @@ public sealed class TemporaryChatService(ILogger<TemporaryChatService> logger, S
|
||||
return;
|
||||
}
|
||||
|
||||
await this.StartMaintenance();
|
||||
this.StartMaintenance();
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(CHECK_INTERVAL, stoppingToken);
|
||||
await this.StartMaintenance();
|
||||
this.StartMaintenance();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Task StartMaintenance()
|
||||
private void StartMaintenance()
|
||||
{
|
||||
logger.LogInformation("Starting maintenance of temporary chat storage.");
|
||||
var temporaryDirectories = Path.Join(SettingsManager.DataDirectory, "tempChats");
|
||||
if(!Directory.Exists(temporaryDirectories))
|
||||
{
|
||||
logger.LogWarning("Temporary chat storage directory does not exist. End maintenance.");
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var tempChatDirPath in Directory.EnumerateDirectories(temporaryDirectories))
|
||||
@ -71,7 +71,6 @@ public sealed class TemporaryChatService(ILogger<TemporaryChatService> logger, S
|
||||
}
|
||||
|
||||
logger.LogInformation("Finished maintenance of temporary chat storage.");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
|
||||
@ -39,9 +39,9 @@
|
||||
},
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.11, )",
|
||||
"resolved": "9.0.11",
|
||||
"contentHash": "vvB9rtDmWaXgYkViT00KORBVmA3pcYsHlgd9vOPqL9sf5bKy3rvLMF1+sI1uUfVj28S3itirHlHmX5/kcpZKNw=="
|
||||
"requested": "[9.0.8, )",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "rd1CbIsMtVPtZNTIVD6Xydue//klYOOQIDpRgu3BHtv17AlpRs74/6QFbcYgMm/jL+naVU2T3OFLxVSLV5lQLQ=="
|
||||
},
|
||||
"MudBlazor": {
|
||||
"type": "Direct",
|
||||
@ -210,6 +210,6 @@
|
||||
"type": "Project"
|
||||
}
|
||||
},
|
||||
"net9.0/osx-arm64": {}
|
||||
"net9.0/win-x64": {}
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,6 @@
|
||||
1.91.1 (commit ed61e7d7e)
|
||||
8.12.0
|
||||
1.8.1
|
||||
45ac3eee2ba, release
|
||||
osx-arm64
|
||||
bac0b49dce9, release
|
||||
win-x64
|
||||
137.0.7215.0
|
||||
@ -1,14 +1,16 @@
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use log::{error, info, trace, warn};
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use once_cell::sync::Lazy;
|
||||
use rocket::{get, post};
|
||||
use rocket::response::stream::TextStream;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
use tauri::updater::UpdateResponse;
|
||||
use tauri::{Manager, PathResolver, Window};
|
||||
use tauri::{FileDropEvent, UpdaterEvent, RunEvent, Manager, PathResolver, Window, WindowEvent};
|
||||
use tauri::api::dialog::blocking::FileDialogBuilder;
|
||||
use tokio::sync::broadcast;
|
||||
use tokio::time;
|
||||
use crate::api_token::APIToken;
|
||||
use crate::dotnet::stop_dotnet_server;
|
||||
@ -22,18 +24,70 @@ static MAIN_WINDOW: Lazy<Mutex<Option<Window>>> = Lazy::new(|| Mutex::new(None))
|
||||
/// The update response coming from the Tauri updater.
|
||||
static CHECK_UPDATE_RESPONSE: Lazy<Mutex<Option<UpdateResponse<tauri::Wry>>>> = Lazy::new(|| Mutex::new(None));
|
||||
|
||||
/// The event broadcast sender for Tauri events.
|
||||
static EVENT_BROADCAST: Lazy<Mutex<Option<broadcast::Sender<Event>>>> = Lazy::new(|| Mutex::new(None));
|
||||
|
||||
/// Starts the Tauri app.
|
||||
pub fn start_tauri() {
|
||||
info!("Starting Tauri app...");
|
||||
|
||||
// Create the event broadcast channel:
|
||||
let (event_sender, root_event_receiver) = broadcast::channel(100);
|
||||
|
||||
// Save a copy of the event broadcast sender for later use:
|
||||
*EVENT_BROADCAST.lock().unwrap() = Some(event_sender.clone());
|
||||
|
||||
// When the last receiver is dropped, we lose the ability to send events.
|
||||
// Therefore, we spawn a task that keeps the root receiver alive:
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let mut root_receiver = root_event_receiver;
|
||||
loop {
|
||||
match root_receiver.recv().await {
|
||||
Ok(event) => {
|
||||
debug!(Source = "Tauri"; "Tauri event received: location=root receiver , event={event:?}");
|
||||
},
|
||||
|
||||
Err(broadcast::error::RecvError::Lagged(skipped)) => {
|
||||
warn!(Source = "Tauri"; "Root event receiver lagged, skipped {skipped} messages.");
|
||||
},
|
||||
|
||||
Err(broadcast::error::RecvError::Closed) => {
|
||||
warn!(Source = "Tauri"; "Root event receiver channel closed.");
|
||||
return;
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let app = tauri::Builder::default()
|
||||
.setup(move |app| {
|
||||
|
||||
// Get the main window:
|
||||
let window = app.get_window("main").expect("Failed to get main window.");
|
||||
|
||||
// Register a callback for window events, such as file drops. We have to use
|
||||
// this handler in addition to the app event handler, because file drop events
|
||||
// are only available in the window event handler (is a bug, cf. https://github.com/tauri-apps/tauri/issues/14338):
|
||||
window.on_window_event(move |event| {
|
||||
debug!(Source = "Tauri"; "Tauri event received: location=window event handler, event={event:?}");
|
||||
let event_to_send = Event::from_window_event(event);
|
||||
let sender = event_sender.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
match sender.send(event_to_send) {
|
||||
Ok(_) => {},
|
||||
Err(error) => error!(Source = "Tauri"; "Failed to channel window event: {error}"),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Save the main window for later access:
|
||||
*MAIN_WINDOW.lock().unwrap() = Some(window);
|
||||
|
||||
info!(Source = "Bootloader Tauri"; "Setup is running.");
|
||||
let data_path = app.path_resolver().app_local_data_dir().unwrap();
|
||||
let data_path = data_path.join("data");
|
||||
|
||||
// Get and store the data and config directories:
|
||||
DATA_DIRECTORY.set(data_path.to_str().unwrap().to_string()).map_err(|_| error!("Was not abe to set the data directory.")).unwrap();
|
||||
CONFIG_DIRECTORY.set(app.path_resolver().app_config_dir().unwrap().to_str().unwrap().to_string()).map_err(|_| error!("Was not able to set the config directory.")).unwrap();
|
||||
|
||||
@ -46,43 +100,43 @@ pub fn start_tauri() {
|
||||
.build(tauri::generate_context!())
|
||||
.expect("Error while running Tauri application");
|
||||
|
||||
app.run(|app_handle, event| match event {
|
||||
// The app event handler:
|
||||
app.run(|app_handle, event| {
|
||||
if !matches!(event, RunEvent::MainEventsCleared) {
|
||||
debug!(Source = "Tauri"; "Tauri event received: location=app event handler , event={event:?}");
|
||||
}
|
||||
|
||||
tauri::RunEvent::WindowEvent { event, label, .. } => {
|
||||
match event {
|
||||
tauri::WindowEvent::CloseRequested { .. } => {
|
||||
RunEvent::WindowEvent { event, label, .. } => {
|
||||
match event {
|
||||
WindowEvent::CloseRequested { .. } => {
|
||||
warn!(Source = "Tauri"; "Window '{label}': close was requested.");
|
||||
}
|
||||
|
||||
tauri::WindowEvent::Destroyed => {
|
||||
WindowEvent::Destroyed => {
|
||||
warn!(Source = "Tauri"; "Window '{label}': was destroyed.");
|
||||
}
|
||||
|
||||
tauri::WindowEvent::FileDrop(files) => {
|
||||
info!(Source = "Tauri"; "Window '{label}': files were dropped: {files:?}");
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
tauri::RunEvent::Updater(updater_event) => {
|
||||
RunEvent::Updater(updater_event) => {
|
||||
match updater_event {
|
||||
|
||||
tauri::UpdaterEvent::UpdateAvailable { body, date, version } => {
|
||||
UpdaterEvent::UpdateAvailable { body, date, version } => {
|
||||
let body_len = body.len();
|
||||
info!(Source = "Tauri"; "Updater: update available: body size={body_len} time={date:?} version={version}");
|
||||
}
|
||||
|
||||
tauri::UpdaterEvent::Pending => {
|
||||
UpdaterEvent::Pending => {
|
||||
info!(Source = "Tauri"; "Updater: update is pending!");
|
||||
}
|
||||
|
||||
tauri::UpdaterEvent::DownloadProgress { chunk_length, content_length: _ } => {
|
||||
UpdaterEvent::DownloadProgress { chunk_length, content_length: _ } => {
|
||||
trace!(Source = "Tauri"; "Updater: downloading chunk of {chunk_length} bytes");
|
||||
}
|
||||
|
||||
tauri::UpdaterEvent::Downloaded => {
|
||||
UpdaterEvent::Downloaded => {
|
||||
info!(Source = "Tauri"; "Updater: update has been downloaded!");
|
||||
warn!(Source = "Tauri"; "Try to stop the .NET server now...");
|
||||
|
||||
@ -93,7 +147,7 @@ pub fn start_tauri() {
|
||||
}
|
||||
}
|
||||
|
||||
tauri::UpdaterEvent::Updated => {
|
||||
UpdaterEvent::Updated => {
|
||||
info!(Source = "Tauri"; "Updater: app has been updated");
|
||||
warn!(Source = "Tauri"; "Try to restart the app now...");
|
||||
|
||||
@ -102,28 +156,28 @@ pub fn start_tauri() {
|
||||
} else {
|
||||
warn!(Source = "Tauri"; "Development environment detected; do not restart the app.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tauri::UpdaterEvent::AlreadyUpToDate => {
|
||||
UpdaterEvent::AlreadyUpToDate => {
|
||||
info!(Source = "Tauri"; "Updater: app is already up to date");
|
||||
}
|
||||
|
||||
tauri::UpdaterEvent::Error(error) => {
|
||||
UpdaterEvent::Error(error) => {
|
||||
warn!(Source = "Tauri"; "Updater: failed to update: {error}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tauri::RunEvent::ExitRequested { .. } => {
|
||||
RunEvent::ExitRequested { .. } => {
|
||||
warn!(Source = "Tauri"; "Run event: exit was requested.");
|
||||
}
|
||||
|
||||
tauri::RunEvent::Ready => {
|
||||
RunEvent::Ready => {
|
||||
info!(Source = "Tauri"; "Run event: Tauri app is ready.");
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
|
||||
warn!(Source = "Tauri"; "Tauri app was stopped.");
|
||||
@ -133,6 +187,144 @@ pub fn start_tauri() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Our event API endpoint for Tauri events. We try to send an endless stream of events to the client.
|
||||
/// If no events are available for a certain time, we send a ping event to keep the connection alive.
|
||||
/// When the client disconnects, the stream is closed. But we try to not lose events in between.
|
||||
/// The client is expected to reconnect automatically when the connection is closed and continue
|
||||
/// listening for events.
|
||||
#[get("/events")]
|
||||
pub async fn get_event_stream(_token: APIToken) -> TextStream![String] {
|
||||
// Get the lock to the event broadcast sender:
|
||||
let event_broadcast_lock = EVENT_BROADCAST.lock().unwrap();
|
||||
|
||||
// Get and subscribe to the event receiver:
|
||||
let mut event_receiver = event_broadcast_lock.as_ref()
|
||||
.expect("Event sender not initialized.")
|
||||
.subscribe();
|
||||
|
||||
// Drop the lock to allow other access to the sender:
|
||||
drop(event_broadcast_lock);
|
||||
|
||||
// Create the event stream:
|
||||
TextStream! {
|
||||
loop {
|
||||
// Wait at most 3 seconds for an event:
|
||||
match time::timeout(Duration::from_secs(3), event_receiver.recv()).await {
|
||||
|
||||
// Case: we received an event
|
||||
Ok(Ok(event)) => {
|
||||
// Serialize the event to JSON. Important is that the entire event
|
||||
// is serialized as a single line so that the client can parse it
|
||||
// correctly:
|
||||
let event_json = serde_json::to_string(&event).unwrap();
|
||||
yield event_json;
|
||||
|
||||
// The client expects a newline after each event because we are using
|
||||
// a method to read the stream line-by-line:
|
||||
yield "\n".to_string();
|
||||
},
|
||||
|
||||
// Case: we lagged behind and missed some events
|
||||
Ok(Err(broadcast::error::RecvError::Lagged(skipped))) => {
|
||||
warn!(Source = "Tauri"; "Event receiver lagged, skipped {skipped} messages.");
|
||||
},
|
||||
|
||||
// Case: the event channel was closed
|
||||
Ok(Err(broadcast::error::RecvError::Closed)) => {
|
||||
warn!(Source = "Tauri"; "Event receiver channel closed.");
|
||||
return;
|
||||
},
|
||||
|
||||
// Case: timeout. We will send a ping event to keep the connection alive.
|
||||
Err(_) => {
|
||||
let ping_event = Event::new(TauriEventType::Ping, Vec::new());
|
||||
|
||||
// Again, we have to serialize the event as a single line:
|
||||
let event_json = serde_json::to_string(&ping_event).unwrap();
|
||||
yield event_json;
|
||||
|
||||
// The client expects a newline after each event because we are using
|
||||
// a method to read the stream line-by-line:
|
||||
yield "\n".to_string();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Data structure representing a Tauri event for our event API.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct Event {
|
||||
pub event_type: TauriEventType,
|
||||
pub payload: Vec<String>,
|
||||
}
|
||||
|
||||
/// Implementation of the Event struct.
|
||||
impl Event {
|
||||
|
||||
/// Creates a new Event instance.
|
||||
pub fn new(event_type: TauriEventType, payload: Vec<String>) -> Self {
|
||||
Event {
|
||||
payload,
|
||||
event_type,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an Event instance from a Tauri WindowEvent.
|
||||
pub fn from_window_event(window_event: &WindowEvent) -> Self {
|
||||
match window_event {
|
||||
WindowEvent::FileDrop(drop_event) => {
|
||||
match drop_event {
|
||||
FileDropEvent::Hovered(files) => Event::new(TauriEventType::FileDropHovered,
|
||||
files.iter().map(|f| f.to_string_lossy().to_string()).collect(),
|
||||
),
|
||||
|
||||
FileDropEvent::Dropped(files) => Event::new(TauriEventType::FileDropDropped,
|
||||
files.iter().map(|f| f.to_string_lossy().to_string()).collect(),
|
||||
),
|
||||
|
||||
FileDropEvent::Cancelled => Event::new(TauriEventType::FileDropCanceled,
|
||||
Vec::new(),
|
||||
),
|
||||
|
||||
_ => Event::new(TauriEventType::Unknown,
|
||||
Vec::new(),
|
||||
),
|
||||
}
|
||||
},
|
||||
|
||||
WindowEvent::Focused(state) => if *state {
|
||||
Event::new(TauriEventType::WindowFocused,
|
||||
Vec::new(),
|
||||
)
|
||||
} else {
|
||||
Event::new(TauriEventType::WindowNotFocused,
|
||||
Vec::new(),
|
||||
)
|
||||
},
|
||||
|
||||
_ => Event::new(TauriEventType::Unknown,
|
||||
Vec::new(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The types of Tauri events we can send through our event API.
|
||||
#[derive(Debug, Serialize, Clone)]
|
||||
pub enum TauriEventType {
|
||||
None,
|
||||
Ping,
|
||||
Unknown,
|
||||
|
||||
WindowFocused,
|
||||
WindowNotFocused,
|
||||
|
||||
FileDropHovered,
|
||||
FileDropDropped,
|
||||
FileDropCanceled,
|
||||
}
|
||||
|
||||
/// Changes the location of the main window to the given URL.
|
||||
pub async fn change_location_to(url: &str) {
|
||||
// Try to get the main window. If it is not available yet, wait for it:
|
||||
|
||||
@ -27,6 +27,7 @@ pub struct Chunk {
|
||||
pub stream_id: String,
|
||||
pub metadata: Metadata,
|
||||
}
|
||||
|
||||
impl Chunk {
|
||||
pub fn new(content: String, metadata: Metadata) -> Self {
|
||||
Chunk { content, stream_id: String::new(), metadata }
|
||||
|
||||
@ -68,6 +68,7 @@ pub fn start_runtime_api() {
|
||||
crate::dotnet::dotnet_port,
|
||||
crate::dotnet::dotnet_ready,
|
||||
crate::clipboard::set_clipboard,
|
||||
crate::app_window::get_event_stream,
|
||||
crate::app_window::check_for_update,
|
||||
crate::app_window::install_update,
|
||||
crate::app_window::select_directory,
|
||||
|
||||
@ -40,7 +40,8 @@
|
||||
"resizable": true,
|
||||
"title": "MindWork AI Studio",
|
||||
"width": 1920,
|
||||
"height": 1080
|
||||
"height": 1080,
|
||||
"fileDropEnabled": true
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user