Store the model a self-hosted transcription provider was given

This commit is contained in:
Thorsten Sommer 2026-09-19 12:58:16 +02:00
parent d79f3c2100
commit c96586f7db
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108
3 changed files with 21 additions and 81 deletions

View File

@ -87,47 +87,28 @@
{
<MudField FullWidth="true" Label="@T("Model selection")" Variant="Variant.Outlined" Class="mb-3">
<MudStack Row="@true" AlignItems="AlignItems.Center" StretchItems="StretchItems.End">
@if (this.DataLLMProvider.IsTranscriptionModelProvidedManually(this.DataHost))
<MudButton Disabled="@(this.IsEnterpriseConfiguration || !this.DataLLMProvider.CanLoadModels(this.DataHost, this.dataAPIKey))" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.Refresh" OnClick="@this.ReloadModels">
@T("Load")
</MudButton>
@if(this.availableModels.Count is 0)
{
<MudTextField
T="string"
@bind-Text="@this.dataManuallyModel"
Label="@T("Model")"
Class="mb-3"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Dns"
AdornmentColor="Color.Info"
Disabled="@this.IsEnterpriseConfiguration"
Validation="@this.ValidateManuallyModel"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
HelperText="@T("Currently, we cannot query the transcription models for the selected provider and/or host. Therefore, please enter the model name manually.")"
/>
<MudText Typo="Typo.body1">
@T("No models loaded or available.")
</MudText>
}
else
{
<MudButton Disabled="@(this.IsEnterpriseConfiguration || !this.DataLLMProvider.CanLoadModels(this.DataHost, this.dataAPIKey))" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.Refresh" OnClick="@this.ReloadModels">
@T("Load")
</MudButton>
@if(this.availableModels.Count is 0)
{
<MudText Typo="Typo.body1">
@T("No models loaded or available.")
</MudText>
}
else
{
<MudSelect Disabled="@(this.IsEnterpriseConfiguration || this.IsNoneProvider)" @bind-Value="@this.DataModel" Label="@T("Model")"
OpenIcon="@Icons.Material.Filled.FaceRetouchingNatural"
AdornmentColor="Color.Info" Adornment="Adornment.Start"
Validation="@this.providerValidation.ValidatingModel">
@foreach (var model in this.availableModels)
{
<MudSelectItem Value="@model">
@model
</MudSelectItem>
}
</MudSelect>
}
<MudSelect Disabled="@(this.IsEnterpriseConfiguration || this.IsNoneProvider)" @bind-Value="@this.DataModel" Label="@T("Model")"
OpenIcon="@Icons.Material.Filled.FaceRetouchingNatural"
AdornmentColor="Color.Info" Adornment="Adornment.Start"
Validation="@this.providerValidation.ValidatingModel">
@foreach (var model in this.availableModels)
{
<MudSelectItem Value="@model">
@model
</MudSelectItem>
}
</MudSelect>
}
</MudStack>
@if (!string.IsNullOrWhiteSpace(this.dataLoadingModelsIssue))

View File

@ -106,7 +106,6 @@ public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId
private string[] dataIssues = [];
private string dataAPIKey = string.Empty;
private bool dataHadStoredAPIKeyOnLoad;
private string dataManuallyModel = string.Empty;
private string dataAPIKeyStorageIssue = string.Empty;
private string dataEditingPreviousInstanceName = string.Empty;
private string dataLoadingModelsIssue = string.Empty;
@ -127,7 +126,6 @@ public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId
GetPreviousInstanceName = () => this.dataEditingPreviousInstanceName,
GetUsedInstanceNames = () => this.UsedInstanceNames,
GetHost = () => this.DataHost,
IsModelProvidedManually = () => this.DataLLMProvider.IsTranscriptionModelProvidedManually(this.DataHost),
};
}
@ -135,30 +133,9 @@ public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId
{
var cleanedHostname = this.DataHostname.Trim();
// Determine the model based on the provider and host configuration:
Model model;
if (this.DataLLMProvider.IsTranscriptionModelSelectionHidden(this.DataHost))
{
// Use system model placeholder for hosts that don't support model selection (e.g., whisper.cpp):
model = Model.SYSTEM_MODEL;
}
else 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:
default:
model = this.DataModel;
break;
}
}
else
model = this.DataModel;
// whisper.cpp serves whatever it was started with and names no models, so the placeholder
// stands in for the one model there is. Everywhere else the user picked one from the list:
var model = this.DataLLMProvider.IsTranscriptionModelSelectionHidden(this.DataHost) ? Model.SYSTEM_MODEL : this.DataModel;
return new()
{
@ -194,10 +171,6 @@ public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId
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;
// Load the API key. A self-hosted server may well need one: LM Studio can ask for a
// token of its own, and any of these servers can sit behind an authenticating proxy.
@ -302,14 +275,6 @@ public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId
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 OnAPIKeyChanged(string apiKey)
@ -327,7 +292,6 @@ public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId
// When the host changes, reset the model selection state:
this.DataHost = selectedHost;
this.DataModel = default;
this.dataManuallyModel = string.Empty;
this.availableModels.Clear();
this.dataLoadingModelsIssue = string.Empty;
}

View File

@ -421,11 +421,6 @@ public static class LLMProvidersExtensions
_ => false,
};
public static bool IsTranscriptionModelProvidedManually(this LLMProviders provider, Host host) => provider switch
{
_ => false,
};
/// <summary>
/// Determines if the model selection should be completely hidden for LLM providers.
/// This is the case when the host does not support model selection.