diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index c2429c15..108267b1 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -2107,15 +2107,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T24199 -- Name UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T266367750"] = "Name" +-- Configured Embedding Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T305753126"] = "Configured Embedding Providers" + -- This helps AI Studio understand and compare things in a way that's similar to how humans do. When you're working on something, AI Studio can automatically identify related documents and data by comparing their digital fingerprints. For instance, if you're writing about customer service, AI Studio can instantly find other documents in your data that discuss similar topics or experiences, even if they use different words. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3251217940"] = "This helps AI Studio understand and compare things in a way that's similar to how humans do. When you're working on something, AI Studio can automatically identify related documents and data by comparing their digital fingerprints. For instance, if you're writing about customer service, AI Studio can instantly find other documents in your data that discuss similar topics or experiences, even if they use different words." -- Edit UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3267849393"] = "Edit" --- Configured Embeddings -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3526613453"] = "Configured Embeddings" - -- Actions UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3865031940"] = "Actions" @@ -2125,6 +2125,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T40680 -- Edit Embedding Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T4264602229"] = "Edit Embedding Provider" +-- Configure Embedding Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T488419116"] = "Configure Embedding Providers" + -- Delete Embedding Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T511304264"] = "Delete Embedding Provider" @@ -2134,9 +2137,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T78223 -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T900237532"] = "Provider" --- Configure Embeddings -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T970042679"] = "Configure Embeddings" - -- Show provider's confidence level? UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1052533048"] = "Show provider's confidence level?" @@ -2155,6 +2155,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T172585 -- Add Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1806589097"] = "Add Provider" +-- Configure LLM Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1810190350"] = "Configure LLM Providers" + -- Edit LLM Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1868766523"] = "Edit LLM Provider" @@ -2188,8 +2191,8 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T284206 -- No providers configured yet. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T2911731076"] = "No providers configured yet." --- Configure Providers -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3027859089"] = "Configure Providers" +-- Configured LLM Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3019870540"] = "Configured LLM Providers" -- as selected by provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3082210376"] = "as selected by provider" @@ -2212,9 +2215,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T361241 -- No, do not enforce a minimum confidence level UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3642102079"] = "No, do not enforce a minimum confidence level" --- Configured Providers -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3850871263"] = "Configured Providers" - -- Actions UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3865031940"] = "Actions" @@ -2242,6 +2242,54 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T853225 -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T900237532"] = "Provider" +-- No transcription provider configured yet. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "No transcription provider configured yet." + +-- Edit Transcription Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1317362918"] = "Edit Transcription Provider" + +-- Delete +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1469573738"] = "Delete" + +-- Add transcription provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1645238629"] = "Add transcription provider" + +-- Add Transcription Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T2066315685"] = "Add Transcription Provider" + +-- Model +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T2189814010"] = "Model" + +-- Name +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T266367750"] = "Name" + +-- Edit +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T3267849393"] = "Edit" + +-- Delete Transcription Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T370103955"] = "Delete Transcription Provider" + +-- Actions +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T3865031940"] = "Actions" + +-- Configure Transcription Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T4073110625"] = "Configure Transcription Providers" + +-- Configured Transcription Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T4210863523"] = "Configured Transcription Providers" + +-- Open Dashboard +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T78223861"] = "Open Dashboard" + +-- Are you sure you want to delete the transcription provider '{0}'? +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T789660305"] = "Are you sure you want to delete the transcription provider '{0}'?" + +-- With the support of transcription models, MindWork AI Studio can convert human speech into text. This is useful, for example, when you need to dictate text. You can choose from dedicated transcription models, but not multimodal LLMs (large language models) that can handle both speech and text. The configuration of multimodal models is done in the \"Configure providers\" section. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T799338148"] = "With the support of transcription models, MindWork AI Studio can convert human speech into text. This is useful, for example, when you need to dictate text. You can choose from dedicated transcription models, but not multimodal LLMs (large language models) that can handle both speech and text. The configuration of multimodal models is done in the \\\"Configure providers\\\" section." + +-- Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T900237532"] = "Provider" + -- Copy {0} to the clipboard UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Copy {0} to the clipboard" @@ -3106,9 +3154,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2189814010"] = "Mo -- (Optional) API Key UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2331453405"] = "(Optional) API Key" --- Currently, we cannot query the embedding models of self-hosted systems. Therefore, enter the model name manually. -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2615586687"] = "Currently, we cannot query the embedding models of self-hosted systems. Therefore, enter the model name manually." - -- Add UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2646845972"] = "Add" @@ -3118,6 +3163,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2810182573"] = "No -- Instance Name UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2842060373"] = "Instance Name" +-- Currently, we cannot query the embedding models for the selected provider and/or host. Therefore, please enter the model name manually. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T290547799"] = "Currently, we cannot query the embedding models for the selected provider and/or host. Therefore, please enter the model name manually." + -- Model selection UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T416738168"] = "Model selection" @@ -3328,6 +3376,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T3361153305"] = "Show Expert -- Show available models UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T3763891899"] = "Show available models" +-- Currently, we cannot query the models for the selected provider and/or host. Therefore, please enter the model name manually. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T4116737656"] = "Currently, we cannot query the models for the selected provider and/or host. Therefore, please enter the model name manually." + -- Model selection UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T416738168"] = "Model selection" @@ -4504,6 +4555,60 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SINGLEINPUTDIALOG::T4030229154"] = "Your Inp -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SINGLEINPUTDIALOG::T900713019"] = "Cancel" +-- Failed to store the API key in the operating system. The message was: {0}. Please try again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1122745046"] = "Failed to store the API key in the operating system. The message was: {0}. Please try again." + +-- API Key +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1324664716"] = "API Key" + +-- Create account +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1356621346"] = "Create account" + +-- Currently, we cannot query the transcription models for the selected provider and/or host. Therefore, please enter the model name manually. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1381635232"] = "Currently, we cannot query the transcription models for the selected provider and/or host. Therefore, please enter the model name manually." + +-- Hostname +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1727440780"] = "Hostname" + +-- Load +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1756340745"] = "Load" + +-- Update +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1847791252"] = "Update" + +-- Failed to load the API key from the operating system. The message was: {0}. You might ignore this message and provide the API key again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1870831108"] = "Failed to load the API key from the operating system. The message was: {0}. You might ignore this message and provide the API key again." + +-- Model +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2189814010"] = "Model" + +-- (Optional) API Key +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2331453405"] = "(Optional) API Key" + +-- Add +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2646845972"] = "Add" + +-- No models loaded or available. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2810182573"] = "No models loaded or available." + +-- Instance Name +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2842060373"] = "Instance Name" + +-- Please enter a transcription model name. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T3703662664"] = "Please enter a transcription model name." + +-- Model selection +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T416738168"] = "Model selection" + +-- Host +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T808120719"] = "Host" + +-- Provider +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T900237532"] = "Provider" + +-- Cancel +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T900713019"] = "Cancel" + -- Install now UI_TEXT_CONTENT["AISTUDIO::DIALOGS::UPDATEDIALOG::T2366359512"] = "Install now" @@ -5206,6 +5311,9 @@ UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Un -- no model selected UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODEL::T2234274832"] = "no model selected" +-- Model as configured by whisper.cpp +UI_TEXT_CONTENT["AISTUDIO::PROVIDER::SELFHOSTED::PROVIDERSELFHOSTED::T3313940770"] = "Model as configured by whisper.cpp" + -- Use no chat template UI_TEXT_CONTENT["AISTUDIO::SETTINGS::CHATTEMPLATE::T4258819635"] = "Use no chat template" @@ -5374,15 +5482,15 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1848 -- 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" --- Speech to Text: Preview of our speech to text system where you can transcribe recordings and audio files into text -UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T221133923"] = "Speech to Text: Preview of our speech to text system where you can transcribe recordings and audio files into text" - -- RAG: Preview of our RAG implementation where you can refer your files or integrate enterprise data within your company UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2708939138"] = "RAG: Preview of our RAG implementation where you can refer your files or integrate enterprise data within your company" -- Unknown preview feature UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2722827307"] = "Unknown preview feature" +-- Transcription: Preview of our speech to text system where you can transcribe recordings and audio files into text +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T714355911"] = "Transcription: Preview of our speech to text system where you can transcribe recordings and audio files into text" + -- Use no data sources, when sending an assistant result to a chat UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::SENDTOCHATDATASOURCEBEHAVIOREXTENSIONS::T1223925477"] = "Use no data sources, when sending an assistant result to a chat" diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor index 69bcfb97..42dd29f9 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor @@ -4,10 +4,10 @@ @if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager)) { - + - @T("Configured Embeddings") + @T("Configured Embedding Providers") @T("Embeddings are a way to represent words, sentences, entire documents, or even images and videos as digital fingerprints. Just like each person has a unique fingerprint, embedding models create unique digital patterns that capture the meaning and characteristics of the content they analyze. When two things are similar in meaning or content, their digital fingerprints will look very similar. For example, the fingerprints for 'happy' and 'joyful' would be more alike than those for 'happy' and 'sad'.") @@ -35,7 +35,7 @@ @context.Num @context.Name @context.UsedLLMProvider.ToName() - @this.GetEmbeddingProviderModelName(context) + @GetEmbeddingProviderModelName(context) @@ -43,10 +43,10 @@ - + - + diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs index ec8a2316..06ce34ea 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs @@ -15,7 +15,7 @@ public partial class SettingsPanelEmbeddings : SettingsPanelBase [Parameter] public EventCallback>> AvailableEmbeddingProvidersChanged { get; set; } - private string GetEmbeddingProviderModelName(EmbeddingProvider provider) + private static string GetEmbeddingProviderModelName(EmbeddingProvider provider) { const int MAX_LENGTH = 36; var modelName = provider.Model.ToString(); diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor index 616149d0..f9567086 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor @@ -3,9 +3,9 @@ @using AIStudio.Provider.SelfHosted @inherits SettingsPanelBase - + - @T("Configured Providers") + @T("Configured LLM Providers") @T("What we call a provider is the combination of an LLM provider such as OpenAI and a model like GPT-4o. You can configure as many providers as you want. This way, you can use the appropriate model for each task. As an LLM provider, you can also choose local providers. However, to use this app, you must configure at least one provider.") @@ -32,11 +32,11 @@ @if (context.UsedLLMProvider is not LLMProviders.SELF_HOSTED) { - @this.GetLLMProviderModelName(context) + @GetLLMProviderModelName(context) } - else if (context.UsedLLMProvider is LLMProviders.SELF_HOSTED && context.Host is not Host.LLAMACPP) + else if (context.UsedLLMProvider is LLMProviders.SELF_HOSTED && context.Host is not Host.LLAMA_CPP) { - @this.GetLLMProviderModelName(context) + @GetLLMProviderModelName(context) } else { @@ -57,10 +57,10 @@ - + - + } diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs index af506e5e..0b68a736 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs @@ -134,7 +134,7 @@ public partial class SettingsPanelProviders : SettingsPanelBase await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); } - private string GetLLMProviderModelName(AIStudio.Settings.Provider provider) + private static string GetLLMProviderModelName(AIStudio.Settings.Provider provider) { const int MAX_LENGTH = 36; var modelName = provider.Model.ToString(); diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor new file mode 100644 index 00000000..fd707c5a --- /dev/null +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor @@ -0,0 +1,64 @@ +@using AIStudio.Provider +@using AIStudio.Settings.DataModel +@inherits SettingsPanelBase + +@if (PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.SettingsManager)) +{ + + + + @T("Configured Transcription Providers") + + + @T("With the support of transcription models, MindWork AI Studio can convert human speech into text. This is useful, for example, when you need to dictate text. You can choose from dedicated transcription models, but not multimodal LLMs (large language models) that can handle both speech and text. The configuration of multimodal models is done in the \"Configure providers\" section.") + + + + + + + + + + + + # + @T("Name") + @T("Provider") + @T("Model") + @T("Actions") + + + @context.Num + @context.Name + @context.UsedLLMProvider.ToName() + @GetTranscriptionProviderModelName(context) + + + + + + + + + + + + + + + + + + @if (this.SettingsManager.ConfigurationData.TranscriptionProviders.Count == 0) + { + + @T("No transcription provider configured yet.") + + } + + + @T("Add transcription provider") + + +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor.cs new file mode 100644 index 00000000..b9e699f7 --- /dev/null +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor.cs @@ -0,0 +1,122 @@ +using AIStudio.Dialogs; +using AIStudio.Settings; + +using Microsoft.AspNetCore.Components; + +using DialogOptions = AIStudio.Dialogs.DialogOptions; + +namespace AIStudio.Components.Settings; + +public partial class SettingsPanelTranscription : SettingsPanelBase +{ + [Parameter] + public List> AvailableTranscriptionProviders { get; set; } = new(); + + [Parameter] + public EventCallback>> AvailableTranscriptionProvidersChanged { get; set; } + + private static string GetTranscriptionProviderModelName(TranscriptionProvider provider) + { + const int MAX_LENGTH = 36; + var modelName = provider.Model.ToString(); + return modelName.Length > MAX_LENGTH ? "[...] " + modelName[^Math.Min(MAX_LENGTH, modelName.Length)..] : modelName; + } + + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + await this.UpdateTranscriptionProviders(); + await base.OnInitializedAsync(); + } + + #endregion + + private async Task AddTranscriptionProvider() + { + var dialogParameters = new DialogParameters + { + { x => x.IsEditing, false }, + }; + + var dialogReference = await this.DialogService.ShowAsync(T("Add Transcription Provider"), dialogParameters, DialogOptions.FULLSCREEN); + var dialogResult = await dialogReference.Result; + if (dialogResult is null || dialogResult.Canceled) + return; + + var addedTranscription = (TranscriptionProvider)dialogResult.Data!; + addedTranscription = addedTranscription with { Num = this.SettingsManager.ConfigurationData.NextTranscriptionNum++ }; + + this.SettingsManager.ConfigurationData.TranscriptionProviders.Add(addedTranscription); + await this.UpdateTranscriptionProviders(); + + await this.SettingsManager.StoreSettings(); + await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); + } + + private async Task EditTranscriptionProvider(TranscriptionProvider transcriptionProvider) + { + var dialogParameters = new DialogParameters + { + { x => x.DataNum, transcriptionProvider.Num }, + { x => x.DataId, transcriptionProvider.Id }, + { x => x.DataName, transcriptionProvider.Name }, + { x => x.DataLLMProvider, transcriptionProvider.UsedLLMProvider }, + { x => x.DataModel, transcriptionProvider.Model }, + { x => x.DataHostname, transcriptionProvider.Hostname }, + { x => x.IsSelfHosted, transcriptionProvider.IsSelfHosted }, + { x => x.IsEditing, true }, + { x => x.DataHost, transcriptionProvider.Host }, + }; + + var dialogReference = await this.DialogService.ShowAsync(T("Edit Transcription Provider"), dialogParameters, DialogOptions.FULLSCREEN); + var dialogResult = await dialogReference.Result; + if (dialogResult is null || dialogResult.Canceled) + return; + + var editedTranscriptionProvider = (TranscriptionProvider)dialogResult.Data!; + + // Set the provider number if it's not set. This is important for providers + // added before we started saving the provider number. + if(editedTranscriptionProvider.Num == 0) + editedTranscriptionProvider = editedTranscriptionProvider with { Num = this.SettingsManager.ConfigurationData.NextTranscriptionNum++ }; + + this.SettingsManager.ConfigurationData.TranscriptionProviders[this.SettingsManager.ConfigurationData.TranscriptionProviders.IndexOf(transcriptionProvider)] = editedTranscriptionProvider; + await this.UpdateTranscriptionProviders(); + + await this.SettingsManager.StoreSettings(); + await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); + } + + private async Task DeleteTranscriptionProvider(TranscriptionProvider provider) + { + var dialogParameters = new DialogParameters + { + { x => x.Message, string.Format(T("Are you sure you want to delete the transcription provider '{0}'?"), provider.Name) }, + }; + + var dialogReference = await this.DialogService.ShowAsync(T("Delete Transcription Provider"), dialogParameters, DialogOptions.FULLSCREEN); + var dialogResult = await dialogReference.Result; + if (dialogResult is null || dialogResult.Canceled) + return; + + var deleteSecretResponse = await this.RustService.DeleteAPIKey(provider); + if(deleteSecretResponse.Success) + { + this.SettingsManager.ConfigurationData.TranscriptionProviders.Remove(provider); + await this.SettingsManager.StoreSettings(); + } + + await this.UpdateTranscriptionProviders(); + await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); + } + + private async Task UpdateTranscriptionProviders() + { + this.AvailableTranscriptionProviders.Clear(); + foreach (var provider in this.SettingsManager.ConfigurationData.TranscriptionProviders) + this.AvailableTranscriptionProviders.Add(new (provider.Name, provider.Id)); + + await this.AvailableTranscriptionProvidersChanged.InvokeAsync(this.AvailableTranscriptionProviders); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor b/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor index c79c80dd..a94b9ebd 100644 --- a/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor +++ b/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor @@ -10,7 +10,7 @@ @foreach (LLMProviders provider in Enum.GetValues(typeof(LLMProviders))) { - if (provider.ProvideEmbeddings() || provider is LLMProviders.NONE) + if (provider.ProvideEmbeddingAPI() || provider is LLMProviders.NONE) { @provider.ToName() @@ -47,7 +47,7 @@ @foreach (Host host in Enum.GetValues(typeof(Host))) { - if (host.AreEmbeddingsSupported()) + if (host.IsEmbeddingSupported()) { @host.Name() @@ -71,12 +71,12 @@ AdornmentColor="Color.Info" Validation="@this.ValidateManuallyModel" UserAttributes="@SPELLCHECK_ATTRIBUTES" - HelperText="@T("Currently, we cannot query the embedding models of self-hosted systems. Therefore, enter the model name manually.")" + HelperText="@T("Currently, we cannot query the embedding models for the selected provider and/or host. Therefore, please enter the model name manually.")" /> } else { - + @T("Load") @if(this.availableModels.Count is 0) diff --git a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor index e4c22f18..dc92f441 100644 --- a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor +++ b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor @@ -44,9 +44,12 @@ @foreach (Host host in Enum.GetValues(typeof(Host))) { - - @host.Name() - + @if (host.IsChatSupported()) + { + + @host.Name() + + } } } @@ -84,11 +87,12 @@ AdornmentColor="Color.Info" Validation="@this.ValidateManuallyModel" UserAttributes="@SPELLCHECK_ATTRIBUTES" + HelperText="@T("Currently, we cannot query the models for the selected provider and/or host. Therefore, please enter the model name manually.")" /> } else { - + @T("Load models") @if(this.availableModels.Count is 0) diff --git a/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor b/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor new file mode 100644 index 00000000..5c862365 --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor @@ -0,0 +1,140 @@ +@using AIStudio.Provider +@using AIStudio.Provider.SelfHosted +@inherits MSGComponentBase + + + + + + @* ReSharper disable once CSharpWarnings::CS8974 *@ + + @foreach (LLMProviders provider in Enum.GetValues(typeof(LLMProviders))) + { + if (provider.ProvideTranscriptionAPI() || provider is LLMProviders.NONE) + { + + @provider.ToName() + + } + } + + + @T("Create account") + + + + @if (this.DataLLMProvider.IsAPIKeyNeeded(this.DataHost)) + { + + } + + @if (this.DataLLMProvider.IsHostnameNeeded()) + { + + } + + @if (this.DataLLMProvider.IsHostNeeded()) + { + + @foreach (Host host in Enum.GetValues(typeof(Host))) + { + if (host.IsTranscriptionSupported()) + { + + @host.Name() + + } + } + + } + + + + @if (this.DataLLMProvider.IsTranscriptionModelProvidedManually(this.DataHost)) + { + + } + else + { + + @T("Load") + + @if(this.availableModels.Count is 0) + { + + @T("No models loaded or available.") + + } + else + { + + @foreach (var model in this.availableModels) + { + + @model + + } + + } + } + + + + @* ReSharper disable once CSharpWarnings::CS8974 *@ + + + + + + + + @T("Cancel") + + + @if(this.IsEditing) + { + @T("Update") + } + else + { + @T("Add") + } + + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor.cs b/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor.cs new file mode 100644 index 00000000..01caa6af --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor.cs @@ -0,0 +1,272 @@ +using AIStudio.Components; +using AIStudio.Provider; +using AIStudio.Settings; +using AIStudio.Tools.Services; +using AIStudio.Tools.Validation; + +using Microsoft.AspNetCore.Components; + +using Host = AIStudio.Provider.SelfHosted.Host; + +namespace AIStudio.Dialogs; + +public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId +{ + [CascadingParameter] + private IMudDialogInstance MudDialog { get; set; } = null!; + + /// + /// The transcription provider's number in the list. + /// + [Parameter] + public uint DataNum { get; set; } + + /// + /// The transcription provider's ID. + /// + [Parameter] + public string DataId { get; set; } = Guid.NewGuid().ToString(); + + /// + /// The user chosen name. + /// + [Parameter] + public string DataName { get; set; } = string.Empty; + + /// + /// The chosen hostname for self-hosted providers. + /// + [Parameter] + public string DataHostname { get; set; } = string.Empty; + + /// + /// The host to use, e.g., llama.cpp. + /// + [Parameter] + public Host DataHost { get; set; } = Host.NONE; + + /// + /// Is this provider self-hosted? + /// + [Parameter] + public bool IsSelfHosted { get; set; } + + /// + /// The provider to use. + /// + [Parameter] + public LLMProviders DataLLMProvider { get; set; } = LLMProviders.NONE; + + /// + /// The transcription model to use. + /// + [Parameter] + public Model DataModel { get; set; } + + /// + /// Should the dialog be in editing mode? + /// + [Parameter] + public bool IsEditing { get; init; } + + [Inject] + private RustService RustService { get; init; } = null!; + + private static readonly Dictionary SPELLCHECK_ATTRIBUTES = new(); + + /// + /// The list of used instance names. We need this to check for uniqueness. + /// + private List UsedInstanceNames { get; set; } = []; + + private bool dataIsValid; + private string[] dataIssues = []; + private string dataAPIKey = string.Empty; + private string dataManuallyModel = string.Empty; + private string dataAPIKeyStorageIssue = string.Empty; + private string dataEditingPreviousInstanceName = string.Empty; + + // We get the form reference from Blazor code to validate it manually: + private MudForm form = null!; + + private readonly List availableModels = new(); + private readonly Encryption encryption = Program.ENCRYPTION; + private readonly ProviderValidation providerValidation; + + public TranscriptionProviderDialog() + { + this.providerValidation = new() + { + GetProvider = () => this.DataLLMProvider, + GetAPIKeyStorageIssue = () => this.dataAPIKeyStorageIssue, + GetPreviousInstanceName = () => this.dataEditingPreviousInstanceName, + GetUsedInstanceNames = () => this.UsedInstanceNames, + GetHost = () => this.DataHost, + }; + } + + private TranscriptionProvider CreateTranscriptionProviderSettings() + { + var cleanedHostname = this.DataHostname.Trim(); + Model model = default; + if(this.DataLLMProvider is LLMProviders.SELF_HOSTED) + { + switch (this.DataHost) + { + case Host.OLLAMA: + model = new Model(this.dataManuallyModel, null); + break; + + case Host.VLLM: + case Host.LM_STUDIO: + case Host.WHISPER_CPP: + model = this.DataModel; + break; + } + } + else + model = this.DataModel; + + return new() + { + Num = this.DataNum, + Id = this.DataId, + Name = this.DataName, + UsedLLMProvider = this.DataLLMProvider, + Model = model, + IsSelfHosted = this.DataLLMProvider is LLMProviders.SELF_HOSTED, + Hostname = cleanedHostname.EndsWith('/') ? cleanedHostname[..^1] : cleanedHostname, + Host = this.DataHost, + }; + } + + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + // Configure the spellchecking for the instance name input: + this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES); + + // Load the used instance names: + this.UsedInstanceNames = this.SettingsManager.ConfigurationData.TranscriptionProviders.Select(x => x.Name.ToLowerInvariant()).ToList(); + + // When editing, we need to load the data: + if(this.IsEditing) + { + this.dataEditingPreviousInstanceName = this.DataName.ToLowerInvariant(); + + // When using self-hosted models, we must copy the model name: + if (this.DataLLMProvider is LLMProviders.SELF_HOSTED) + this.dataManuallyModel = this.DataModel.Id; + + // + // We cannot load the API key for self-hosted providers: + // + if (this.DataLLMProvider is LLMProviders.SELF_HOSTED && this.DataHost is not Host.OLLAMA) + { + await this.ReloadModels(); + await base.OnInitializedAsync(); + return; + } + + // Load the API key: + var requestedSecret = await this.RustService.GetAPIKey(this, isTrying: this.DataLLMProvider is LLMProviders.SELF_HOSTED); + if (requestedSecret.Success) + this.dataAPIKey = await requestedSecret.Secret.Decrypt(this.encryption); + else + { + this.dataAPIKey = string.Empty; + if (this.DataLLMProvider is not LLMProviders.SELF_HOSTED) + { + this.dataAPIKeyStorageIssue = string.Format(T("Failed to load the API key from the operating system. The message was: {0}. You might ignore this message and provide the API key again."), requestedSecret.Issue); + await this.form.Validate(); + } + } + + await this.ReloadModels(); + } + + await base.OnInitializedAsync(); + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + // Reset the validation when not editing and on the first render. + // We don't want to show validation errors when the user opens the dialog. + if(!this.IsEditing && firstRender) + this.form.ResetValidation(); + + await base.OnAfterRenderAsync(firstRender); + } + + #endregion + + #region Implementation of ISecretId + + public string SecretId => this.DataId; + + public string SecretName => this.DataName; + + #endregion + + private async Task Store() + { + await this.form.Validate(); + this.dataAPIKeyStorageIssue = string.Empty; + + // When the data is not valid, we don't store it: + if (!this.dataIsValid) + return; + + // Use the data model to store the provider. + // We just return this data to the parent component: + var addedProviderSettings = this.CreateTranscriptionProviderSettings(); + if (!string.IsNullOrWhiteSpace(this.dataAPIKey)) + { + // Store the API key in the OS secure storage: + var storeResponse = await this.RustService.SetAPIKey(this, this.dataAPIKey); + if (!storeResponse.Success) + { + this.dataAPIKeyStorageIssue = string.Format(T("Failed to store the API key in the operating system. The message was: {0}. Please try again."), storeResponse.Issue); + await this.form.Validate(); + return; + } + } + + this.MudDialog.Close(DialogResult.Ok(addedProviderSettings)); + } + + private string? ValidateManuallyModel(string manuallyModel) + { + if (this.DataLLMProvider is LLMProviders.SELF_HOSTED && string.IsNullOrWhiteSpace(manuallyModel)) + return T("Please enter a transcription model name."); + + return null; + } + + private void Cancel() => this.MudDialog.Cancel(); + + private async Task ReloadModels() + { + var currentTranscriptionProviderSettings = this.CreateTranscriptionProviderSettings(); + var provider = currentTranscriptionProviderSettings.CreateProvider(); + if(provider is NoProvider) + return; + + var models = await provider.GetTranscriptionModels(this.dataAPIKey); + + // Order descending by ID means that the newest models probably come first: + var orderedModels = models.OrderByDescending(n => n.Id); + + this.availableModels.Clear(); + this.availableModels.AddRange(orderedModels); + } + + private string APIKeyText => this.DataLLMProvider switch + { + LLMProviders.SELF_HOSTED => T("(Optional) API Key"), + _ => T("API Key"), + }; + + private bool IsNoneProvider => this.DataLLMProvider is LLMProviders.NONE; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Pages/Settings.razor b/app/MindWork AI Studio/Pages/Settings.razor index 7931453f..70201807 100644 --- a/app/MindWork AI Studio/Pages/Settings.razor +++ b/app/MindWork AI Studio/Pages/Settings.razor @@ -15,6 +15,11 @@ } + @if (PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.SettingsManager)) + { + + } + @if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager)) diff --git a/app/MindWork AI Studio/Pages/Settings.razor.cs b/app/MindWork AI Studio/Pages/Settings.razor.cs index 89c7338b..561ebb46 100644 --- a/app/MindWork AI Studio/Pages/Settings.razor.cs +++ b/app/MindWork AI Studio/Pages/Settings.razor.cs @@ -9,6 +9,7 @@ public partial class Settings : MSGComponentBase { private List> availableLLMProviders = new(); private List> availableEmbeddingProviders = new(); + private List> availableTranscriptionProviders = new(); #region Overrides of ComponentBase diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index e2ad8227..bded7fd4 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -2109,15 +2109,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T24199 -- Name UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T266367750"] = "Name" +-- Configured Embedding Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T305753126"] = "Konfigurierte Anbieter für Einbettungen" + -- This helps AI Studio understand and compare things in a way that's similar to how humans do. When you're working on something, AI Studio can automatically identify related documents and data by comparing their digital fingerprints. For instance, if you're writing about customer service, AI Studio can instantly find other documents in your data that discuss similar topics or experiences, even if they use different words. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3251217940"] = "Dies hilft AI Studio, Dinge auf eine Art und Weise zu verstehen und zu vergleichen, die der menschlichen Denkweise ähnelt. Wenn Sie an etwas arbeiten, kann AI Studio automatisch verwandte Dokumente und Daten erkennen, indem es ihre digitalen Fingerabdrücke vergleicht. Wenn Sie zum Beispiel über Kundenservice schreiben, kann AI Studio sofort andere Dokumente in ihren Daten finden, die über ähnliche Themen oder Erfahrungen sprechen – selbst wenn sie andere Begriffe verwenden." -- Edit UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3267849393"] = "Bearbeiten" --- Configured Embeddings -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3526613453"] = "Konfigurierte Einbettungen" - -- Actions UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3865031940"] = "Aktionen" @@ -2127,6 +2127,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T40680 -- Edit Embedding Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T4264602229"] = "Einbettungsanbieter bearbeiten" +-- Configure Embedding Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T488419116"] = "Anbieter für Einbettungen konfigurieren" + -- Delete Embedding Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T511304264"] = "Einbettungsanbieter löschen" @@ -2136,9 +2139,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T78223 -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T900237532"] = "Anbieter" --- Configure Embeddings -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T970042679"] = "Einbettungen konfigurieren" - -- Show provider's confidence level? UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1052533048"] = "Anzeigen, wie sicher sich der Anbieter ist?" @@ -2157,6 +2157,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T172585 -- Add Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1806589097"] = "Anbieter hinzufügen" +-- Configure LLM Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1810190350"] = "Anbieter für LLM konfigurieren" + -- Edit LLM Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1868766523"] = "LLM-Anbieter bearbeiten" @@ -2190,8 +2193,8 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T284206 -- No providers configured yet. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T2911731076"] = "Noch keine Anbieter konfiguriert." --- Configure Providers -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3027859089"] = "Anbieter konfigurieren" +-- Configured LLM Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3019870540"] = "Konfigurierte Anbieter für LLM" -- as selected by provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3082210376"] = "wie vom Anbieter ausgewählt" @@ -2214,9 +2217,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T361241 -- No, do not enforce a minimum confidence level UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3642102079"] = "Nein, kein Mindestvertrauensniveau erzwingen" --- Configured Providers -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3850871263"] = "Konfigurierte Anbieter" - -- Actions UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3865031940"] = "Aktionen" @@ -2244,6 +2244,54 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T853225 -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T900237532"] = "Anbieter" +-- No transcription provider configured yet. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "Es ist bisher kein Anbieter für Transkriptionen konfiguriert." + +-- Edit Transcription Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1317362918"] = "Anbieter für Transkriptionen bearbeiten" + +-- Delete +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1469573738"] = "Löschen" + +-- Add transcription provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1645238629"] = "Anbieter für Transkriptionen hinzufügen" + +-- Add Transcription Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T2066315685"] = "Anbieter für Transkriptionen hinzufügen" + +-- Model +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T2189814010"] = "Modell" + +-- Name +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T266367750"] = "Name" + +-- Edit +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T3267849393"] = "Bearbeiten" + +-- Delete Transcription Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T370103955"] = "Anbieter für Transkriptionen löschen" + +-- Actions +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T3865031940"] = "Aktionen" + +-- Configure Transcription Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T4073110625"] = "Anbieter für Transkriptionen konfigurieren" + +-- Configured Transcription Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T4210863523"] = "Konfigurierte Anbieter für Transkriptionen" + +-- Open Dashboard +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T78223861"] = "Dashboard öffnen" + +-- Are you sure you want to delete the transcription provider '{0}'? +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T789660305"] = "Möchten Sie den Anbieter für Transkriptionen „{0}“ wirklich löschen?" + +-- With the support of transcription models, MindWork AI Studio can convert human speech into text. This is useful, for example, when you need to dictate text. You can choose from dedicated transcription models, but not multimodal LLMs (large language models) that can handle both speech and text. The configuration of multimodal models is done in the \"Configure providers\" section. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T799338148"] = "Mit Unterstützung von Modellen für Transkriptionen kann MindWork AI Studio menschliche Sprache in Text umwandeln. Das ist zum Beispiel hilfreich, wenn Sie Texte diktieren möchten. Sie können aus speziellen Modellen für Transkriptionen wählen, jedoch nicht aus multimodalen LLMs (Large Language Models), die sowohl Sprache als auch Text verarbeiten können. Die Einrichtung multimodaler Modelle erfolgt im Abschnitt „Anbieter konfigurieren“." + +-- Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T900237532"] = "Anbieter" + -- Copy {0} to the clipboard UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Kopiere {0} in die Zwischenablage" @@ -3108,9 +3156,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2189814010"] = "Mo -- (Optional) API Key UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2331453405"] = "(Optional) API-Schlüssel" --- Currently, we cannot query the embedding models of self-hosted systems. Therefore, enter the model name manually. -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2615586687"] = "Derzeit können wir die Einbettungs-Modelle von selbst gehosteten Systemen nicht abfragen. Bitte geben Sie daher den Modellnamen manuell ein." - -- Add UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2646845972"] = "Hinzufügen" @@ -3120,6 +3165,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2810182573"] = "Ke -- Instance Name UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2842060373"] = "Instanzname" +-- Currently, we cannot query the embedding models for the selected provider and/or host. Therefore, please enter the model name manually. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T290547799"] = "Derzeit können wir die Einbettungs-Modelle für den ausgewählten Anbieter und/oder Host nicht abfragen. Bitte geben Sie daher den Modellnamen manuell ein." + -- Model selection UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T416738168"] = "Modellauswahl" @@ -3330,6 +3378,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T3361153305"] = "Experten-Ei -- Show available models UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T3763891899"] = "Verfügbare Modelle anzeigen" +-- Currently, we cannot query the models for the selected provider and/or host. Therefore, please enter the model name manually. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T4116737656"] = "Derzeit können wir die Modelle für den ausgewählten Anbieter und/oder Host nicht abfragen. Bitte geben Sie daher den Modellnamen manuell ein." + -- Model selection UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T416738168"] = "Modellauswahl" @@ -4506,6 +4557,60 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SINGLEINPUTDIALOG::T4030229154"] = "Ihre Ein -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SINGLEINPUTDIALOG::T900713019"] = "Abbrechen" +-- Failed to store the API key in the operating system. The message was: {0}. Please try again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1122745046"] = "Der API-Schlüssel konnte nicht im Betriebssystem gespeichert werden. Die Meldung lautete: '{0}'. Bitte versuchen Sie es erneut." + +-- API Key +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1324664716"] = "API-Schlüssel" + +-- Create account +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1356621346"] = "Konto erstellen" + +-- Currently, we cannot query the transcription models for the selected provider and/or host. Therefore, please enter the model name manually. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1381635232"] = "Derzeit können wir die Modelle für Transkriptionen für den ausgewählten Anbieter und/oder Host nicht abfragen. Bitte geben Sie daher den Modellnamen manuell ein." + +-- Hostname +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1727440780"] = "Hostname" + +-- Load +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1756340745"] = "Laden" + +-- Update +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1847791252"] = "Aktualisieren" + +-- Failed to load the API key from the operating system. The message was: {0}. You might ignore this message and provide the API key again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1870831108"] = "Der API-Schlüssel konnte nicht aus dem Betriebssystem geladen werden. Die Meldung lautete: '{0}'. Sie können diese Meldung ignorieren und den API-Schlüssel erneut eingeben." + +-- Model +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2189814010"] = "Modell" + +-- (Optional) API Key +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2331453405"] = "(Optional) API-Schlüssel" + +-- Add +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2646845972"] = "Hinzufügen" + +-- No models loaded or available. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2810182573"] = "Keine Modelle geladen oder verfügbar." + +-- Instance Name +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2842060373"] = "Instanzname" + +-- Please enter a transcription model name. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T3703662664"] = "Bitte geben Sie den Namen eines Transkriptionsmodells ein." + +-- Model selection +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T416738168"] = "Modellauswahl" + +-- Host +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T808120719"] = "Host" + +-- Provider +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T900237532"] = "Anbieter" + +-- Cancel +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T900713019"] = "Abbrechen" + -- Install now UI_TEXT_CONTENT["AISTUDIO::DIALOGS::UPDATEDIALOG::T2366359512"] = "Jetzt installieren" @@ -5208,6 +5313,9 @@ UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Un -- no model selected UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODEL::T2234274832"] = "Kein Modell ausgewählt" +-- Model as configured by whisper.cpp +UI_TEXT_CONTENT["AISTUDIO::PROVIDER::SELFHOSTED::PROVIDERSELFHOSTED::T3313940770"] = "Modell wie in whisper.cpp konfiguriert" + -- Use no chat template UI_TEXT_CONTENT["AISTUDIO::SETTINGS::CHATTEMPLATE::T4258819635"] = "Keine Chat-Vorlage verwenden" @@ -5376,15 +5484,15 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1848 -- 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" --- Speech to Text: Preview of our speech to text system where you can transcribe recordings and audio files into text -UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T221133923"] = "Sprache zu Text: Vorschau unseres Sprache-zu-Text-Systems, mit dem Sie Aufnahmen und Audiodateien in Text transkribieren können." - -- RAG: Preview of our RAG implementation where you can refer your files or integrate enterprise data within your company UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2708939138"] = "RAG: Vorschau auf unsere RAG-Implementierung, mit der Sie auf ihre Dateien zugreifen oder Unternehmensdaten in ihrem Unternehmen integrieren können" -- Unknown preview feature UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2722827307"] = "Unbekannte Vorschau-Funktion" +-- Transcription: Preview of our speech to text system where you can transcribe recordings and audio files into text +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T714355911"] = "Transkription: Vorschau unseres Sprache-zu-Text-Systems, mit dem Sie Aufnahmen und Audiodateien in Text transkribieren können" + -- Use no data sources, when sending an assistant result to a chat UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::SENDTOCHATDATASOURCEBEHAVIOREXTENSIONS::T1223925477"] = "Keine Datenquellen vorauswählen, wenn ein Ergebnis von einem Assistenten an einen neuen Chat gesendet wird" diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index 1057ad86..bd4bc772 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -2109,15 +2109,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T24199 -- Name UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T266367750"] = "Name" +-- Configured Embedding Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T305753126"] = "Configured Embedding Providers" + -- This helps AI Studio understand and compare things in a way that's similar to how humans do. When you're working on something, AI Studio can automatically identify related documents and data by comparing their digital fingerprints. For instance, if you're writing about customer service, AI Studio can instantly find other documents in your data that discuss similar topics or experiences, even if they use different words. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3251217940"] = "This helps AI Studio understand and compare things in a way that's similar to how humans do. When you're working on something, AI Studio can automatically identify related documents and data by comparing their digital fingerprints. For instance, if you're writing about customer service, AI Studio can instantly find other documents in your data that discuss similar topics or experiences, even if they use different words." -- Edit UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3267849393"] = "Edit" --- Configured Embeddings -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3526613453"] = "Configured Embeddings" - -- Actions UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T3865031940"] = "Actions" @@ -2127,6 +2127,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T40680 -- Edit Embedding Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T4264602229"] = "Edit Embedding Provider" +-- Configure Embedding Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T488419116"] = "Configure Embedding Providers" + -- Delete Embedding Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T511304264"] = "Delete Embedding Provider" @@ -2136,9 +2139,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T78223 -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T900237532"] = "Provider" --- Configure Embeddings -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T970042679"] = "Configure Embeddings" - -- Show provider's confidence level? UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1052533048"] = "Show provider's confidence level?" @@ -2157,6 +2157,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T172585 -- Add Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1806589097"] = "Add Provider" +-- Configure LLM Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1810190350"] = "Configure LLM Providers" + -- Edit LLM Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T1868766523"] = "Edit LLM Provider" @@ -2190,8 +2193,8 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T284206 -- No providers configured yet. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T2911731076"] = "No providers configured yet." --- Configure Providers -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3027859089"] = "Configure Providers" +-- Configured LLM Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3019870540"] = "Configured LLM Providers" -- as selected by provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3082210376"] = "as selected by provider" @@ -2214,9 +2217,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T361241 -- No, do not enforce a minimum confidence level UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3642102079"] = "No, do not enforce a minimum confidence level" --- Configured Providers -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3850871263"] = "Configured Providers" - -- Actions UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T3865031940"] = "Actions" @@ -2244,6 +2244,54 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T853225 -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T900237532"] = "Provider" +-- No transcription provider configured yet. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "No transcription provider configured yet." + +-- Edit Transcription Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1317362918"] = "Edit Transcription Provider" + +-- Delete +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1469573738"] = "Delete" + +-- Add transcription provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1645238629"] = "Add transcription provider" + +-- Add Transcription Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T2066315685"] = "Add Transcription Provider" + +-- Model +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T2189814010"] = "Model" + +-- Name +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T266367750"] = "Name" + +-- Edit +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T3267849393"] = "Edit" + +-- Delete Transcription Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T370103955"] = "Delete Transcription Provider" + +-- Actions +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T3865031940"] = "Actions" + +-- Configure Transcription Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T4073110625"] = "Configure Transcription Providers" + +-- Configured Transcription Providers +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T4210863523"] = "Configured Transcription Providers" + +-- Open Dashboard +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T78223861"] = "Open Dashboard" + +-- Are you sure you want to delete the transcription provider '{0}'? +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T789660305"] = "Are you sure you want to delete the transcription provider '{0}'?" + +-- With the support of transcription models, MindWork AI Studio can convert human speech into text. This is useful, for example, when you need to dictate text. You can choose from dedicated transcription models, but not multimodal LLMs (large language models) that can handle both speech and text. The configuration of multimodal models is done in the \"Configure providers\" section. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T799338148"] = "With the support of transcription models, MindWork AI Studio can convert human speech into text. This is useful, for example, when you need to dictate text. You can choose from dedicated transcription models, but not multimodal LLMs (large language models) that can handle both speech and text. The configuration of multimodal models is done in the \\\"Configure providers\\\" section." + +-- Provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T900237532"] = "Provider" + -- Copy {0} to the clipboard UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Copy {0} to the clipboard" @@ -3108,9 +3156,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2189814010"] = "Mo -- (Optional) API Key UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2331453405"] = "(Optional) API Key" --- Currently, we cannot query the embedding models of self-hosted systems. Therefore, enter the model name manually. -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2615586687"] = "Currently, we cannot query the embedding models of self-hosted systems. Therefore, enter the model name manually." - -- Add UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2646845972"] = "Add" @@ -3120,6 +3165,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2810182573"] = "No -- Instance Name UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2842060373"] = "Instance Name" +-- Currently, we cannot query the embedding models for the selected provider and/or host. Therefore, please enter the model name manually. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T290547799"] = "Currently, we cannot query the embedding models for the selected provider and/or host. Therefore, please enter the model name manually." + -- Model selection UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T416738168"] = "Model selection" @@ -3330,6 +3378,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T3361153305"] = "Show Expert -- Show available models UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T3763891899"] = "Show available models" +-- Currently, we cannot query the models for the selected provider and/or host. Therefore, please enter the model name manually. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T4116737656"] = "Currently, we cannot query the models for the selected provider and/or host. Therefore, please enter the model name manually." + -- Model selection UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROVIDERDIALOG::T416738168"] = "Model selection" @@ -4506,6 +4557,60 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SINGLEINPUTDIALOG::T4030229154"] = "Your Inp -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SINGLEINPUTDIALOG::T900713019"] = "Cancel" +-- Failed to store the API key in the operating system. The message was: {0}. Please try again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1122745046"] = "Failed to store the API key in the operating system. The message was: {0}. Please try again." + +-- API Key +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1324664716"] = "API Key" + +-- Create account +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1356621346"] = "Create account" + +-- Currently, we cannot query the transcription models for the selected provider and/or host. Therefore, please enter the model name manually. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1381635232"] = "Currently, we cannot query the transcription models for the selected provider and/or host. Therefore, please enter the model name manually." + +-- Hostname +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1727440780"] = "Hostname" + +-- Load +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1756340745"] = "Load" + +-- Update +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1847791252"] = "Update" + +-- Failed to load the API key from the operating system. The message was: {0}. You might ignore this message and provide the API key again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T1870831108"] = "Failed to load the API key from the operating system. The message was: {0}. You might ignore this message and provide the API key again." + +-- Model +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2189814010"] = "Model" + +-- (Optional) API Key +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2331453405"] = "(Optional) API Key" + +-- Add +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2646845972"] = "Add" + +-- No models loaded or available. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2810182573"] = "No models loaded or available." + +-- Instance Name +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T2842060373"] = "Instance Name" + +-- Please enter a transcription model name. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T3703662664"] = "Please enter a transcription model name." + +-- Model selection +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T416738168"] = "Model selection" + +-- Host +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T808120719"] = "Host" + +-- Provider +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T900237532"] = "Provider" + +-- Cancel +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::TRANSCRIPTIONPROVIDERDIALOG::T900713019"] = "Cancel" + -- Install now UI_TEXT_CONTENT["AISTUDIO::DIALOGS::UPDATEDIALOG::T2366359512"] = "Install now" @@ -5208,6 +5313,9 @@ UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Un -- no model selected UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODEL::T2234274832"] = "no model selected" +-- Model as configured by whisper.cpp +UI_TEXT_CONTENT["AISTUDIO::PROVIDER::SELFHOSTED::PROVIDERSELFHOSTED::T3313940770"] = "Model as configured by whisper.cpp" + -- Use no chat template UI_TEXT_CONTENT["AISTUDIO::SETTINGS::CHATTEMPLATE::T4258819635"] = "Use no chat template" @@ -5376,15 +5484,15 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1848 -- 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" --- Speech to Text: Preview of our speech to text system where you can transcribe recordings and audio files into text -UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T221133923"] = "Speech to Text: Preview of our speech to text system where you can transcribe recordings and audio files into text" - -- RAG: Preview of our RAG implementation where you can refer your files or integrate enterprise data within your company UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2708939138"] = "RAG: Preview of our RAG implementation where you can refer your files or integrate enterprise data within your company" -- Unknown preview feature UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2722827307"] = "Unknown preview feature" +-- Transcription: Preview of our speech to text system where you can transcribe recordings and audio files into text +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T714355911"] = "Transcription: Preview of our speech to text system where you can transcribe recordings and audio files into text" + -- Use no data sources, when sending an assistant result to a chat UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::SENDTOCHATDATASOURCEBEHAVIOREXTENSIONS::T1223925477"] = "Use no data sources, when sending an assistant result to a chat" diff --git a/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs b/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs index dacfeea5..6b648372 100644 --- a/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs +++ b/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs @@ -131,8 +131,17 @@ public sealed class ProviderAlibabaCloud() : BaseProvider(LLMProviders.ALIBABA_C return this.LoadModels(["text-embedding-"], token, apiKeyProvisional).ContinueWith(t => t.Result.Concat(additionalModels).OrderBy(x => x.Id).AsEnumerable(), token); } - - + + #region Overrides of BaseProvider + + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } + + #endregion + #endregion private async Task> LoadModels(string[] prefixes, CancellationToken token, string? apiKeyProvisional = null) diff --git a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs index 7f02781b..42268936 100644 --- a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs +++ b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs @@ -136,6 +136,12 @@ public sealed class ProviderAnthropic() : BaseProvider(LLMProviders.ANTHROPIC, " return Task.FromResult(Enumerable.Empty()); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } + #endregion private async Task> LoadModels(CancellationToken token, string? apiKeyProvisional = null) diff --git a/app/MindWork AI Studio/Provider/BaseProvider.cs b/app/MindWork AI Studio/Provider/BaseProvider.cs index 62464910..c5594087 100644 --- a/app/MindWork AI Studio/Provider/BaseProvider.cs +++ b/app/MindWork AI Studio/Provider/BaseProvider.cs @@ -97,6 +97,9 @@ public abstract class BaseProvider : IProvider, ISecretId /// public abstract Task> GetEmbeddingModels(string? apiKeyProvisional = null, CancellationToken token = default); + + /// + public abstract Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default); #endregion diff --git a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs index 4b597601..b2715f47 100644 --- a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs +++ b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs @@ -99,6 +99,11 @@ public sealed class ProviderDeepSeek() : BaseProvider(LLMProviders.DEEP_SEEK, "h return Task.FromResult(Enumerable.Empty()); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } #endregion diff --git a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs index 5e056674..9450134d 100644 --- a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs +++ b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs @@ -100,5 +100,16 @@ public class ProviderFireworks() : BaseProvider(LLMProviders.FIREWORKS, "https:/ return Task.FromResult(Enumerable.Empty()); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult>( + new List + { + new("whisper-v3", "Whisper v3"), + new("whisper-v3-turbo", "Whisper v3 Turbo"), + }); + } + #endregion } \ No newline at end of file diff --git a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs index deecd6d5..da322942 100644 --- a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs +++ b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs @@ -101,6 +101,17 @@ public sealed class ProviderGWDG() : BaseProvider(LLMProviders.GWDG, "https://ch return models.Where(model => model.Id.StartsWith("e5-", StringComparison.InvariantCultureIgnoreCase)); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + // Source: https://docs.hpc.gwdg.de/services/saia/index.html#voice-to-text + return Task.FromResult>( + new List + { + new("whisper-large-v2", "Whisper v2 Large"), + }); + } + #endregion private async Task> LoadModels(CancellationToken token, string? apiKeyProvisional = null) diff --git a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs index a53368f9..fce1a451 100644 --- a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs +++ b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs @@ -112,6 +112,11 @@ public class ProviderGoogle() : BaseProvider(LLMProviders.GOOGLE, "https://gener .Select(n => new Provider.Model(n.Name.Replace("models/", string.Empty), n.DisplayName)); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } #endregion diff --git a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs index 60d449b0..b6e9137a 100644 --- a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs +++ b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs @@ -100,6 +100,12 @@ public class ProviderGroq() : BaseProvider(LLMProviders.GROQ, "https://api.groq. return Task.FromResult(Enumerable.Empty()); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } + #endregion private async Task> LoadModels(CancellationToken token, string? apiKeyProvisional = null) diff --git a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs index 07263d39..213bf075 100644 --- a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs +++ b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs @@ -105,6 +105,12 @@ public sealed class ProviderHelmholtz() : BaseProvider(LLMProviders.HELMHOLTZ, " model.Id.Contains("gritlm", StringComparison.InvariantCultureIgnoreCase)); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } + #endregion private async Task> LoadModels(CancellationToken token, string? apiKeyProvisional = null) diff --git a/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs b/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs index cfd2346c..794b4f42 100644 --- a/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs +++ b/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs @@ -104,5 +104,11 @@ public sealed class ProviderHuggingFace : BaseProvider return Task.FromResult(Enumerable.Empty()); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } + #endregion } \ No newline at end of file diff --git a/app/MindWork AI Studio/Provider/IProvider.cs b/app/MindWork AI Studio/Provider/IProvider.cs index 41d9b37d..4ae6dc6c 100644 --- a/app/MindWork AI Studio/Provider/IProvider.cs +++ b/app/MindWork AI Studio/Provider/IProvider.cs @@ -74,4 +74,11 @@ public interface IProvider /// The list of embedding models. public Task> GetEmbeddingModels(string? apiKeyProvisional = null, CancellationToken token = default); + /// + /// Load all possible transcription models that can be used with this provider. + /// + /// The provisional API key to use. Useful when the user is adding a new provider. When null, the stored API key is used. + /// >The cancellation token. + /// >The list of transcription models. + public Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Provider/LLMProvidersExtensions.cs b/app/MindWork AI Studio/Provider/LLMProvidersExtensions.cs index 91dfba8e..ea548923 100644 --- a/app/MindWork AI Studio/Provider/LLMProvidersExtensions.cs +++ b/app/MindWork AI Studio/Provider/LLMProvidersExtensions.cs @@ -110,7 +110,7 @@ public static class LLMProvidersExtensions /// /// The provider to check. /// True if the provider supports embeddings; otherwise, false. - public static bool ProvideEmbeddings(this LLMProviders llmProvider) => llmProvider switch + public static bool ProvideEmbeddingAPI(this LLMProviders llmProvider) => llmProvider switch { // // Providers that support embeddings: @@ -141,6 +141,43 @@ public static class LLMProvidersExtensions _ => false, }; + + public static bool ProvideTranscriptionAPI(this LLMProviders llmProvider) => llmProvider switch + { + // + // Providers that support transcription: + // + LLMProviders.OPEN_AI => true, + LLMProviders.MISTRAL => true, + LLMProviders.FIREWORKS => true, + LLMProviders.GWDG => true, + + // + // Providers that support transcription but provide no OpenAI-compatible API yet: + // + LLMProviders.ALIBABA_CLOUD => false, + LLMProviders.GOOGLE => false, + + // + // Providers that do not support transcription: + // + LLMProviders.OPEN_ROUTER => false, + LLMProviders.GROQ => false, + LLMProviders.ANTHROPIC => false, + LLMProviders.X => false, + LLMProviders.DEEP_SEEK => false, + LLMProviders.HUGGINGFACE => false, + LLMProviders.PERPLEXITY => false, + + LLMProviders.HELMHOLTZ => false, + + // + // Self-hosted providers are treated as a special case anyway. + // + LLMProviders.SELF_HOSTED => true, + + _ => false, + }; /// /// Creates a new provider instance based on the provider value. @@ -162,6 +199,16 @@ public static class LLMProvidersExtensions return embeddingProviderSettings.UsedLLMProvider.CreateProvider(embeddingProviderSettings.Name, embeddingProviderSettings.Host, embeddingProviderSettings.Hostname, embeddingProviderSettings.Model, HFInferenceProvider.NONE); } + /// + /// Creates a new provider instance based on the speech provider value. + /// + /// The speech provider settings. + /// The provider instance. + public static IProvider CreateProvider(this TranscriptionProvider transcriptionProviderSettings) + { + return transcriptionProviderSettings.UsedLLMProvider.CreateProvider(transcriptionProviderSettings.Name, transcriptionProviderSettings.Host, transcriptionProviderSettings.Hostname, transcriptionProviderSettings.Model, HFInferenceProvider.NONE); + } + private static IProvider CreateProvider(this LLMProviders provider, string instanceName, Host host, string hostname, Model model, HFInferenceProvider inferenceProvider, string expertProviderApiParameter = "") { try @@ -274,6 +321,11 @@ public static class LLMProvidersExtensions LLMProviders.SELF_HOSTED => host is not Host.LM_STUDIO, _ => false, }; + + public static bool IsTranscriptionModelProvidedManually(this LLMProviders provider, Host host) => provider switch + { + _ => false, + }; public static bool IsHostNeeded(this LLMProviders provider) => provider switch { @@ -338,13 +390,14 @@ public static class LLMProvidersExtensions switch (host) { case Host.NONE: - case Host.LLAMACPP: + case Host.LLAMA_CPP: default: return false; case Host.OLLAMA: case Host.LM_STUDIO: case Host.VLLM: + case Host.WHISPER_CPP: return true; } } diff --git a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs index 522757ea..598f7016 100644 --- a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs +++ b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs @@ -113,6 +113,17 @@ public sealed class ProviderMistral() : BaseProvider(LLMProviders.MISTRAL, "http return Task.FromResult(Enumerable.Empty()); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + // Source: https://docs.mistral.ai/capabilities/audio_transcription + return Task.FromResult>( + new List + { + new("voxtral-mini-latest", "Voxtral Mini Latest"), + }); + } + #endregion private async Task LoadModelList(string? apiKeyProvisional, CancellationToken token) diff --git a/app/MindWork AI Studio/Provider/NoProvider.cs b/app/MindWork AI Studio/Provider/NoProvider.cs index 73d75d61..4f92e5c9 100644 --- a/app/MindWork AI Studio/Provider/NoProvider.cs +++ b/app/MindWork AI Studio/Provider/NoProvider.cs @@ -23,6 +23,8 @@ public class NoProvider : IProvider public Task> GetImageModels(string? apiKeyProvisional = null, CancellationToken token = default) => Task.FromResult>([]); public Task> GetEmbeddingModels(string? apiKeyProvisional = null, CancellationToken token = default) => Task.FromResult>([]); + + public Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) => Task.FromResult>([]); public async IAsyncEnumerable StreamChatCompletion(Model chatModel, ChatThread chatChatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default) { diff --git a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs index b5a11e60..d06d6e15 100644 --- a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs +++ b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs @@ -241,6 +241,14 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, "https return this.LoadModels(["text-embedding-"], token, apiKeyProvisional); } + /// + public override async Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + var models = await this.LoadModels(["whisper-", "gpt-"], token, apiKeyProvisional); + return models.Where(model => model.Id.StartsWith("whisper-", StringComparison.InvariantCultureIgnoreCase) || + model.Id.Contains("-transcribe", StringComparison.InvariantCultureIgnoreCase)); + } + #endregion private async Task> LoadModels(string[] prefixes, CancellationToken token, string? apiKeyProvisional = null) diff --git a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs index 9f2d3648..d6945799 100644 --- a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs +++ b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs @@ -106,6 +106,12 @@ public sealed class ProviderOpenRouter() : BaseProvider(LLMProviders.OPEN_ROUTER { return this.LoadEmbeddingModels(token, apiKeyProvisional); } + + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } #endregion diff --git a/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs b/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs index 27101716..0616f2d9 100644 --- a/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs +++ b/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs @@ -107,6 +107,12 @@ public sealed class ProviderPerplexity() : BaseProvider(LLMProviders.PERPLEXITY, return Task.FromResult(Enumerable.Empty()); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } + #endregion private Task> LoadModels() => Task.FromResult>(KNOWN_MODELS); diff --git a/app/MindWork AI Studio/Provider/SelfHosted/Host.cs b/app/MindWork AI Studio/Provider/SelfHosted/Host.cs index d922ccd5..d0dde806 100644 --- a/app/MindWork AI Studio/Provider/SelfHosted/Host.cs +++ b/app/MindWork AI Studio/Provider/SelfHosted/Host.cs @@ -5,7 +5,8 @@ public enum Host NONE, LM_STUDIO, - LLAMACPP, + LLAMA_CPP, + WHISPER_CPP, OLLAMA, VLLM, } \ No newline at end of file diff --git a/app/MindWork AI Studio/Provider/SelfHosted/HostExtensions.cs b/app/MindWork AI Studio/Provider/SelfHosted/HostExtensions.cs index 3478d9e5..6c475273 100644 --- a/app/MindWork AI Studio/Provider/SelfHosted/HostExtensions.cs +++ b/app/MindWork AI Studio/Provider/SelfHosted/HostExtensions.cs @@ -7,7 +7,8 @@ public static class HostExtensions Host.NONE => "None", Host.LM_STUDIO => "LM Studio", - Host.LLAMACPP => "llama.cpp", + Host.LLAMA_CPP => "llama.cpp", + Host.WHISPER_CPP => "whisper.cpp", Host.OLLAMA => "ollama", Host.VLLM => "vLLM", @@ -24,7 +25,28 @@ public static class HostExtensions _ => "chat/completions", }; - public static bool AreEmbeddingsSupported(this Host host) + public static string TranscriptionURL(this Host host) => host switch + { + _ => "audio/transcriptions", + }; + + public static bool IsChatSupported(this Host host) + { + switch (host) + { + case Host.WHISPER_CPP: + return false; + + default: + case Host.OLLAMA: + case Host.VLLM: + case Host.LM_STUDIO: + case Host.LLAMA_CPP: + return true; + } + } + + public static bool IsEmbeddingSupported(this Host host) { switch (host) { @@ -34,7 +56,23 @@ public static class HostExtensions return true; default: - case Host.LLAMACPP: + case Host.LLAMA_CPP: + return false; + } + } + + public static bool IsTranscriptionSupported(this Host host) + { + switch (host) + { + case Host.OLLAMA: + case Host.VLLM: + case Host.WHISPER_CPP: + return true; + + default: + case Host.LM_STUDIO: + case Host.LLAMA_CPP: return false; } } diff --git a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs index 70228589..a61a3b26 100644 --- a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs +++ b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs @@ -6,12 +6,15 @@ using System.Text.Json; using AIStudio.Chat; using AIStudio.Provider.OpenAI; using AIStudio.Settings; +using AIStudio.Tools.PluginSystem; namespace AIStudio.Provider.SelfHosted; public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvider(LLMProviders.SELF_HOSTED, $"{hostname}{host.BaseURL()}", LOGGER) { private static readonly ILogger LOGGER = Program.LOGGER_FACTORY.CreateLogger(); + + private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ProviderSelfHosted).Namespace, nameof(ProviderSelfHosted)); #region Implementation of IProvider @@ -91,7 +94,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide { switch (host) { - case Host.LLAMACPP: + case Host.LLAMA_CPP: // Right now, llama.cpp only supports one model. // There is no API to list the model(s). return [ new Provider.Model("as configured by llama.cpp", null) ]; @@ -138,6 +141,35 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide } } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + try + { + switch (host) + { + case Host.WHISPER_CPP: + return Task.FromResult>( + new List + { + new("loaded-model", TB("Model as configured by whisper.cpp")), + }); + + case Host.OLLAMA: + case Host.VLLM: + return this.LoadModels([], [], token, apiKeyProvisional); + + default: + return Task.FromResult(Enumerable.Empty()); + } + } + catch (Exception e) + { + LOGGER.LogError(e, "Failed to load transcription models from self-hosted provider."); + return Task.FromResult(Enumerable.Empty()); + } + } + #endregion private async Task> LoadModels(string[] ignorePhrases, string[] filterPhrases, CancellationToken token, string? apiKeyProvisional = null) diff --git a/app/MindWork AI Studio/Provider/X/ProviderX.cs b/app/MindWork AI Studio/Provider/X/ProviderX.cs index db3f3a29..92aad1eb 100644 --- a/app/MindWork AI Studio/Provider/X/ProviderX.cs +++ b/app/MindWork AI Studio/Provider/X/ProviderX.cs @@ -101,6 +101,12 @@ public sealed class ProviderX() : BaseProvider(LLMProviders.X, "https://api.x.ai return Task.FromResult>([]); } + /// + public override Task> GetTranscriptionModels(string? apiKeyProvisional = null, CancellationToken token = default) + { + return Task.FromResult(Enumerable.Empty()); + } + #endregion private async Task> LoadModels(string[] prefixes, CancellationToken token, string? apiKeyProvisional = null) diff --git a/app/MindWork AI Studio/Settings/DataModel/Data.cs b/app/MindWork AI Studio/Settings/DataModel/Data.cs index c07ab3d6..622d737e 100644 --- a/app/MindWork AI Studio/Settings/DataModel/Data.cs +++ b/app/MindWork AI Studio/Settings/DataModel/Data.cs @@ -25,6 +25,11 @@ public sealed class Data /// A collection of embedding providers configured. /// public List EmbeddingProviders { get; init; } = []; + + /// + /// A collection of speech providers configured. + /// + public List TranscriptionProviders { get; init; } = []; /// /// A collection of data sources configured. @@ -52,9 +57,14 @@ public sealed class Data public uint NextProviderNum { get; set; } = 1; /// - /// The next embedding number to use. + /// The next embedding provider number to use. /// public uint NextEmbeddingNum { get; set; } = 1; + + /// + /// The next transcription provider number to use. + /// + public uint NextTranscriptionNum { get; set; } = 1; /// /// The next data source number to use. diff --git a/app/MindWork AI Studio/Settings/DataModel/PreviewFeaturesExtensions.cs b/app/MindWork AI Studio/Settings/DataModel/PreviewFeaturesExtensions.cs index 0433119c..00399f0b 100644 --- a/app/MindWork AI Studio/Settings/DataModel/PreviewFeaturesExtensions.cs +++ b/app/MindWork AI Studio/Settings/DataModel/PreviewFeaturesExtensions.cs @@ -14,7 +14,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"), - PreviewFeatures.PRE_SPEECH_TO_TEXT_2026 => TB("Speech to Text: Preview of our speech to text system where you can transcribe recordings and audio files into text"), + PreviewFeatures.PRE_SPEECH_TO_TEXT_2026 => TB("Transcription: Preview of our speech to text system where you can transcribe recordings and audio files into text"), _ => TB("Unknown preview feature") }; diff --git a/app/MindWork AI Studio/Settings/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs index 04bce7b3..3b4ea704 100644 --- a/app/MindWork AI Studio/Settings/SettingsManager.cs +++ b/app/MindWork AI Studio/Settings/SettingsManager.cs @@ -263,7 +263,7 @@ public sealed class SettingsManager if (preselection != Profile.NO_PROFILE) return preselection; - preselection = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id.Equals(this.ConfigurationData.App.PreselectedProfile, StringComparison.InvariantCultureIgnoreCase)); + preselection = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id.Equals(this.ConfigurationData.App.PreselectedProfile, StringComparison.OrdinalIgnoreCase)); return preselection ?? Profile.NO_PROFILE; } @@ -273,7 +273,7 @@ public sealed class SettingsManager if (preselection != ChatTemplate.NO_CHAT_TEMPLATE) return preselection; - preselection = this.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id.Equals(this.ConfigurationData.App.PreselectedChatTemplate, StringComparison.InvariantCultureIgnoreCase)); + preselection = this.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id.Equals(this.ConfigurationData.App.PreselectedChatTemplate, StringComparison.OrdinalIgnoreCase)); return preselection ?? ChatTemplate.NO_CHAT_TEMPLATE; } diff --git a/app/MindWork AI Studio/Settings/TranscriptionProvider.cs b/app/MindWork AI Studio/Settings/TranscriptionProvider.cs new file mode 100644 index 00000000..a7ce8957 --- /dev/null +++ b/app/MindWork AI Studio/Settings/TranscriptionProvider.cs @@ -0,0 +1,32 @@ +using System.Text.Json.Serialization; + +using AIStudio.Provider; + +using Host = AIStudio.Provider.SelfHosted.Host; + +namespace AIStudio.Settings; + +public readonly record struct TranscriptionProvider( + uint Num, + string Id, + string Name, + LLMProviders UsedLLMProvider, + Model Model, + bool IsSelfHosted = false, + string Hostname = "http://localhost:1234", + Host Host = Host.NONE) : ISecretId +{ + public override string ToString() => this.Name; + + #region Implementation of ISecretId + + /// + [JsonIgnore] + public string SecretId => this.Id; + + /// + [JsonIgnore] + public string SecretName => this.Name; + + #endregion +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Validation/ProviderValidation.cs b/app/MindWork AI Studio/Tools/Validation/ProviderValidation.cs index aa6217b0..3b074ba9 100644 --- a/app/MindWork AI Studio/Tools/Validation/ProviderValidation.cs +++ b/app/MindWork AI Studio/Tools/Validation/ProviderValidation.cs @@ -70,7 +70,7 @@ public sealed class ProviderValidation public string? ValidatingModel(Model model) { - if(this.GetProvider() is LLMProviders.SELF_HOSTED && this.GetHost() == Host.LLAMACPP) + if(this.GetProvider() is LLMProviders.SELF_HOSTED && this.GetHost() == Host.LLAMA_CPP) return null; if (model == default) diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.1.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.1.1.md index 4edc4e48..49ec1f85 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.1.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.1.1.md @@ -2,5 +2,6 @@ - Added the option to attach files, including images, to chat templates. You can also define templates with file attachments through a configuration plugin. These file attachments aren’t copied—they’re re-read every time. That means the AI will pick up any updates you make to those files. - Added the option to use source code files in chats and document analysis. This supports software development workflows. - Added a preview feature that lets you record your own voice in preparation for the transcription feature. The feature remains in development and appears only when the preview feature is enabled. +- Added the option to configure transcription providers (for example, using Whisper models). As usual, there can be local as well as cloud models configured. This option is part of the transcription preview and remains hidden until the preview is activated or the feature gets released. - Improved the app versioning. Starting in 2026, each version number includes the year, followed by the month. The last digit shows the release number for that month. For example, version `26.1.1` is the first release in January 2026. - Fixed a bug in the profile selection where the "Use no profile" entry could not be localized, causing English text to appear in languages such as German. This behavior has now been fixed.