mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-09-27 03:33:37 +00:00
Keep provider management working when tokenizer storage fails
This commit is contained in:
parent
fe35630eff
commit
8950acb654
@ -3,7 +3,6 @@ using AIStudio.Dialogs;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools.Services;
|
||||
using AIStudio.Tools.Rust;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
@ -144,8 +143,14 @@ public partial class SettingsPanelEmbeddings : SettingsPanelProviderBase
|
||||
return;
|
||||
|
||||
var deleteSecretResponse = await this.RustService.DeleteAPIKey(provider, SecretStoreType.EMBEDDING_PROVIDER);
|
||||
var deleteTokenizerResponse = await this.RustService.DeleteTokenizer(TokenizerModelId.ForEmbeddingProvider(provider));
|
||||
if(deleteSecretResponse.Success && deleteTokenizerResponse.Success)
|
||||
|
||||
//
|
||||
// Removing the tokenizer is best effort: it leaves an unused file behind when it fails,
|
||||
// which is not worth bothering the user about while they are deleting the provider. The
|
||||
// API key is different, though, because a leftover secret is a secret we promised to remove.
|
||||
//
|
||||
_ = await this.RustService.DeleteTokenizer(TokenizerModelId.ForEmbeddingProvider(provider));
|
||||
if(deleteSecretResponse.Success)
|
||||
{
|
||||
this.SettingsManager.ConfigurationData.EmbeddingProviders.Remove(provider);
|
||||
await this.SettingsManager.StoreSettings();
|
||||
@ -154,7 +159,7 @@ public partial class SettingsPanelEmbeddings : SettingsPanelProviderBase
|
||||
{
|
||||
var issueDialogParameters = new DialogParameters<ConfirmDialog>
|
||||
{
|
||||
{ x => x.Message, string.Format(T("Couldn't delete the embedding provider '{0}'. The issue: {1}. We can ignore this issue and delete the embedding provider anyway. Do you want to ignore it and delete this embedding provider?"), provider.Name, BuildDeleteIssue(deleteSecretResponse, deleteTokenizerResponse)) },
|
||||
{ x => x.Message, string.Format(T("Couldn't delete the embedding provider '{0}'. The issue: {1}. We can ignore this issue and delete the embedding provider anyway. Do you want to ignore it and delete this embedding provider?"), provider.Name, deleteSecretResponse.Issue) },
|
||||
};
|
||||
|
||||
var issueDialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Delete Embedding Provider"), issueDialogParameters, DialogOptions.FULLSCREEN);
|
||||
@ -171,18 +176,6 @@ public partial class SettingsPanelEmbeddings : SettingsPanelProviderBase
|
||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||
}
|
||||
|
||||
private static string BuildDeleteIssue(DeleteSecretResponse deleteSecretResponse, TokenizerResponse deleteTokenizerResponse)
|
||||
{
|
||||
var issues = new List<string>();
|
||||
if (!deleteSecretResponse.Success)
|
||||
issues.Add(deleteSecretResponse.Issue);
|
||||
|
||||
if (!deleteTokenizerResponse.Success)
|
||||
issues.Add(deleteTokenizerResponse.Message);
|
||||
|
||||
return string.Join(" | ", issues);
|
||||
}
|
||||
|
||||
private async Task ExportEmbeddingProvider(EmbeddingProvider provider)
|
||||
{
|
||||
if (!this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||
|
||||
@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools.Rust;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@ -134,8 +133,14 @@ public partial class SettingsPanelProviders : SettingsPanelProviderBase
|
||||
return;
|
||||
|
||||
var deleteSecretResponse = await this.RustService.DeleteAPIKey(provider, SecretStoreType.LLM_PROVIDER);
|
||||
var deleteTokenizerResponse = await this.RustService.DeleteTokenizer(TokenizerModelId.ForProvider(provider));
|
||||
if(deleteSecretResponse.Success && deleteTokenizerResponse.Success)
|
||||
|
||||
//
|
||||
// Removing the tokenizer is best effort: it leaves an unused file behind when it fails,
|
||||
// which is not worth bothering the user about while they are deleting the provider. The
|
||||
// API key is different, though, because a leftover secret is a secret we promised to remove.
|
||||
//
|
||||
_ = await this.RustService.DeleteTokenizer(TokenizerModelId.ForProvider(provider));
|
||||
if(deleteSecretResponse.Success)
|
||||
{
|
||||
this.SettingsManager.ConfigurationData.Providers.Remove(provider);
|
||||
await this.SettingsManager.StoreSettings();
|
||||
@ -144,7 +149,7 @@ public partial class SettingsPanelProviders : SettingsPanelProviderBase
|
||||
{
|
||||
var issueDialogParameters = new DialogParameters<ConfirmDialog>
|
||||
{
|
||||
{ x => x.Message, string.Format(T("Couldn't delete the provider '{0}'. The issue: {1}. We can ignore this issue and delete the provider anyway. Do you want to ignore it and delete this provider?"), provider.InstanceName, BuildDeleteIssue(deleteSecretResponse, deleteTokenizerResponse)) },
|
||||
{ x => x.Message, string.Format(T("Couldn't delete the provider '{0}'. The issue: {1}. We can ignore this issue and delete the provider anyway. Do you want to ignore it and delete this provider?"), provider.InstanceName, deleteSecretResponse.Issue) },
|
||||
};
|
||||
|
||||
var issueDialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Delete LLM Provider"), issueDialogParameters, DialogOptions.FULLSCREEN);
|
||||
@ -161,18 +166,6 @@ public partial class SettingsPanelProviders : SettingsPanelProviderBase
|
||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||
}
|
||||
|
||||
private static string BuildDeleteIssue(DeleteSecretResponse deleteSecretResponse, TokenizerResponse deleteTokenizerResponse)
|
||||
{
|
||||
var issues = new List<string>();
|
||||
if (!deleteSecretResponse.Success)
|
||||
issues.Add(deleteSecretResponse.Issue);
|
||||
|
||||
if (!deleteTokenizerResponse.Success)
|
||||
issues.Add(deleteTokenizerResponse.Message);
|
||||
|
||||
return string.Join(" | ", issues);
|
||||
}
|
||||
|
||||
private async Task ExportLLMProvider(AIStudio.Settings.Provider provider)
|
||||
{
|
||||
if (!this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
|
||||
|
||||
@ -327,10 +327,22 @@ public partial class ProviderDialog : MSGComponentBase, ISecretId
|
||||
var tokenizerResponse = await this.StoreOrDeleteTokenizerAsync();
|
||||
if (!tokenizerResponse.Success)
|
||||
{
|
||||
this.dataCustomTokenizerValidationIssue = tokenizerResponse.Message;
|
||||
await this.form.Validate();
|
||||
return;
|
||||
//
|
||||
// Storing a tokenizer the user has chosen must succeed: otherwise the provider would
|
||||
// silently work without the tokenizer the user asked for. Removing a tokenizer the
|
||||
// user has cleared is best effort, though. A failed cleanup leaves an unused file
|
||||
// behind, which is no reason to refuse saving the provider itself.
|
||||
//
|
||||
if (!string.IsNullOrWhiteSpace(this.dataFilePath))
|
||||
{
|
||||
this.dataCustomTokenizerValidationIssue = tokenizerResponse.Message;
|
||||
await this.form.Validate();
|
||||
return;
|
||||
}
|
||||
|
||||
this.Logger.LogWarning($"Failed to remove the tokenizer of provider '{this.DataInstanceName}'. The provider is stored anyway. The message was: {tokenizerResponse.Message}");
|
||||
}
|
||||
|
||||
this.dataFilePath = tokenizerResponse.StoredPath;
|
||||
|
||||
// Use the data model to store the provider.
|
||||
@ -465,10 +477,18 @@ public partial class ProviderDialog : MSGComponentBase, ISecretId
|
||||
private Task<TokenizerResponse> StoreOrDeleteTokenizerAsync()
|
||||
{
|
||||
var tokenizerId = TokenizerModelId.ForProviderId(this.DataId);
|
||||
if (string.IsNullOrWhiteSpace(this.dataFilePath))
|
||||
return this.RustService.DeleteTokenizer(tokenizerId);
|
||||
if (!string.IsNullOrWhiteSpace(this.dataFilePath))
|
||||
return this.RustService.StoreTokenizer(tokenizerId, this.dataFilePath);
|
||||
|
||||
return this.RustService.StoreTokenizer(tokenizerId, this.dataFilePath);
|
||||
//
|
||||
// A provider which never had a tokenizer has nothing to clean up. Calling the runtime
|
||||
// anyway could only fail here, and that failure would block saving a provider which has
|
||||
// nothing to do with tokenizers at all.
|
||||
//
|
||||
if (string.IsNullOrWhiteSpace(this.DataTokenizerPath))
|
||||
return Task.FromResult(new TokenizerResponse(true, 0, string.Empty));
|
||||
|
||||
return this.RustService.DeleteTokenizer(tokenizerId);
|
||||
}
|
||||
|
||||
private void OnProviderChanged(LLMProviders selectedProvider)
|
||||
|
||||
@ -38,7 +38,8 @@ public interface IProvider
|
||||
/// The tokenizer path associated with this provider configuration.
|
||||
/// </summary>
|
||||
public string TokenizerPath { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether this provider instance can load available models from the backend/API.
|
||||
/// This capability may differ by provider type, host, or modality.
|
||||
/// </summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user