Compare commits

...
6 Commits
59 changed files with 794 additions and 117 deletions

No files matched your search

+2 -53
View File
@@ -249,18 +249,6 @@ jobs:
cd publish/dotnet
mv mindworkAIStudio.exe "../../app/MindWork AI Studio/bin/dist/mindworkAIStudioServer${{ matrix.dotnet_name_postfix }}"
- name: Create parts for the Rust cache key (Unix)
if: matrix.platform != 'windows-latest'
run: |
cd runtime
echo "CARGO_LOCK_HASH=${{ hashFiles('**/Cargo.lock') }}" >> $GITHUB_ENV
- name: Create parts for the Rust cache key (Windows)
if: matrix.platform == 'windows-latest'
run: |
cd runtime
echo "CARGO_LOCK_HASH=${{ hashFiles('**/Cargo.lock') }}" >> $env:GITHUB_ENV
- name: Cache Rust
uses: actions/cache@v4
with:
@@ -272,17 +260,7 @@ jobs:
~/.rustup/toolchains
runtime/target
# When the entire key matches, Rust might just create the bundles using the current .NET build:
key: target-${{ matrix.dotnet_runtime }}-rust-${{ env.RUST_VERSION }}-dependencies-${{ env.CARGO_LOCK_HASH }}
# - 1st key: the Rust runtime dependencies changed. Anyway, we might be able to re-use many previously built packages.
#
# - No match: alright, a new Rust version was released. Sadly, we cannot re-use anything now. Why?
# The updated Rust compiler might mitigate some bugs or vulnerabilities. In order to apply
# these changes to our app, we have to re-compile everything. That's the reason why it makes
# no sense to use more parts for the cache key, like Tauri or Tauri build versions.
restore-keys: |
target-${{ matrix.dotnet_runtime }}-rust-${{ env.RUST_VERSION }}-dependencies-
key: target-${{ matrix.dotnet_runtime }}-rust-${{ env.RUST_VERSION }}
- name: Setup Rust (stable)
uses: dtolnay/rust-toolchain@master
@@ -478,30 +456,13 @@ jobs:
cd publish/dotnet
mv mindworkAIStudio "../../app/MindWork AI Studio/bin/dist/mindworkAIStudioServer-aarch64-unknown-linux-gnu"
- name: Create parts for the Rust cache key
if: ${{ env.SKIP != 'true' }}
run: |
cd runtime
echo "CARGO_LOCK_HASH=${{ hashFiles('**/Cargo.lock') }}" >> $GITHUB_ENV
- name: Cache linux arm64 runner image
if: ${{ env.SKIP != 'true' }}
uses: actions/cache@v4
id: linux_arm_cache
with:
path: ${{ runner.temp }}/linux_arm_qemu_cache.img
# When the entire key matches, Rust might just create the bundles using the current .NET build:
key: target-linux-arm64-rust-${{ env.RUST_VERSION }}-dependencies-${{ env.CARGO_LOCK_HASH }}
# - 1st key: the Rust runtime dependencies changed. Anyway, we might be able to re-use many previously built packages.
#
# - No match: alright, a new Rust version was released. Sadly, we cannot re-use anything now. Why?
# The updated Rust compiler might mitigate some bugs or vulnerabilities. In order to apply
# these changes to our app, we have to re-compile everything. That's the reason why it makes
# no sense to use more parts for the cache key, like Tauri or Tauri build versions.
restore-keys: |
target-linux-arm64-rust-${{ env.RUST_VERSION }}-dependencies-
key: target-linux-arm64-rust-${{ env.RUST_VERSION }}
- name: Build linux arm runner image
uses: pguyot/arm-runner-action@v2
@@ -585,18 +546,6 @@ jobs:
# Save the built libraries for the next job:
rm -fr /rust-cache/target
cp -Rp target /rust-cache
- name: Debug
if: ${{ env.SKIP != 'true' }}
run: |
echo "Current directory: $(pwd)"
ls -lhat
echo "Searching for linux_arm_qemu_cache.img"
find $RUNNER_TEMP -name 'linux_arm_qemu_cache.img' -print 2>/dev/null
echo "Searching for mind-work-ai-studio_*.deb"
find . -name 'mind-work-ai-studio_*.deb' -print 2>/dev/null
- name: Update the runner image to cache the Rust runtime build
if: ${{ env.SKIP != 'true' }}
+1
View File
@@ -1,5 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AI/@EntryIndexedValue">AI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LLM/@EntryIndexedValue">LLM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LM/@EntryIndexedValue">LM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MSG/@EntryIndexedValue">MSG</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ollama/@EntryIndexedValue">True</s:Boolean>
@@ -48,8 +48,4 @@
}
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.CreateAgenda()">
Create agenda
</MudButton>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -97,6 +97,10 @@ public partial class AssistantAgenda : AssistantBaseCore
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Create Agenda";
protected override Func<Task> SubmitAction => this.CreateAgenda;
protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with
{
SystemPrompt = SystemPrompts.DEFAULT,
@@ -8,12 +8,16 @@
<ChildContent>
<MudForm @ref="@(this.form)" @bind-IsValid="@(this.inputIsValid)" @bind-Errors="@(this.inputIssues)" Class="pr-2">
<MudText Typo="Typo.body1" Align="Align.Justify" Class="mb-6">
@(this.Description)
@this.Description
</MudText>
@if (this.Body is not null)
{
@(this.Body)
@this.Body
<MudButton Disabled="@this.SubmitDisabled" Variant="Variant.Filled" Class="mb-3" OnClick="() => this.SubmitAction()" Style="@this.SubmitButtonStyle">
@this.SubmitText
</MudButton>
}
</MudForm>
<Issues IssuesData="@(this.inputIssues)"/>
@@ -93,8 +97,13 @@
<MudButton Variant="Variant.Filled" Color="Color.Warning" StartIcon="@Icons.Material.Filled.Refresh" OnClick="() => this.InnerResetForm()">
Reset
</MudButton>
@if (this.AllowProfiles)
@if (this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)
{
<ConfidenceInfo Mode="ConfidenceInfoMode.BUTTON" Provider="@this.providerSettings.UsedProvider"/>
}
@if (this.AllowProfiles && this.ShowProfileSelection)
{
<ProfileSelection MarginLeft="" @bind-CurrentProfile="@this.currentProfile"/>
}
@@ -52,11 +52,19 @@ public abstract partial class AssistantBase : ComponentBase
protected abstract bool MightPreselectValues();
protected abstract string SubmitText { get; }
protected abstract Func<Task> SubmitAction { get; }
protected virtual bool SubmitDisabled => false;
private protected virtual RenderFragment? Body => null;
protected virtual bool ShowResult => true;
protected virtual bool AllowProfiles => true;
protected virtual bool ShowProfileSelection => true;
protected virtual bool ShowDedicatedProgress => false;
@@ -69,12 +77,12 @@ public abstract partial class AssistantBase : ComponentBase
protected AIStudio.Settings.Provider providerSettings;
protected MudForm? form;
protected bool inputIsValid;
protected Profile currentProfile = Profile.NO_PROFILE;
protected ChatThread? chatThread;
private ContentBlock? resultingContentBlock;
private string[] inputIssues = [];
private bool isProcessing;
private Profile currentProfile = Profile.NO_PROFILE;
#region Overrides of ComponentBase
@@ -105,6 +113,8 @@ public abstract partial class AssistantBase : ComponentBase
}
#endregion
private string SubmitButtonStyle => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence ? this.providerSettings.UsedProvider.GetConfidence(this.SettingsManager).StyleBorder() : string.Empty;
protected string? ValidatingProvider(AIStudio.Settings.Provider provider)
{
@@ -24,8 +24,4 @@
</MudStack>
<MudTextField T="string" @bind-Text="@this.questions" Validation="@this.ValidateQuestions" AdornmentIcon="@Icons.Material.Filled.QuestionMark" Adornment="Adornment.Start" Label="Your question(s)" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Color="Color.Info" OnClick="() => this.GetSupport()" Class="mb-3">
Get support
</MudButton>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -28,6 +28,10 @@ public partial class AssistantCoding : AssistantBaseCore
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Get Support";
protected override Func<Task> SubmitAction => this.GetSupport;
protected override void ResetFrom()
{
this.codingContexts.Clear();
@@ -20,8 +20,4 @@
<MudTextField T="string" @bind-Text="@this.inputName" Label="(Optional) Your name for the closing salutation" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Your name for the closing salutation of your e-mail." Class="mb-3"/>
<EnumSelection T="WritingStyles" NameFunc="@(style => style.Name())" @bind-Value="@this.selectedWritingStyle" Icon="@Icons.Material.Filled.Edit" Label="Select the writing style" ValidateSelection="@this.ValidateWritingStyle"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.CreateMail()">
Create e-mail
</MudButton>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -24,6 +24,10 @@ public partial class AssistantEMail : AssistantBaseCore
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Create email";
protected override Func<Task> SubmitAction => this.CreateMail;
protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with
{
SystemPrompt = SystemPrompts.DEFAULT,
@@ -3,8 +3,4 @@
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input to check" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom language" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.ProofreadText()">
Proofread
</MudButton>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -41,6 +41,10 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore
},
];
protected override string SubmitText => "Proofread";
protected override Func<Task> SubmitAction => this.ProofreadText;
protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with
{
SystemPrompt = SystemPrompts.DEFAULT,
@@ -15,8 +15,4 @@
<MudButton Href="@this.selectedIconSource.URL()" Target="_blank" Variant="Variant.Filled" Size="Size.Medium">Open website</MudButton>
}
</MudStack>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.FindIcon()">
Find icon
</MudButton>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -29,6 +29,10 @@ public partial class AssistantIconFinder : AssistantBaseCore
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Find Icon";
protected override Func<Task> SubmitAction => this.FindIcon;
protected override void ResetFrom()
{
this.inputContext = string.Empty;
@@ -8,8 +8,4 @@
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputLegalDocument" Validation="@this.ValidatingLegalDocument" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Legal document" Variant="Variant.Outlined" Lines="12" AutoGrow="@true" MaxLines="24" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputQuestions" Validation="@this.ValidatingQuestions" AdornmentIcon="@Icons.Material.Filled.QuestionAnswer" Adornment="Adornment.Start" Label="Your questions" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Disabled="@this.isAgentRunning" Variant="Variant.Filled" Class="mb-3" OnClick="() => this.AksQuestions()">
Ask your questions
</MudButton>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -24,6 +24,12 @@ public partial class AssistantLegalCheck : AssistantBaseCore
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Ask your questions";
protected override Func<Task> SubmitAction => this.AksQuestions;
protected override bool SubmitDisabled => this.isAgentRunning;
protected override void ResetFrom()
{
this.inputLegalDocument = string.Empty;
@@ -0,0 +1,7 @@
@attribute [Route(Routes.ASSISTANT_MY_TASKS)]
@inherits AssistantBaseCore
<ProfileFormSelection Validation="@this.ValidateProfile" @bind-Profile="@this.currentProfile"/>
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Text or email" Variant="Variant.Outlined" Lines="12" AutoGrow="@true" MaxLines="24" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -0,0 +1,123 @@
using AIStudio.Settings;
namespace AIStudio.Assistants.MyTasks;
public partial class AssistantMyTasks : AssistantBaseCore
{
protected override Tools.Components Component => Tools.Components.MY_TASKS_ASSISTANT;
protected override string Title => "My Tasks";
protected override string Description =>
"""
You received a cryptic email that was sent to many recipients and you are now wondering
if you need to do something? Copy the email into the input field. You also need to select
a personal profile. In this profile, you should describe your role in the organization.
The AI will then try to give you hints on what your tasks might be.
""";
protected override string SystemPrompt =>
$"""
You are a friendly and professional business expert. You receive business emails, protocols,
reports, etc. as input. Additionally, you know the user's role in the organization. The user
wonders if any tasks arise for them in their role based on the text. You now try to give hints
and advice on whether and what the user should do. When you believe there are no tasks for the
user, you tell them this. You consider typical business etiquette in your advice.
You write your advice in the following language: {this.SystemPromptLanguage()}.
""";
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Analyze text";
protected override Func<Task> SubmitAction => this.AnalyzeText;
protected override bool ShowProfileSelection => false;
protected override void ResetFrom()
{
this.inputText = string.Empty;
if (!this.MightPreselectValues())
{
this.selectedTargetLanguage = CommonLanguages.AS_IS;
this.customTargetLanguage = string.Empty;
}
}
protected override bool MightPreselectValues()
{
if (this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)
{
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage;
this.customTargetLanguage = this.SettingsManager.ConfigurationData.MyTasks.PreselectOtherLanguage;
return true;
}
return false;
}
private string inputText = string.Empty;
private CommonLanguages selectedTargetLanguage = CommonLanguages.AS_IS;
private string customTargetLanguage = string.Empty;
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_MY_TASKS_ASSISTANT).FirstOrDefault();
if (deferredContent is not null)
this.inputText = deferredContent;
await base.OnInitializedAsync();
}
#endregion
private string? ValidatingText(string text)
{
if(string.IsNullOrWhiteSpace(text))
return "Please provide some text as input. For example, an email.";
return null;
}
private string? ValidateProfile(Profile profile)
{
if(profile == default || profile == Profile.NO_PROFILE)
return "Please select one of your profiles.";
return null;
}
private string? ValidateCustomLanguage(string language)
{
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
return "Please provide a custom language.";
return null;
}
private string SystemPromptLanguage()
{
if(this.selectedTargetLanguage is CommonLanguages.AS_IS)
return "Use the same language as the input";
if(this.selectedTargetLanguage is CommonLanguages.OTHER)
return this.customTargetLanguage;
return this.selectedTargetLanguage.Name();
}
private async Task AnalyzeText()
{
await this.form!.Validate();
if (!this.inputIsValid)
return;
this.CreateChatThread();
var time = this.AddUserRequest(this.inputText);
await this.AddAIResponseAsync(time);
}
}
@@ -5,8 +5,4 @@
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom language" />
<EnumSelection T="WritingStyles" NameFunc="@(style => style.Name())" @bind-Value="@this.selectedWritingStyle" Icon="@Icons.Material.Filled.Edit" Label="Writing style" AllowOther="@false" />
<EnumSelection T="SentenceStructure" NameFunc="@(voice => voice.Name())" @bind-Value="@this.selectedSentenceStructure" Icon="@Icons.Material.Filled.Person4" Label="Sentence structure" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.RewriteText()">
Improve
</MudButton>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -42,6 +42,10 @@ public partial class AssistantRewriteImprove : AssistantBaseCore
},
];
protected override string SubmitText => "Improve";
protected override Func<Task> SubmitAction => this.RewriteText;
protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with
{
SystemPrompt = SystemPrompts.DEFAULT,
@@ -6,7 +6,3 @@
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedLanguage" Icon="@Icons.Material.Filled.Translate" Label="Language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.FindSynonyms()">
Get synonyms
</MudButton>
@@ -51,6 +51,10 @@ public partial class AssistantSynonyms : AssistantBaseCore
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Find synonyms";
protected override Func<Task> SubmitAction => this.FindSynonyms;
protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with
{
SystemPrompt = SystemPrompts.DEFAULT,
@@ -9,8 +9,4 @@
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" @bind-OtherInput="@this.customTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="Custom target language" ValidateOther="@this.ValidateCustomLanguage" />
<EnumSelection T="Complexity" NameFunc="@(complexity => complexity.Name())" @bind-Value="@this.selectedComplexity" Icon="@Icons.Material.Filled.Layers" Label="Target complexity" AllowOther="@true" @bind-OtherInput="@this.expertInField" OtherValue="Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS" LabelOther="Your expertise" ValidateOther="@this.ValidateExpertInField" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.SummarizeText()" Disabled="@this.isAgentRunning">
Summarize
</MudButton>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -29,6 +29,12 @@ public partial class AssistantTextSummarizer : AssistantBaseCore
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Summarize";
protected override Func<Task> SubmitAction => this.SummarizeText;
protected override bool SubmitDisabled => this.isAgentRunning;
protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with
{
SystemPrompt = SystemPrompts.DEFAULT,
@@ -17,8 +17,4 @@ else
}
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Disabled="@this.isAgentRunning" Variant="Variant.Filled" Class="mb-3" OnClick="() => this.TranslateText(force: true)">
Translate
</MudButton>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -25,6 +25,12 @@ public partial class AssistantTranslation : AssistantBaseCore
protected override IReadOnlyList<IButtonData> FooterButtons => [];
protected override string SubmitText => "Translate";
protected override Func<Task> SubmitAction => () => this.TranslateText(true);
protected override bool SubmitDisabled => this.isAgentRunning;
protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with
{
SystemPrompt = SystemPrompts.DEFAULT,
@@ -13,6 +13,8 @@ public partial class Changelog
public static readonly Log[] LOGS =
[
new (184, "v0.9.9, build 184 (2024-09-11 21:10 UTC)", "v0.9.9.md"),
new (183, "v0.9.8, build 183 (2024-09-09 13:10 UTC)", "v0.9.8.md"),
new (182, "v0.9.7, build 182 (2024-09-08 20:55 UTC)", "v0.9.7.md"),
new (181, "v0.9.6, build 181 (2024-09-08 09:30 UTC)", "v0.9.6.md"),
new (180, "v0.9.5, build 180 (2024-09-07 16:33 UTC)", "v0.9.5.md"),
@@ -0,0 +1,56 @@
@using AIStudio.Provider
<div class="d-flex">
@if (this.Mode is ConfidenceInfoMode.ICON)
{
<MudIconButton Icon="@Icons.Material.Filled.Security" Class="confidence-icon" Style="@this.Provider.GetConfidence(this.SettingsManager).SetColorStyle()" OnClick="@(() => this.ToggleConfidence())"/>
}
else
{
<MudButton Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.Security" IconClass="confidence-icon" Style="@this.Provider.GetConfidence(this.SettingsManager).SetColorStyle()" OnClick="@(() => this.ToggleConfidence())">
Confidence
</MudButton>
}
<MudPopover Open="@this.showConfidence" AnchorOrigin="Origin.TopLeft" TransformOrigin="Origin.BottomLeft" Style="@this.GetPopoverStyle()" DropShadow="@true" Class="border-solid border-4 rounded-lg">
<MudCard>
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h5">Confidence Card</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudText Typo="Typo.h6">Description</MudText>
<MudMarkdown Value="@this.currentConfidence.Description"/>
@if (this.currentConfidence.Sources.Count > 0)
{
<MudText Typo="Typo.h6">Sources</MudText>
<MudList T="@string">
@foreach (var sourceTuple in this.GetConfidenceSources())
{
<MudListItem Icon="@Icons.Material.Filled.Link" Href="@sourceTuple.Source" Target="_blank" Text="@sourceTuple.Index"/>
}
</MudList>
}
@if (!string.IsNullOrWhiteSpace(this.currentConfidence.Region))
{
<MudText Typo="Typo.h6">Region</MudText>
<MudText Typo="Typo.body1" Class="mb-3">
<b>@this.currentConfidence.Region</b>
</MudText>
}
<MudText Typo="Typo.h6">Confidence Level</MudText>
<MudText Typo="Typo.body1" Style="@this.GetCurrentConfidenceColor()">
<b>@this.currentConfidence.Level.GetName()</b>
</MudText>
</MudCardContent>
<MudCardActions>
<MudButton Variant="Variant.Filled" OnClick="@(() => this.HideConfidence())">
Close
</MudButton>
</MudCardActions>
</MudCard>
</MudPopover>
</div>
@@ -0,0 +1,57 @@
using AIStudio.Provider;
using AIStudio.Settings;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Components;
public partial class ConfidenceInfo : ComponentBase
{
[Parameter]
public ConfidenceInfoMode Mode { get; set; } = ConfidenceInfoMode.BUTTON;
[Parameter]
public Providers Provider { get; set; }
[Inject]
private SettingsManager SettingsManager { get; init; } = null!;
private Confidence currentConfidence;
private bool showConfidence;
public ConfidenceInfo()
{
this.currentConfidence = Providers.NONE.GetConfidence(this.SettingsManager);
}
#region Overrides of ComponentBase
protected override async Task OnParametersSetAsync()
{
this.currentConfidence = this.Provider.GetConfidence(this.SettingsManager);
await base.OnParametersSetAsync();
}
#endregion
private void ToggleConfidence()
{
this.showConfidence = !this.showConfidence;
}
private void HideConfidence()
{
this.showConfidence = false;
}
private IEnumerable<(string Index, string Source)> GetConfidenceSources()
{
var index = 0;
foreach (var source in this.currentConfidence.Sources)
yield return ($"Source {++index}", source);
}
private string GetCurrentConfidenceColor() => $"color: {this.currentConfidence.Level.GetColor()};";
private string GetPopoverStyle() => $"border-color: {this.currentConfidence.Level.GetColor()}; max-width: calc(35vw);";
}
@@ -0,0 +1,7 @@
namespace AIStudio.Components;
public enum ConfidenceInfoMode
{
BUTTON,
ICON,
}
@@ -0,0 +1,10 @@
@using AIStudio.Settings
<MudSelect T="Profile" Strict="@true" Value="@this.Profile" ValueChanged="@this.SelectionChanged" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person4" Margin="Margin.Dense" Label="Select one of your profiles" Variant="Variant.Outlined" Class="mb-3" Validation="@this.Validation">
@foreach (var profile in this.SettingsManager.ConfigurationData.Profiles.GetAllProfiles())
{
<MudSelectItem Value="profile">
@profile.Name
</MudSelectItem>
}
</MudSelect>
@@ -0,0 +1,26 @@
using AIStudio.Settings;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Components;
public partial class ProfileFormSelection : ComponentBase
{
[Parameter]
public Profile Profile { get; set; } = Profile.NO_PROFILE;
[Parameter]
public EventCallback<Profile> ProfileChanged { get; set; }
[Parameter]
public Func<Profile, string?> Validation { get; set; } = _ => null;
[Inject]
private SettingsManager SettingsManager { get; init; } = null!;
private async Task SelectionChanged(Profile profile)
{
this.Profile = profile;
await this.ProfileChanged.InvokeAsync(profile);
}
}
@@ -22,6 +22,7 @@
</MudText>
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
<AssistantBlock Name="E-Mail" Description="Generate an e-mail for a given context." Icon="@Icons.Material.Filled.Email" Link="@Routes.ASSISTANT_EMAIL"/>
<AssistantBlock Name="My Tasks" Description="Analyze a text or an email for tasks you need to complete." Icon="@Icons.Material.Filled.Task" Link="@Routes.ASSISTANT_MY_TASKS"/>
<AssistantBlock Name="Agenda Planner" Description="Generate an agenda for a given meeting, seminar, etc." Icon="@Icons.Material.Filled.CalendarToday" Link="@Routes.ASSISTANT_AGENDA"/>
<AssistantBlock Name="Legal Check" Description="Ask a question about a legal document." Icon="@Icons.Material.Filled.Gavel" Link="@Routes.ASSISTANT_LEGAL_CHECK"/>
<AssistantBlock Name="Icon Finder" Description="Using a LLM to find an icon for a given context." Icon="@Icons.Material.Filled.FindInPage" Link="@Routes.ASSISTANT_ICON_FINDER"/>
+6 -1
View File
@@ -28,7 +28,7 @@
</ChildContent>
<FooterContent>
<MudElement Style="flex: 0 0 auto;">
<MudTextField T="string" @ref="@this.inputField" @bind-Text="@this.userInput" Variant="Variant.Outlined" AutoGrow="@true" Lines="3" MaxLines="12" Label="@this.InputLabel" Placeholder="@this.ProviderPlaceholder" Adornment="Adornment.End" AdornmentIcon="@Icons.Material.Filled.Send" OnAdornmentClick="() => this.SendMessage()" ReadOnly="!this.IsProviderSelected || this.isStreaming" Immediate="@true" OnKeyUp="this.InputKeyEvent" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudTextField T="string" @ref="@this.inputField" @bind-Text="@this.userInput" Variant="Variant.Outlined" AutoGrow="@true" Lines="3" MaxLines="12" Label="@this.InputLabel" Placeholder="@this.ProviderPlaceholder" Adornment="Adornment.End" AdornmentIcon="@Icons.Material.Filled.Send" OnAdornmentClick="() => this.SendMessage()" ReadOnly="!this.IsProviderSelected || this.isStreaming" Immediate="@true" OnKeyUp="this.InputKeyEvent" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="@this.UserInputClass" Style="@this.UserInputStyle"/>
</MudElement>
<MudToolBar WrapContent="true" Gutters="@false" Class="border border-solid rounded" Style="border-color: lightgrey;">
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES)
@@ -70,6 +70,11 @@
</MudTooltip>
}
@if (this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)
{
<ConfidenceInfo Mode="ConfidenceInfoMode.ICON" Provider="@this.providerSettings.UsedProvider"/>
}
<ProfileSelection CurrentProfile="@this.currentProfile" CurrentProfileChanged="@this.ProfileWasChanged" />
</MudToolBar>
</FooterContent>
@@ -120,6 +120,10 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
private string TooltipAddChatToWorkspace => $"Start new chat in workspace \"{this.currentWorkspaceName}\"";
private string UserInputStyle => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence ? this.providerSettings.UsedProvider.GetConfidence(this.SettingsManager).SetColorStyle() : string.Empty;
private string UserInputClass => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence ? "confidence-border" : string.Empty;
private void ProfileWasChanged(Profile profile)
{
this.currentProfile = profile;
+65 -2
View File
@@ -17,7 +17,7 @@
task. As an LLM provider, you can also choose local providers. However, to use this app, you must
configure at least one provider.
</MudJustifiedText>
<MudTable Items="@this.SettingsManager.ConfigurationData.Providers" Class="border-dashed border rounded-lg">
<MudTable Items="@this.SettingsManager.ConfigurationData.Providers" Hover="@true" Class="border-dashed border rounded-lg">
<ColGroup>
<col style="width: 3em;"/>
<col style="width: 12em;"/>
@@ -72,6 +72,56 @@
<MudButton Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddProvider">
Add Provider
</MudButton>
<MudText Typo="Typo.h4" Class="mb-3">LLM Provider Confidence</MudText>
<MudJustifiedText Class="mb-3">
Do you want to always be able to recognize how trustworthy your LLM providers are? This way,
you keep control over which provider you send your data to. You have two options for this:
Either you choose a common schema, or you configure the trust levels for each LLM provider yourself.
</MudJustifiedText>
<ConfigurationOption OptionDescription="Show provider's confidence level?" LabelOn="Yes, show me the confidence level" LabelOff="No, please hide the confidence level" State="@(() => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence = updatedState)" OptionHelp="When enabled, we show you the confidence level for the selected provider in the app. This helps you assess where you are sending your data at any time. Example: are you currently working with sensitive data? Then choose a particularly trustworthy provider, etc."/>
@if (this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)
{
<ConfigurationSelect OptionDescription="Select a confidence scheme" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LLMProviders.ConfidenceScheme)" Data="@ConfigurationSelectDataFactory.GetConfidenceSchemesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LLMProviders.ConfidenceScheme = selectedValue)" OptionHelp="Choose the scheme that best suits you and your life. Do you trust any western provider? Or only providers from the USA or exclusively European providers? Then choose the appropriate scheme. Alternatively, you can assign the confidence levels to each provider yourself."/>
@if (this.SettingsManager.ConfigurationData.LLMProviders.ConfidenceScheme is ConfidenceSchemes.CUSTOM)
{
<MudTable Items="@(Enum.GetValues<Providers>().Where(x => x is not Providers.NONE))" Hover="@true" Class="border-dashed border rounded-lg">
<ColGroup>
<col style="width: 12em;"/>
<col/>
<col style="width: 22em;"/>
</ColGroup>
<HeaderContent>
<MudTh>LLM Provider</MudTh>
<MudTh>Description</MudTh>
<MudTh>Confidence Level</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd Style="vertical-align: top;">
@context.ToName()
</MudTd>
<MudTd>
<MudMarkdown Value="@context.GetConfidence(this.SettingsManager).Description"/>
</MudTd>
<MudTd Style="vertical-align: top;">
<MudMenu StartIcon="@Icons.Material.Filled.Security" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="@this.GetCurrentConfidenceLevelName(context)" Variant="Variant.Filled" Style="@this.SetCurrentConfidenceLevelColorStyle(context)">
@foreach (var confidenceLevel in Enum.GetValues<ConfidenceLevel>().OrderBy(n => n))
{
if(confidenceLevel is ConfidenceLevel.NONE or ConfidenceLevel.UNKNOWN)
continue;
<MudMenuItem OnClick="@(async () => await this.ChangeCustomConfidenceLevel(context, confidenceLevel))">
@confidenceLevel.GetName()
</MudMenuItem>
}
</MudMenu>
</MudTd>
</RowTemplate>
</MudTable>
}
}
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Person4" HeaderText="Configure Profiles">
@@ -88,7 +138,7 @@
code. In these profiles, you can record how much experience you have or which methods you like or
dislike using. Later, you can choose when and where you want to use each profile.
</MudJustifiedText>
<MudTable Items="@this.SettingsManager.ConfigurationData.Profiles" Class="border-dashed border rounded-lg">
<MudTable Items="@this.SettingsManager.ConfigurationData.Profiles" Hover="@true" Class="border-dashed border rounded-lg">
<ColGroup>
<col style="width: 3em;"/>
<col/>
@@ -299,6 +349,19 @@
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Synonyms.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Synonyms.PreselectedProvider = selectedValue)"/>
</MudPaper>
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Task" HeaderText="Assistant: My Tasks">
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
<ConfigurationOption OptionDescription="Preselect options?" LabelOn="Options are preselected" LabelOff="No options are preselected" State="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect options. This is might be useful when you prefer a specific language or LLM model."/>
<ConfigurationSelect OptionDescription="Preselect the language" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which language should be preselected?"/>
@if (this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage is CommonLanguages.OTHER)
{
<ConfigurationText OptionDescription="Preselect another language" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.MyTasks.PreselectOtherLanguage = updatedText)"/>
}
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProvider = selectedValue)"/>
</MudPaper>
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TextFields" HeaderText="Agent: Text Content Cleaner Options">
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
@@ -160,6 +160,28 @@ public partial class Settings : ComponentBase, IMessageBusReceiver, IDisposable
this.availableProviders.Add(new (provider.InstanceName, provider.Id));
}
private string GetCurrentConfidenceLevelName(Providers provider)
{
if (this.SettingsManager.ConfigurationData.LLMProviders.CustomConfidenceScheme.TryGetValue(provider, out var level))
return level.GetName();
return "Not yet configured";
}
private string SetCurrentConfidenceLevelColorStyle(Providers provider)
{
if (this.SettingsManager.ConfigurationData.LLMProviders.CustomConfidenceScheme.TryGetValue(provider, out var level))
return $"background-color: {level.GetColor()};";
return $"background-color: {ConfidenceLevel.UNKNOWN.GetColor()};";
}
private async Task ChangeCustomConfidenceLevel(Providers provider, ConfidenceLevel level)
{
this.SettingsManager.ConfigurationData.LLMProviders.CustomConfidenceScheme[provider] = level;
await this.SettingsManager.StoreSettings();
}
#endregion
#region Profile related
@@ -0,0 +1,65 @@
namespace AIStudio.Provider;
public sealed record Confidence
{
public ConfidenceLevel Level { get; private init; } = ConfidenceLevel.UNKNOWN;
public string Region { get; private init; } = string.Empty;
public string Description { get; private init; } = string.Empty;
public List<string> Sources { get; private init; } = [];
private Confidence()
{
}
public Confidence WithSources(params string[] sources) => this with { Sources = sources.ToList() };
public Confidence WithRegion(string region) => this with { Region = region };
public Confidence WithLevel(ConfidenceLevel level) => this with { Level = level };
public string StyleBorder() => $"border: 2px solid {this.Level.GetColor()}; border-radius: 6px;";
public string SetColorStyle() => $"--confidence-color: {this.Level.GetColor()};";
public static readonly Confidence NONE = new()
{
Level = ConfidenceLevel.NONE,
Description =
"""
No provider selected. Please select a provider to get see its confidence level.
""",
};
public static readonly Confidence USA_NOT_TRUSTED = new()
{
Level = ConfidenceLevel.UNTRUSTED,
Description = "The provider operates its service from the USA and is subject to **U.S. jurisdiction**. In case of suspicion, authorities in the USA can access your data. The provider's terms of service state that **all your data can be used by the provider at will.**",
};
public static readonly Confidence UNKNOWN = new()
{
Level = ConfidenceLevel.UNKNOWN,
Description = "The trust level of this provider **has not yet** been thoroughly **investigated and evaluated**. We do not know if your data is safe.",
};
public static readonly Confidence USA_NO_TRAINING = new()
{
Level = ConfidenceLevel.MODERATE,
Description = "The provider operates its service from the USA and is subject to **US jurisdiction**. In case of suspicion, authorities in the USA can access your data. However, **your data is not used for training** purposes.",
};
public static readonly Confidence GDPR_NO_TRAINING = new()
{
Level = ConfidenceLevel.MEDIUM,
Description = "The provider is located in the EU and is subject to the **GDPR** (General Data Protection Regulation). Additionally, the provider states that **your data is not used for training**.",
};
public static readonly Confidence SELF_HOSTED = new()
{
Level = ConfidenceLevel.HIGH,
Description = "You or your organization operate the LLM locally or within your trusted network. In terms of data processing and security, this is the best possible way.",
};
}
@@ -0,0 +1,18 @@
namespace AIStudio.Provider;
public enum ConfidenceLevel
{
NONE = 0,
UNTRUSTED = 1,
UNKNOWN = 10,
VERY_LOW = 90,
LOW = 100,
MODERATE = 150,
MEDIUM = 200,
HIGH = 300,
}
@@ -0,0 +1,34 @@
namespace AIStudio.Provider;
public static class ConfidenceLevelExtensions
{
public static string GetName(this ConfidenceLevel level) => level switch
{
ConfidenceLevel.NONE => "No provider selected",
ConfidenceLevel.UNTRUSTED => "Untrusted",
ConfidenceLevel.VERY_LOW => "Very Low",
ConfidenceLevel.LOW => "Low",
ConfidenceLevel.MODERATE => "Moderate",
ConfidenceLevel.MEDIUM => "Medium",
ConfidenceLevel.HIGH => "High",
_ => "Unknown confidence level",
};
public static string GetColor(this ConfidenceLevel level) => level switch
{
ConfidenceLevel.NONE => "#cccccc",
ConfidenceLevel.UNTRUSTED => "#ff0000",
ConfidenceLevel.VERY_LOW => "#ff6600",
ConfidenceLevel.LOW => "#ffcc00",
ConfidenceLevel.MODERATE => "#99cc00",
ConfidenceLevel.MEDIUM => "#86b300",
ConfidenceLevel.HIGH => "#009933",
_ => "#cc6600",
};
public static string SetColorStyle(this ConfidenceLevel level) => $"--confidence-color: {level.GetColor()};";
}
@@ -3,6 +3,7 @@ using AIStudio.Provider.Fireworks;
using AIStudio.Provider.Mistral;
using AIStudio.Provider.OpenAI;
using AIStudio.Provider.SelfHosted;
using AIStudio.Settings;
namespace AIStudio.Provider;
@@ -27,6 +28,33 @@ public static class ProvidersExtensions
_ => "Unknown",
};
/// <summary>
/// Get a provider's confidence.
/// </summary>
/// <param name="provider">The provider.</param>
/// <param name="settingsManager">The settings manager.</param>
/// <returns>The confidence of the provider.</returns>
public static Confidence GetConfidence(this Providers provider, SettingsManager settingsManager) => provider switch
{
Providers.NONE => Confidence.NONE,
Providers.FIREWORKS => Confidence.USA_NOT_TRUSTED.WithRegion("America, U.S.").WithSources("https://fireworks.ai/terms-of-service").WithLevel(settingsManager.GetConfiguredConfidenceLevel(provider)),
Providers.OPEN_AI => Confidence.USA_NO_TRAINING.WithRegion("America, U.S.").WithSources(
"https://openai.com/policies/terms-of-use/",
"https://help.openai.com/en/articles/5722486-how-your-data-is-used-to-improve-model-performance",
"https://openai.com/enterprise-privacy/"
).WithLevel(settingsManager.GetConfiguredConfidenceLevel(provider)),
Providers.ANTHROPIC => Confidence.USA_NO_TRAINING.WithRegion("America, U.S.").WithSources("https://www.anthropic.com/legal/commercial-terms").WithLevel(settingsManager.GetConfiguredConfidenceLevel(provider)),
Providers.MISTRAL => Confidence.GDPR_NO_TRAINING.WithRegion("Europe, France").WithSources("https://mistral.ai/terms/#terms-of-service-la-plateforme").WithLevel(settingsManager.GetConfiguredConfidenceLevel(provider)),
Providers.SELF_HOSTED => Confidence.SELF_HOSTED.WithLevel(settingsManager.GetConfiguredConfidenceLevel(provider)),
_ => Confidence.UNKNOWN.WithLevel(settingsManager.GetConfiguredConfidenceLevel(provider)),
};
/// <summary>
/// Creates a new provider instance based on the provider value.
+1
View File
@@ -20,5 +20,6 @@ public sealed partial class Routes
public const string ASSISTANT_EMAIL = "/assistant/email";
public const string ASSISTANT_LEGAL_CHECK = "/assistant/legal-check";
public const string ASSISTANT_SYNONYMS = "/assistant/synonyms";
public const string ASSISTANT_MY_TASKS = "/assistant/my-tasks";
// ReSharper restore InconsistentNaming
}
@@ -136,4 +136,10 @@ public static class ConfigurationSelectDataFactory
foreach (var profile in profiles.GetAllProfiles())
yield return new(profile.Name, profile.Id);
}
public static IEnumerable<ConfigurationSelectData<ConfidenceSchemes>> GetConfidenceSchemesData()
{
foreach (var scheme in Enum.GetValues<ConfidenceSchemes>())
yield return new(scheme.GetListDescription(), scheme);
}
}
@@ -16,6 +16,11 @@ public sealed class Data
/// </summary>
public List<Provider> Providers { get; init; } = [];
/// <summary>
/// Settings concerning the LLM providers.
/// </summary>
public DataLLMProviders LLMProviders { get; init; } = new();
/// <summary>
/// List of configured profiles.
/// </summary>
@@ -58,4 +63,6 @@ public sealed class Data
public DataLegalCheck LegalCheck { get; set; } = new();
public DataSynonyms Synonyms { get; set; } = new();
public DataMyTasks MyTasks { get; set; } = new();
}
@@ -0,0 +1,21 @@
using AIStudio.Provider;
namespace AIStudio.Settings.DataModel;
public sealed class DataLLMProviders
{
/// <summary>
/// Should we show the provider confidence level?
/// </summary>
public bool ShowProviderConfidence { get; set; } = true;
/// <summary>
/// Which confidence scheme to use.
/// </summary>
public ConfidenceSchemes ConfidenceScheme { get; set; } = ConfidenceSchemes.TRUST_USA_EUROPE;
/// <summary>
/// Provide custom confidence levels for each LLM provider.
/// </summary>
public Dictionary<Providers, ConfidenceLevel> CustomConfidenceScheme { get; set; } = new();
}
@@ -0,0 +1,29 @@
namespace AIStudio.Settings.DataModel;
public sealed class DataMyTasks
{
/// <summary>
/// Do you want to preselect any options?
/// </summary>
public bool PreselectOptions { get; set; }
/// <summary>
/// Preselect the target language?
/// </summary>
public CommonLanguages PreselectedTargetLanguage { get; set; }
/// <summary>
/// Preselect any other language?
/// </summary>
public string PreselectOtherLanguage { get; set; } = string.Empty;
/// <summary>
/// The preselected provider.
/// </summary>
public string PreselectedProvider { get; set; } = string.Empty;
/// <summary>
/// Preselect a profile?
/// </summary>
public string PreselectedProfile { get; set; } = string.Empty;
}
@@ -1,6 +1,7 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using AIStudio.Provider;
using AIStudio.Settings.DataModel;
// ReSharper disable NotAccessedPositionalProperty.Local
@@ -129,6 +130,7 @@ public sealed class SettingsManager(ILogger<SettingsManager> logger)
Tools.Components.EMAIL_ASSISTANT => this.ConfigurationData.EMail.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.EMail.PreselectedProvider) : default,
Tools.Components.LEGAL_CHECK_ASSISTANT => this.ConfigurationData.LegalCheck.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.LegalCheck.PreselectedProvider) : default,
Tools.Components.SYNONYMS_ASSISTANT => this.ConfigurationData.Synonyms.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.Synonyms.PreselectedProvider) : default,
Tools.Components.MY_TASKS_ASSISTANT => this.ConfigurationData.MyTasks.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.MyTasks.PreselectedProvider) : default,
_ => default,
};
@@ -148,6 +150,7 @@ public sealed class SettingsManager(ILogger<SettingsManager> logger)
Tools.Components.CODING_ASSISTANT => this.ConfigurationData.Coding.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.Coding.PreselectedProfile) : default,
Tools.Components.EMAIL_ASSISTANT => this.ConfigurationData.EMail.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.EMail.PreselectedProfile) : default,
Tools.Components.LEGAL_CHECK_ASSISTANT => this.ConfigurationData.LegalCheck.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.LegalCheck.PreselectedProfile) : default,
Tools.Components.MY_TASKS_ASSISTANT => this.ConfigurationData.MyTasks.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.MyTasks.PreselectedProfile) : default,
_ => default,
};
@@ -158,4 +161,57 @@ public sealed class SettingsManager(ILogger<SettingsManager> logger)
preselection = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.App.PreselectedProfile);
return preselection != default ? preselection : Profile.NO_PROFILE;
}
public ConfidenceLevel GetConfiguredConfidenceLevel(Providers provider)
{
if(provider is Providers.NONE)
return ConfidenceLevel.NONE;
switch (this.ConfigurationData.LLMProviders.ConfidenceScheme)
{
case ConfidenceSchemes.TRUST_USA_EUROPE:
return provider switch
{
Providers.SELF_HOSTED => ConfidenceLevel.HIGH,
Providers.FIREWORKS => ConfidenceLevel.UNTRUSTED,
_ => ConfidenceLevel.MEDIUM,
};
case ConfidenceSchemes.TRUST_USA:
return provider switch
{
Providers.SELF_HOSTED => ConfidenceLevel.HIGH,
Providers.FIREWORKS => ConfidenceLevel.UNTRUSTED,
Providers.MISTRAL => ConfidenceLevel.LOW,
_ => ConfidenceLevel.MEDIUM,
};
case ConfidenceSchemes.TRUST_EUROPE:
return provider switch
{
Providers.SELF_HOSTED => ConfidenceLevel.HIGH,
Providers.FIREWORKS => ConfidenceLevel.UNTRUSTED,
Providers.MISTRAL => ConfidenceLevel.MEDIUM,
_ => ConfidenceLevel.LOW,
};
case ConfidenceSchemes.LOCAL_TRUST_ONLY:
return provider switch
{
Providers.SELF_HOSTED => ConfidenceLevel.HIGH,
Providers.FIREWORKS => ConfidenceLevel.UNTRUSTED,
_ => ConfidenceLevel.VERY_LOW,
};
case ConfidenceSchemes.CUSTOM:
return this.ConfigurationData.LLMProviders.CustomConfidenceScheme.GetValueOrDefault(provider, ConfidenceLevel.UNKNOWN);
default:
return ConfidenceLevel.UNKNOWN;
}
}
}
@@ -14,6 +14,7 @@ public enum Components
EMAIL_ASSISTANT,
LEGAL_CHECK_ASSISTANT,
SYNONYMS_ASSISTANT,
MY_TASKS_ASSISTANT,
CHAT,
}
@@ -0,0 +1,12 @@
namespace AIStudio.Tools;
public enum ConfidenceSchemes
{
TRUST_USA_EUROPE = 0,
TRUST_USA = 1,
TRUST_EUROPE = 2,
LOCAL_TRUST_ONLY = 3,
CUSTOM = 10_000,
}
@@ -0,0 +1,16 @@
namespace AIStudio.Tools;
public static class ConfidenceSchemesExtensions
{
public static string GetListDescription(this ConfidenceSchemes scheme) => scheme switch
{
ConfidenceSchemes.TRUST_USA_EUROPE => "Trust LLM providers from the USA and Europe",
ConfidenceSchemes.TRUST_USA => "Trust LLM providers from the USA",
ConfidenceSchemes.TRUST_EUROPE => "Trust LLM providers from Europe",
ConfidenceSchemes.LOCAL_TRUST_ONLY => "Trust only local LLM providers",
ConfidenceSchemes.CUSTOM => "Configure your own confidence scheme",
_ => "Unknown confidence scheme"
};
}
+1
View File
@@ -28,4 +28,5 @@ public enum Event
SEND_TO_EMAIL_ASSISTANT,
SEND_TO_LEGAL_CHECK_ASSISTANT,
SEND_TO_SYNONYMS_ASSISTANT,
SEND_TO_MY_TASKS_ASSISTANT,
}
@@ -14,6 +14,7 @@ public static class SendToExtensions
Components.EMAIL_ASSISTANT => "E-Mail Assistant",
Components.LEGAL_CHECK_ASSISTANT => "Legal Check Assistant",
Components.SYNONYMS_ASSISTANT => "Synonym Assistant",
Components.MY_TASKS_ASSISTANT => "My Tasks Assistant",
Components.CHAT => "New Chat",
@@ -32,6 +33,7 @@ public static class SendToExtensions
Components.TEXT_SUMMARIZER_ASSISTANT => new(Event.SEND_TO_TEXT_SUMMARIZER_ASSISTANT, Routes.ASSISTANT_SUMMARIZER),
Components.LEGAL_CHECK_ASSISTANT => new(Event.SEND_TO_LEGAL_CHECK_ASSISTANT, Routes.ASSISTANT_LEGAL_CHECK),
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.CHAT => new(Event.SEND_TO_CHAT, Routes.CHAT),
+13
View File
@@ -33,4 +33,17 @@
.mud-text-list .mud-list-item-icon {
margin-top: 4px;
}
:root {
--confidence-color: #000000;
}
.confidence-icon {
color: var(--confidence-color);
}
.confidence-border > .mud-input-control-input-container > .mud-input > .mud-input-outlined-border {
border-width: 2px;
border-color: var(--confidence-color) !important;
}
@@ -0,0 +1,2 @@
# v0.9.8, build 183 (2024-09-09 13:10 UTC)
- Added the "my tasks" assistant to analyze, e.g., business emails and extract related tasks for your role.
@@ -0,0 +1,7 @@
# v0.9.9, build 184 (2024-09-11 21:10 UTC)
- Added confidence information to LLM providers.
- Added the possibility to choose from predefined confidence schemes.
- Added the possibility to define your own confidence scheme.
- Added an option to show/hide confidence information in the app.
- Added a visual indicator for confidence in the chat and all assistants.
- Added a confidence card to the chat and all assistants.
+4 -4
View File
@@ -1,9 +1,9 @@
0.9.7
2024-09-08 20:55:01 UTC
182
0.9.9
2024-09-11 21:10:00 UTC
184
8.0.108 (commit 665a05cea7)
8.0.8 (commit 08338fcaa5)
1.81.0 (commit eeb90cda1)
7.8.0
1.7.1
54588fc92d8, release
4722c1baa18, release
+1 -1
View File
@@ -2130,7 +2130,7 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mindwork-ai-studio"
version = "0.9.7"
version = "0.9.9"
dependencies = [
"aes",
"arboard",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "mindwork-ai-studio"
version = "0.9.7"
version = "0.9.9"
edition = "2021"
description = "MindWork AI Studio"
authors = ["Thorsten Sommer"]
+1 -1
View File
@@ -6,7 +6,7 @@
},
"package": {
"productName": "MindWork AI Studio",
"version": "0.9.7"
"version": "0.9.9"
},
"tauri": {
"allowlist": {