mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-09-27 01:53:36 +00:00
Keep a configured embedding model selected when the server does not offer it
This commit is contained in:
parent
c96586f7db
commit
ace20e434a
@ -109,6 +109,12 @@
|
||||
</MudSelect>
|
||||
}
|
||||
</MudStack>
|
||||
@if (this.dataConfiguredModelIsNotOffered)
|
||||
{
|
||||
<MudAlert Severity="Severity.Info" Class="mt-3">
|
||||
@T("This server does not offer the selected model right now. It stays selected, so the documents you already prepared keep working. Choosing another model means every document of the data sources behind this provider is prepared again.")
|
||||
</MudAlert>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(this.dataLoadingModelsIssue))
|
||||
{
|
||||
<MudAlert Severity="Severity.Error" Class="mt-3">
|
||||
|
||||
@ -136,6 +136,7 @@ public partial class EmbeddingProviderDialog : MSGComponentBase, ISecretId
|
||||
private string dataAPIKeyStorageIssue = string.Empty;
|
||||
private string dataEditingPreviousInstanceName = string.Empty;
|
||||
private string dataLoadingModelsIssue = string.Empty;
|
||||
private bool dataConfiguredModelIsNotOffered;
|
||||
private string dataFilePath = string.Empty;
|
||||
private string dataTokenizerFingerprint = string.Empty;
|
||||
private string dataCustomTokenizerValidationIssue = string.Empty;
|
||||
@ -493,6 +494,7 @@ public partial class EmbeddingProviderDialog : MSGComponentBase, ISecretId
|
||||
this.DataModel = default;
|
||||
this.availableModels.Clear();
|
||||
this.dataLoadingModelsIssue = string.Empty;
|
||||
this.dataConfiguredModelIsNotOffered = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -509,6 +511,7 @@ public partial class EmbeddingProviderDialog : MSGComponentBase, ISecretId
|
||||
this.DataModel = default;
|
||||
this.availableModels.Clear();
|
||||
this.dataLoadingModelsIssue = string.Empty;
|
||||
this.dataConfiguredModelIsNotOffered = false;
|
||||
}
|
||||
|
||||
private async Task ReloadModels()
|
||||
@ -536,6 +539,38 @@ public partial class EmbeddingProviderDialog : MSGComponentBase, ISecretId
|
||||
this.Logger.LogError($"Failed to load models from provider '{this.DataLLMProvider}' (host={this.DataHost}, hostname='{this.DataHostname}'): {e.Message}");
|
||||
this.dataLoadingModelsIssue = T("We are currently unable to communicate with the provider to load models. Please try again later.");
|
||||
}
|
||||
|
||||
// Whatever the server answered, and whether it answered at all, the model this provider was
|
||||
// configured with stays on the list:
|
||||
this.PinConfiguredModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Keeps the configured model selectable, also when the server does not offer it right now.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is deliberately the opposite of what the chat provider dialog does, which replaces the
|
||||
/// configured model with the one the server reported. An embedding provider carries indexed data
|
||||
/// sources, and its model ID is part of the embedding signature: changing it -- even only in its
|
||||
/// spelling -- means every prepared document is prepared again. So the stored model is added to
|
||||
/// the list here rather than the list being applied to the stored model. A model nobody serves
|
||||
/// any more stays visible and stays chosen, and changing it stays the user's decision, which
|
||||
/// storing then asks about.
|
||||
///
|
||||
/// Comparing is what Model does, which is by ID and ordinal. Matching a differing spelling would
|
||||
/// mean writing that other spelling into the settings, and that is the very change this avoids.
|
||||
/// </remarks>
|
||||
private void PinConfiguredModel()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(this.DataModel.Id))
|
||||
{
|
||||
this.dataConfiguredModelIsNotOffered = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.dataConfiguredModelIsNotOffered = !this.availableModels.Contains(this.DataModel);
|
||||
if (this.dataConfiguredModelIsNotOffered)
|
||||
this.availableModels.Insert(0, this.DataModel);
|
||||
}
|
||||
|
||||
private string APIKeyText => this.DataLLMProvider switch
|
||||
|
||||
@ -47,6 +47,41 @@ public sealed class EmbeddingChangeImpactTests
|
||||
"Another model means another vector space.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A model ID which differs only in how it is written is a different model here.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is why the embedding provider dialog adds a configured model to the list it loaded
|
||||
/// instead of matching it against that list. A server which writes the same model slightly
|
||||
/// differently -- with a tag where the user typed none, or in another case -- would otherwise
|
||||
/// have its spelling written into the settings on the next save, and every document of every
|
||||
/// data source behind that provider would be prepared again for a change nobody made.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void AModelIdWhichOnlyReadsDifferentlyDropsTheStoredIndexAsWell()
|
||||
{
|
||||
var dataSource = StoredDataSource();
|
||||
var stored = StoredEmbeddingProvider() with { Model = new("nomic-embed-text", null) };
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(
|
||||
EmbeddingChangeImpact.AffectsStoredIndex(dataSource, stored, stored with { Model = new("nomic-embed-text:latest", null) }),
|
||||
Is.True,
|
||||
"The tag a server appends is part of the ID, and the ID is part of the signature.");
|
||||
|
||||
Assert.That(
|
||||
EmbeddingChangeImpact.AffectsStoredIndex(dataSource, stored, stored with { Model = new("NOMIC-EMBED-TEXT", null) }),
|
||||
Is.True,
|
||||
"Compared ordinally, so another case is another model rather than the same one written louder.");
|
||||
|
||||
Assert.That(
|
||||
EmbeddingChangeImpact.AffectsStoredIndex(dataSource, stored, stored with { Model = new("nomic-embed-text", "Nomic Embed Text") }),
|
||||
Is.False,
|
||||
"The display name is decoration and reaches no vector, so loading the list may fill it in.");
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ChangingTheTokenLimitDropsTheStoredIndex()
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user