mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-18 14:58:00 +00:00
Fixed the tokenizer fingerprint of imported embedding providers (#1077)
This commit is contained in:
1 parent
d333720f3f
commit
f5a257270e
4 files changed
+109
-1
No files matched your search
@@ -92,7 +92,8 @@ public partial class EmbeddingProviderDialog : MSGComponentBase, ISecretId
|
||||
/// <remarks>
|
||||
/// Carried through the dialog untouched as long as the user leaves the tokenizer alone. Rebuilding
|
||||
/// it from the path on every open would read a file for nothing, and an unreadable one would look
|
||||
/// like another tokenizer and cost every data source of this provider its index.
|
||||
/// like another tokenizer and cost every data source of this provider its index. Only a tokenizer
|
||||
/// which arrives without a fingerprint, as with an imported provider, has it read while storing.
|
||||
/// </remarks>
|
||||
[Parameter]
|
||||
public string DataTokenizerFingerprint { get; set; } = string.Empty;
|
||||
@@ -301,6 +302,16 @@ public partial class EmbeddingProviderDialog : MSGComponentBase, ISecretId
|
||||
if (!this.dataIsValid)
|
||||
return;
|
||||
|
||||
//
|
||||
// A tokenizer can arrive without a fingerprint: an imported provider brings only the path,
|
||||
// because importing reads no file before the user agreed. Storing is that agreement, so the
|
||||
// fingerprint is read here, from the file about to be copied, which the copy matches byte for
|
||||
// byte. It has to be known before the question below, which compares the signatures. Read any
|
||||
// later, it would change the signature after the user was asked, and the data sources of this
|
||||
// provider would be indexed again without a word.
|
||||
//
|
||||
this.dataTokenizerFingerprint = await TokenizerFingerprint.KeepOrReadAsync(this.dataFilePath, this.dataTokenizerFingerprint);
|
||||
|
||||
//
|
||||
// Ask before anything is written. Storing a tokenizer deletes the previous one before it
|
||||
// copies, and the API key goes into the OS keyring right after, so asking any later would
|
||||
|
||||
@@ -43,4 +43,28 @@ public static class TokenizerFingerprint
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the fingerprint a provider is stored with: the one already known, or else the one of its tokenizer file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A known fingerprint is kept without reading the file. Reading it again would cost time for
|
||||
/// nothing, and an unreadable file would look like another tokenizer. A tokenizer without a
|
||||
/// fingerprint, such as the one an imported provider brings along, gets one from its file, so
|
||||
/// the embedding signature tells it apart from no tokenizer at all.
|
||||
/// </remarks>
|
||||
/// <param name="tokenizerPath">The tokenizer file about to be stored. May be empty when no tokenizer is set.</param>
|
||||
/// <param name="knownFingerprint">The fingerprint known for that file so far, or an empty string.</param>
|
||||
/// <param name="token">The cancellation token.</param>
|
||||
/// <returns>The fingerprint, or an empty string when no tokenizer is set or its file cannot be read.</returns>
|
||||
public static async Task<string> KeepOrReadAsync(string tokenizerPath, string knownFingerprint, CancellationToken token = default)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tokenizerPath))
|
||||
return string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(knownFingerprint))
|
||||
return knownFingerprint;
|
||||
|
||||
return await ForFileAsync(tokenizerPath, token);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user