mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-24 20:52:11 +00:00
added warning and improved error handling
This commit is contained in:
parent
759c7f9d89
commit
fd2d99872a
@ -2206,6 +2206,36 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONSHORTCUT::T4081853237"] = "C
|
|||||||
-- Configure Keyboard Shortcut
|
-- Configure Keyboard Shortcut
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONSHORTCUT::T636303786"] = "Configure Keyboard Shortcut"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONSHORTCUT::T636303786"] = "Configure Keyboard Shortcut"
|
||||||
|
|
||||||
|
-- Yes, please send my data to the external embedding provider
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T1159107763"] = "Yes, please send my data to the external embedding provider"
|
||||||
|
|
||||||
|
-- No, I will choose another embedding
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T1246976418"] = "No, I will choose another embedding"
|
||||||
|
|
||||||
|
-- The data source '{0}'
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T2503488371"] = "The data source '{0}'"
|
||||||
|
|
||||||
|
-- The file '{0}'
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T2794508936"] = "The file '{0}'"
|
||||||
|
|
||||||
|
-- Warning: The selected embedding provider is not self-hosted. Creating embeddings can cost money and may need to run multiple times, for example after errors or file changes. {0} will be sent to an external third party. MindWork AI Studio has no control over what that third party does with the data after it is sent.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T3457494593"] = "Warning: The selected embedding provider is not self-hosted. Creating embeddings can cost money and may need to run multiple times, for example after errors or file changes. {0} will be sent to an external third party. MindWork AI Studio has no control over what that third party does with the data after it is sent."
|
||||||
|
|
||||||
|
-- I confirm that I have read and understood the above
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T3683380716"] = "I confirm that I have read and understood the above"
|
||||||
|
|
||||||
|
-- The selected data
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T3793916111"] = "The selected data"
|
||||||
|
|
||||||
|
-- The selected file
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T3999057817"] = "The selected file"
|
||||||
|
|
||||||
|
-- All files in the folder '{0}' and its subfolders
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T661754597"] = "All files in the folder '{0}' and its subfolders"
|
||||||
|
|
||||||
|
-- All files in this folder and its subfolders
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCECLOUDEMBEDDINGWARNING::T916879200"] = "All files in this folder and its subfolders"
|
||||||
|
|
||||||
-- Yes, let the AI decide which data sources are needed.
|
-- Yes, let the AI decide which data sources are needed.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCESELECTION::T1031370894"] = "Yes, let the AI decide which data sources are needed."
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCESELECTION::T1031370894"] = "Yes, let the AI decide which data sources are needed."
|
||||||
|
|
||||||
@ -3805,15 +3835,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T1827669611"
|
|||||||
-- Update
|
-- Update
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T1847791252"] = "Update"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T1847791252"] = "Update"
|
||||||
|
|
||||||
-- Please note: the embedding you selected runs in the cloud. All your data will be sent to the cloud. Please confirm that you have read and understood this.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T1922618794"] = "Please note: the embedding you selected runs in the cloud. All your data will be sent to the cloud. Please confirm that you have read and understood this."
|
|
||||||
|
|
||||||
-- In order for the AI to be able to determine the appropriate data at any time, you must choose an embedding method.
|
-- In order for the AI to be able to determine the appropriate data at any time, you must choose an embedding method.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T1948697886"] = "In order for the AI to be able to determine the appropriate data at any time, you must choose an embedding method."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T1948697886"] = "In order for the AI to be able to determine the appropriate data at any time, you must choose an embedding method."
|
||||||
|
|
||||||
-- Please note: the embedding you selected runs in the cloud. All your data from the folder '{0}' and all its subdirectories will be sent to the cloud. Please confirm that you have read and understood this.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2403121734"] = "Please note: the embedding you selected runs in the cloud. All your data from the folder '{0}' and all its subdirectories will be sent to the cloud. Please confirm that you have read and understood this."
|
|
||||||
|
|
||||||
-- Add
|
-- Add
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2646845972"] = "Add"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2646845972"] = "Add"
|
||||||
|
|
||||||
@ -3826,18 +3850,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2838542994"
|
|||||||
-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc.
|
-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3359366900"] = "For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3359366900"] = "For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc."
|
||||||
|
|
||||||
-- Yes, please send my data to the cloud
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3572613009"] = "Yes, please send my data to the cloud"
|
|
||||||
|
|
||||||
-- I confirm that I have read and understood the above
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3683380716"] = "I confirm that I have read and understood the above"
|
|
||||||
|
|
||||||
-- Your security policy
|
-- Your security policy
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T4081226330"] = "Your security policy"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T4081226330"] = "Your security policy"
|
||||||
|
|
||||||
-- No, I will chose another embedding
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T4253147533"] = "No, I will chose another embedding"
|
|
||||||
|
|
||||||
-- Select the base directory
|
-- Select the base directory
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T562479068"] = "Select the base directory"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T562479068"] = "Select the base directory"
|
||||||
|
|
||||||
@ -3931,15 +3946,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T1827669611"] = "
|
|||||||
-- Update
|
-- Update
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T1847791252"] = "Update"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T1847791252"] = "Update"
|
||||||
|
|
||||||
-- Please note: the embedding you selected runs in the cloud. All your data will be sent to the cloud. Please confirm that you have read and understood this.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T1922618794"] = "Please note: the embedding you selected runs in the cloud. All your data will be sent to the cloud. Please confirm that you have read and understood this."
|
|
||||||
|
|
||||||
-- In order for the AI to be able to determine the appropriate data at any time, you must choose an embedding method.
|
-- In order for the AI to be able to determine the appropriate data at any time, you must choose an embedding method.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T1948697886"] = "In order for the AI to be able to determine the appropriate data at any time, you must choose an embedding method."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T1948697886"] = "In order for the AI to be able to determine the appropriate data at any time, you must choose an embedding method."
|
||||||
|
|
||||||
-- Please note: the embedding you selected runs in the cloud. All your data within the file '{0}' will be sent to the cloud. Please confirm that you have read and understood this.
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2090178026"] = "Please note: the embedding you selected runs in the cloud. All your data within the file '{0}' will be sent to the cloud. Please confirm that you have read and understood this."
|
|
||||||
|
|
||||||
-- Add
|
-- Add
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2646845972"] = "Add"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2646845972"] = "Add"
|
||||||
|
|
||||||
@ -3955,21 +3964,12 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2859265837"] = "
|
|||||||
-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc.
|
-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3359366900"] = "For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc."
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3359366900"] = "For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc."
|
||||||
|
|
||||||
-- Yes, please send my data to the cloud
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3572613009"] = "Yes, please send my data to the cloud"
|
|
||||||
|
|
||||||
-- I confirm that I have read and understood the above
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3683380716"] = "I confirm that I have read and understood the above"
|
|
||||||
|
|
||||||
-- Select the file
|
-- Select the file
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3740148848"] = "Select the file"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3740148848"] = "Select the file"
|
||||||
|
|
||||||
-- Your security policy
|
-- Your security policy
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T4081226330"] = "Your security policy"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T4081226330"] = "Your security policy"
|
||||||
|
|
||||||
-- No, I will chose another embedding
|
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T4253147533"] = "No, I will chose another embedding"
|
|
||||||
|
|
||||||
-- Data Source Name
|
-- Data Source Name
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T813773421"] = "Data Source Name"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T813773421"] = "Data Source Name"
|
||||||
|
|
||||||
@ -4168,6 +4168,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2331453405"] = "(O
|
|||||||
-- Invalid tokenizer:
|
-- Invalid tokenizer:
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2448302543"] = "Invalid tokenizer:"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2448302543"] = "Invalid tokenizer:"
|
||||||
|
|
||||||
|
-- Maximum number of tokens sent to the embedding model per chunk.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2544519277"] = "Maximum number of tokens sent to the embedding model per chunk."
|
||||||
|
|
||||||
-- Add
|
-- Add
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2646845972"] = "Add"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2646845972"] = "Add"
|
||||||
|
|
||||||
@ -4183,6 +4186,12 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2842060373"] = "In
|
|||||||
-- Currently, we cannot query the embedding models for the selected provider and/or host. Therefore, please enter the model name manually.
|
-- 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."
|
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."
|
||||||
|
|
||||||
|
-- Token limit
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T2961294165"] = "Token limit"
|
||||||
|
|
||||||
|
-- Please enter a token limit greater than 0.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T3316544737"] = "Please enter a token limit greater than 0."
|
||||||
|
|
||||||
-- Choose a custom tokenizer here
|
-- Choose a custom tokenizer here
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T3787466119"] = "Choose a custom tokenizer here"
|
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T3787466119"] = "Choose a custom tokenizer here"
|
||||||
|
|
||||||
@ -6160,6 +6169,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T2525374657"] = "{0} of {1} files
|
|||||||
-- Background embeddings
|
-- Background embeddings
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T2547971789"] = "Background embeddings"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T2547971789"] = "Background embeddings"
|
||||||
|
|
||||||
|
-- Refresh this data source
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T2901874229"] = "Refresh this data source"
|
||||||
|
|
||||||
-- Failed files: {0}
|
-- Failed files: {0}
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T309404893"] = "Failed files: {0}"
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T309404893"] = "Failed files: {0}"
|
||||||
|
|
||||||
@ -6169,6 +6181,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T3473125711"] = "Indexed files: {0
|
|||||||
-- No local data source has been queued for embedding yet.
|
-- No local data source has been queued for embedding yet.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T3774205531"] = "No local data source has been queued for embedding yet."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T3774205531"] = "No local data source has been queued for embedding yet."
|
||||||
|
|
||||||
|
-- Failure details ({0})
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::EMBEDDINGS::T843144866"] = "Failure details ({0})"
|
||||||
|
|
||||||
-- Unlike services like ChatGPT, which impose limits after intensive use, MindWork AI Studio offers unlimited usage through the providers API.
|
-- Unlike services like ChatGPT, which impose limits after intensive use, MindWork AI Studio offers unlimited usage through the providers API.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1009708591"] = "Unlike services like ChatGPT, which impose limits after intensive use, MindWork AI Studio offers unlimited usage through the providers API."
|
UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T1009708591"] = "Unlike services like ChatGPT, which impose limits after intensive use, MindWork AI Studio offers unlimited usage through the providers API."
|
||||||
|
|
||||||
|
|||||||
@ -81,7 +81,6 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
private Guid loadedParameterWorkspaceId = Guid.Empty;
|
private Guid loadedParameterWorkspaceId = Guid.Empty;
|
||||||
private Guid foregroundChatId = Guid.Empty;
|
private Guid foregroundChatId = Guid.Empty;
|
||||||
private int workspaceHeaderSyncVersion;
|
private int workspaceHeaderSyncVersion;
|
||||||
private CancellationTokenSource? cancellationTokenSource;
|
|
||||||
private HashSet<FileAttachment> chatDocumentPaths = [];
|
private HashSet<FileAttachment> chatDocumentPaths = [];
|
||||||
private string tokenCount = "0";
|
private string tokenCount = "0";
|
||||||
private string TokenCountMessage => $"{this.T("Estimated amount of tokens:")} {this.tokenCount}";
|
private string TokenCountMessage => $"{this.T("Estimated amount of tokens:")} {this.tokenCount}";
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
@inherits MSGComponentBase
|
||||||
|
|
||||||
|
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined" Dense="@true" Class="mb-3">
|
||||||
|
<MudText Typo="Typo.body2">
|
||||||
|
@this.WarningText
|
||||||
|
</MudText>
|
||||||
|
</MudAlert>
|
||||||
|
|
||||||
|
<MudTextSwitch Value="@this.UserAcknowledged" ValueChanged="@this.UserAcknowledgedChanged" Label="@T("I confirm that I have read and understood the above")" LabelOn="@T("Yes, please send my data to the external embedding provider")" LabelOff="@T("No, I will choose another embedding")" Validation="@this.Validation"/>
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
using AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Components;
|
||||||
|
|
||||||
|
public partial class DataSourceCloudEmbeddingWarning : MSGComponentBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public DataSourceType DataSourceType { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string SourcePath { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool UserAcknowledged { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<bool> UserAcknowledgedChanged { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public Func<bool, string?> Validation { get; set; } = _ => null;
|
||||||
|
|
||||||
|
private string WarningText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var subject = this.GetSubjectText();
|
||||||
|
return string.Format(
|
||||||
|
T("Warning: The selected embedding provider is not self-hosted. Creating embeddings can cost money and may need to run multiple times, for example after errors or file changes. {0} will be sent to an external third party. MindWork AI Studio has no control over what that third party does with the data after it is sent."),
|
||||||
|
subject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetSubjectText()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(this.SourcePath))
|
||||||
|
return this.DataSourceType switch
|
||||||
|
{
|
||||||
|
DataSourceType.LOCAL_DIRECTORY => T("All files in this folder and its subfolders"),
|
||||||
|
DataSourceType.LOCAL_FILE => T("The selected file"),
|
||||||
|
_ => T("The selected data")
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.DataSourceType switch
|
||||||
|
{
|
||||||
|
DataSourceType.LOCAL_DIRECTORY => string.Format(T("All files in the folder '{0}' and its subfolders"), this.SourcePath),
|
||||||
|
DataSourceType.LOCAL_FILE => string.Format(T("The file '{0}'"), this.SourcePath),
|
||||||
|
_ => string.Format(T("The data source '{0}'"), this.SourcePath)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -59,17 +59,7 @@
|
|||||||
{
|
{
|
||||||
if (this.SelectedCloudEmbedding)
|
if (this.SelectedCloudEmbedding)
|
||||||
{
|
{
|
||||||
<MudJustifiedText Typo="Typo.body1" Color="Color.Error" Class="mb-3">
|
<DataSourceCloudEmbeddingWarning DataSourceType="DataSourceType.LOCAL_DIRECTORY" SourcePath="@this.dataPath" @bind-UserAcknowledged="@this.dataUserAcknowledgedCloudEmbedding" Validation="@this.dataSourceValidation.ValidateUserAcknowledgedCloudEmbedding"/>
|
||||||
@if (string.IsNullOrWhiteSpace(this.dataPath))
|
|
||||||
{
|
|
||||||
@T("Please note: the embedding you selected runs in the cloud. All your data will be sent to the cloud. Please confirm that you have read and understood this.")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@string.Format(T("Please note: the embedding you selected runs in the cloud. All your data from the folder '{0}' and all its subdirectories will be sent to the cloud. Please confirm that you have read and understood this."), this.dataPath)
|
|
||||||
}
|
|
||||||
</MudJustifiedText>
|
|
||||||
<MudTextSwitch @bind-Value="@this.dataUserAcknowledgedCloudEmbedding" Label="@T("I confirm that I have read and understood the above")" LabelOn="@T("Yes, please send my data to the cloud")" LabelOff="@T("No, I will chose another embedding")" Validation="@this.dataSourceValidation.ValidateUserAcknowledgedCloudEmbedding"/>
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -96,7 +96,8 @@ public partial class DataSourceLocalDirectoryDialog : MSGComponentBase
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private bool SelectedCloudEmbedding => !(this.SettingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(x => x.Id == this.dataEmbeddingId)?.IsTrustedForDataSourceSecurityChecks(this.SettingsManager) ?? false);
|
private bool SelectedCloudEmbedding => this.SettingsManager.ConfigurationData.EmbeddingProviders
|
||||||
|
.FirstOrDefault(x => x.Id == this.dataEmbeddingId) is { IsSelfHosted: false };
|
||||||
|
|
||||||
private DataSourceLocalDirectory CreateDataSource() => new()
|
private DataSourceLocalDirectory CreateDataSource() => new()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -59,17 +59,7 @@
|
|||||||
{
|
{
|
||||||
if (this.SelectedCloudEmbedding)
|
if (this.SelectedCloudEmbedding)
|
||||||
{
|
{
|
||||||
<MudJustifiedText Typo="Typo.body1" Color="Color.Error" Class="mb-3">
|
<DataSourceCloudEmbeddingWarning DataSourceType="DataSourceType.LOCAL_FILE" SourcePath="@this.dataFilePath" @bind-UserAcknowledged="@this.dataUserAcknowledgedCloudEmbedding" Validation="@this.dataSourceValidation.ValidateUserAcknowledgedCloudEmbedding"/>
|
||||||
@if (string.IsNullOrWhiteSpace(this.dataFilePath))
|
|
||||||
{
|
|
||||||
@T("Please note: the embedding you selected runs in the cloud. All your data will be sent to the cloud. Please confirm that you have read and understood this.")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@string.Format(T("Please note: the embedding you selected runs in the cloud. All your data within the file '{0}' will be sent to the cloud. Please confirm that you have read and understood this."), this.dataFilePath)
|
|
||||||
}
|
|
||||||
</MudJustifiedText>
|
|
||||||
<MudTextSwitch @bind-Value="@this.dataUserAcknowledgedCloudEmbedding" Label="@T("I confirm that I have read and understood the above")" LabelOn="@T("Yes, please send my data to the cloud")" LabelOff="@T("No, I will chose another embedding")" Validation="@this.dataSourceValidation.ValidateUserAcknowledgedCloudEmbedding"/>
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -96,7 +96,8 @@ public partial class DataSourceLocalFileDialog : MSGComponentBase
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private bool SelectedCloudEmbedding => !(this.SettingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(x => x.Id == this.dataEmbeddingId)?.IsTrustedForDataSourceSecurityChecks(this.SettingsManager) ?? false);
|
private bool SelectedCloudEmbedding => this.SettingsManager.ConfigurationData.EmbeddingProviders
|
||||||
|
.FirstOrDefault(x => x.Id == this.dataEmbeddingId) is { IsSelfHosted: false };
|
||||||
|
|
||||||
private DataSourceLocalFile CreateDataSource() => new()
|
private DataSourceLocalFile CreateDataSource() => new()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -31,7 +31,7 @@ public partial class SettingsDialogDataSources : SettingsDialogBase
|
|||||||
|
|
||||||
private bool CanRefreshDataSource(IDataSource dataSource)
|
private bool CanRefreshDataSource(IDataSource dataSource)
|
||||||
{
|
{
|
||||||
return dataSource is DataSourceLocalDirectory or DataSourceLocalFile;
|
return this.DataSourceEmbeddingService.CanRefreshDataSource(dataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool HasRefreshableDataSources()
|
private bool HasRefreshableDataSources()
|
||||||
|
|||||||
@ -28,7 +28,15 @@
|
|||||||
<MudStack Spacing="2">
|
<MudStack Spacing="2">
|
||||||
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
|
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
|
||||||
<MudText Typo="Typo.h6">@status.DataSourceName</MudText>
|
<MudText Typo="Typo.h6">@status.DataSourceName</MudText>
|
||||||
<MudChip T="string" Color="@GetStatusColor(status)" Variant="Variant.Filled">@status.StateLabel</MudChip>
|
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center">
|
||||||
|
<MudChip T="string" Color="@GetStatusColor(status)" Variant="Variant.Filled">@status.StateLabel</MudChip>
|
||||||
|
@if (CanRefresh(status))
|
||||||
|
{
|
||||||
|
<MudTooltip Text="@T("Refresh this data source")">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Sync" Color="Color.Info" Size="Size.Small" OnClick="@(async () => await this.RefreshDataSource(status))" />
|
||||||
|
</MudTooltip>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
||||||
<MudProgressLinear Value="@status.ProgressPercent" Rounded="@true" Color="@GetStatusColor(status)" />
|
<MudProgressLinear Value="@status.ProgressPercent" Rounded="@true" Color="@GetStatusColor(status)" />
|
||||||
@ -51,7 +59,28 @@
|
|||||||
</MudText>
|
</MudText>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(status.LastError))
|
@if (status.Failures.Count > 0)
|
||||||
|
{
|
||||||
|
<MudExpansionPanels MultiExpansion="@false" Class="mt-2">
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.ReportProblem" HeaderText="@string.Format(T("Failure details ({0})"), status.Failures.Count)" MaxHeight="360">
|
||||||
|
<MudStack Spacing="2">
|
||||||
|
@foreach (var failure in status.Failures)
|
||||||
|
{
|
||||||
|
<MudStack Spacing="1" Class="py-1">
|
||||||
|
<MudText Typo="Typo.body2" Style="word-break: break-word;">
|
||||||
|
@failure.FilePath
|
||||||
|
</MudText>
|
||||||
|
<MudText Typo="Typo.caption" Color="Color.Warning" Style="word-break: break-word;">
|
||||||
|
@failure.Reason
|
||||||
|
</MudText>
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</ExpansionPanel>
|
||||||
|
</MudExpansionPanels>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (!string.IsNullOrWhiteSpace(status.LastError) && status.Failures.Count == 0)
|
||||||
{
|
{
|
||||||
<MudAlert Severity="Severity.Warning" Variant="Variant.Text">
|
<MudAlert Severity="Severity.Warning" Variant="Variant.Text">
|
||||||
@status.LastError
|
@status.LastError
|
||||||
|
|||||||
@ -54,4 +54,18 @@ public partial class Embeddings : MSGComponentBase
|
|||||||
DataSourceEmbeddingState.COMPLETED => Color.Success,
|
DataSourceEmbeddingState.COMPLETED => Color.Success,
|
||||||
_ => Color.Default,
|
_ => Color.Default,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private bool CanRefresh(DataSourceEmbeddingStatus status)
|
||||||
|
{
|
||||||
|
return this.DataSourceEmbeddingService.CanRefreshDataSource(status.DataSourceId) &&
|
||||||
|
status.State is not DataSourceEmbeddingState.RUNNING and not DataSourceEmbeddingState.QUEUED &&
|
||||||
|
(status.State is DataSourceEmbeddingState.FAILED || status.FailedFiles > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RefreshDataSource(DataSourceEmbeddingStatus status)
|
||||||
|
{
|
||||||
|
await this.DataSourceEmbeddingService.QueueDataSourceAsync(status.DataSourceId);
|
||||||
|
this.ReloadStatuses();
|
||||||
|
await this.InvokeAsync(this.StateHasChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,8 @@ public sealed record DataSourceEmbeddingStatus(
|
|||||||
int IndexedFiles,
|
int IndexedFiles,
|
||||||
int FailedFiles,
|
int FailedFiles,
|
||||||
string CurrentFile,
|
string CurrentFile,
|
||||||
string LastError)
|
string LastError,
|
||||||
|
IReadOnlyList<DataSourceEmbeddingFailure> Failures)
|
||||||
{
|
{
|
||||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(DataSourceEmbeddingService).Namespace, nameof(DataSourceEmbeddingService));
|
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(DataSourceEmbeddingService).Namespace, nameof(DataSourceEmbeddingService));
|
||||||
|
|
||||||
@ -53,13 +54,26 @@ public sealed record DataSourceEmbeddingStatus(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed record DataSourceEmbeddingFailure(
|
||||||
|
string FilePath,
|
||||||
|
string Reason);
|
||||||
|
|
||||||
public sealed class FileEnumerationResult
|
public sealed class FileEnumerationResult
|
||||||
{
|
{
|
||||||
public List<FileInfo> Files { get; } = [];
|
public List<FileInfo> Files { get; } = [];
|
||||||
|
|
||||||
|
public List<DataSourceEmbeddingFailure> Failures { get; } = [];
|
||||||
|
|
||||||
public int FailedFiles { get; set; }
|
public int FailedFiles { get; set; }
|
||||||
|
|
||||||
public string LastError { get; set; } = string.Empty;
|
public string LastError { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public void AddFailure(string filePath, string reason)
|
||||||
|
{
|
||||||
|
this.Failures.Add(new DataSourceEmbeddingFailure(filePath, reason));
|
||||||
|
this.FailedFiles = this.Failures.Count;
|
||||||
|
this.LastError = reason;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class DataSourceEmbeddingManifest
|
public sealed class DataSourceEmbeddingManifest
|
||||||
|
|||||||
@ -50,8 +50,8 @@ public sealed partial class DataSourceEmbeddingService
|
|||||||
var chunk = currentChunk.ToString().Trim();
|
var chunk = currentChunk.ToString().Trim();
|
||||||
if (!string.IsNullOrWhiteSpace(chunk))
|
if (!string.IsNullOrWhiteSpace(chunk))
|
||||||
{
|
{
|
||||||
await foreach (var finalChunk in this.SplitChunkByEmbeddingTokenLimitAsync(chunk, embeddingProvider, token))
|
await foreach (var splitChunk in this.SplitChunkByEmbeddingTokenLimitAsync(chunk, embeddingProvider, token))
|
||||||
yield return finalChunk;
|
yield return splitChunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
var overlap = chunk.Length > CHUNK_OVERLAP_LENGTH
|
var overlap = chunk.Length > CHUNK_OVERLAP_LENGTH
|
||||||
@ -239,8 +239,7 @@ public sealed partial class DataSourceEmbeddingService
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
result.FailedFiles = 1;
|
result.AddFailure(localFile.FilePath, $"The selected file '{localFile.FilePath}' is not supported for background embeddings.");
|
||||||
result.LastError = $"The selected file '{localFile.FilePath}' is not supported for background embeddings.";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,13 +253,11 @@ public sealed partial class DataSourceEmbeddingService
|
|||||||
switch (dataSource)
|
switch (dataSource)
|
||||||
{
|
{
|
||||||
case DataSourceLocalFile localFile:
|
case DataSourceLocalFile localFile:
|
||||||
result.FailedFiles = 1;
|
result.AddFailure(localFile.FilePath, $"The selected file '{localFile.FilePath}' does not exist.");
|
||||||
result.LastError = $"The selected file '{localFile.FilePath}' does not exist.";
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DataSourceLocalDirectory localDirectory:
|
case DataSourceLocalDirectory localDirectory:
|
||||||
result.FailedFiles = 1;
|
result.AddFailure(localDirectory.Path, $"The selected directory '{localDirectory.Path}' does not exist.");
|
||||||
result.LastError = $"The selected directory '{localDirectory.Path}' does not exist.";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,8 +283,7 @@ public sealed partial class DataSourceEmbeddingService
|
|||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
logger.LogWarning(exception, "Cannot access directory '{DirectoryPath}' while indexing.", currentPath);
|
logger.LogWarning(exception, "Cannot access directory '{DirectoryPath}' while indexing.", currentPath);
|
||||||
result.FailedFiles++;
|
result.AddFailure(currentPath, $"The directory '{currentPath}' could not be accessed.");
|
||||||
result.LastError = $"The directory '{currentPath}' could not be accessed.";
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,8 +299,7 @@ public sealed partial class DataSourceEmbeddingService
|
|||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
logger.LogWarning(exception, "Cannot inspect file '{FilePath}' while indexing.", filePath);
|
logger.LogWarning(exception, "Cannot inspect file '{FilePath}' while indexing.", filePath);
|
||||||
result.FailedFiles++;
|
result.AddFailure(filePath, $"The file '{filePath}' could not be inspected.");
|
||||||
result.LastError = $"The file '{filePath}' could not be inspected.";
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -103,11 +103,29 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
this.RefreshWatchers();
|
this.RefreshWatchers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanRefreshDataSource(IDataSource dataSource)
|
||||||
|
{
|
||||||
|
return this.IsSupportedInternalDataSource(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanRefreshDataSource(string dataSourceId)
|
||||||
|
{
|
||||||
|
return this.TryGetConfiguredDataSource(dataSourceId, out var dataSource) &&
|
||||||
|
this.CanRefreshDataSource(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
public Task QueueDataSourceAsync(IDataSource dataSource)
|
public Task QueueDataSourceAsync(IDataSource dataSource)
|
||||||
{
|
{
|
||||||
return this.QueueDataSourceAsync(dataSource, true);
|
return this.QueueDataSourceAsync(dataSource, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task QueueDataSourceAsync(string dataSourceId)
|
||||||
|
{
|
||||||
|
return this.TryGetConfiguredDataSource(dataSourceId, out var dataSource)
|
||||||
|
? this.QueueDataSourceAsync(dataSource)
|
||||||
|
: Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task QueueDataSourceAsync(IDataSource dataSource, bool queueAfterCurrentRun)
|
private async Task QueueDataSourceAsync(IDataSource dataSource, bool queueAfterCurrentRun)
|
||||||
{
|
{
|
||||||
if (!this.IsSupportedInternalDataSource(dataSource))
|
if (!this.IsSupportedInternalDataSource(dataSource))
|
||||||
@ -134,7 +152,15 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
|
|
||||||
logger.LogInformation("Queueing data source '{DataSourceName}' ({DataSourceId}) for background embeddings.", dataSource.Name, dataSource.Id);
|
logger.LogInformation("Queueing data source '{DataSourceName}' ({DataSourceId}) for background embeddings.", dataSource.Name, dataSource.Id);
|
||||||
if (!this.statuses.TryGetValue(dataSource.Id, out var currentStatus) || currentStatus.State is not DataSourceEmbeddingState.RUNNING)
|
if (!this.statuses.TryGetValue(dataSource.Id, out var currentStatus) || currentStatus.State is not DataSourceEmbeddingState.RUNNING)
|
||||||
this.UpsertStatus(this.CreateStatus(dataSource, DataSourceEmbeddingState.QUEUED, currentStatus?.TotalFiles ?? 0, currentStatus?.IndexedFiles ?? 0, currentStatus?.FailedFiles ?? 0));
|
{
|
||||||
|
this.UpsertStatus(this.CreateStatus(
|
||||||
|
dataSource,
|
||||||
|
DataSourceEmbeddingState.QUEUED,
|
||||||
|
currentStatus?.TotalFiles ?? 0,
|
||||||
|
currentStatus?.IndexedFiles ?? 0,
|
||||||
|
currentStatus?.FailedFiles ?? 0,
|
||||||
|
failures: currentStatus?.Failures ?? []));
|
||||||
|
}
|
||||||
logger.LogDebug("Upserting status for data source '{DataSourceName}' ({DataSourceId}).", dataSource.Name, dataSource.Id);
|
logger.LogDebug("Upserting status for data source '{DataSourceName}' ({DataSourceId}).", dataSource.Name, dataSource.Id);
|
||||||
await this.queue.Writer.WriteAsync(dataSource.Id);
|
await this.queue.Writer.WriteAsync(dataSource.Id);
|
||||||
logger.LogDebug("Queued data source '{DataSourceName}' ({DataSourceId}).", dataSource.Name, dataSource.Id);
|
logger.LogDebug("Queued data source '{DataSourceName}' ({DataSourceId}).", dataSource.Name, dataSource.Id);
|
||||||
@ -266,13 +292,15 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
totalFiles,
|
totalFiles,
|
||||||
0,
|
0,
|
||||||
inputFiles.FailedFiles,
|
inputFiles.FailedFiles,
|
||||||
lastError: inputFiles.LastError));
|
lastError: inputFiles.LastError,
|
||||||
|
failures: inputFiles.Failures));
|
||||||
|
|
||||||
var provider = embeddingProvider.CreateProvider();
|
var provider = embeddingProvider.CreateProvider();
|
||||||
var skippedFiles = 0;
|
var skippedFiles = 0;
|
||||||
var completedFiles = 0;
|
var completedFiles = 0;
|
||||||
var failedFiles = inputFiles.FailedFiles;
|
var failedFiles = inputFiles.FailedFiles;
|
||||||
var lastError = inputFiles.LastError;
|
var lastError = inputFiles.LastError;
|
||||||
|
var failureDetails = inputFiles.Failures.ToList();
|
||||||
|
|
||||||
foreach (var file in indexedFiles)
|
foreach (var file in indexedFiles)
|
||||||
{
|
{
|
||||||
@ -288,11 +316,11 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
dataSource.Name,
|
dataSource.Name,
|
||||||
dataSource.Id);
|
dataSource.Id);
|
||||||
skippedFiles++;
|
skippedFiles++;
|
||||||
this.UpsertStatus(this.CreateStatus(dataSource, DataSourceEmbeddingState.RUNNING, totalFiles, skippedFiles + completedFiles, failedFiles, lastError: lastError));
|
this.UpsertStatus(this.CreateStatus(dataSource, DataSourceEmbeddingState.RUNNING, totalFiles, skippedFiles + completedFiles, failedFiles, lastError: lastError, failures: failureDetails));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.UpsertStatus(this.CreateStatus(dataSource, DataSourceEmbeddingState.RUNNING, totalFiles, skippedFiles + completedFiles, failedFiles, file.Name, lastError));
|
this.UpsertStatus(this.CreateStatus(dataSource, DataSourceEmbeddingState.RUNNING, totalFiles, skippedFiles + completedFiles, failedFiles, file.Name, lastError, failureDetails));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -338,16 +366,17 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
{
|
{
|
||||||
failedFiles++;
|
failedFiles++;
|
||||||
lastError = exception.Message;
|
lastError = exception.Message;
|
||||||
|
failureDetails.Add(new DataSourceEmbeddingFailure(file.FullName, exception.Message));
|
||||||
manifest.Files.Remove(file.FullName);
|
manifest.Files.Remove(file.FullName);
|
||||||
await this.DeleteFilePointsAsync(vectorStore, collectionName, file.FullName, token);
|
await this.DeleteFilePointsAsync(vectorStore, collectionName, file.FullName, token);
|
||||||
await embeddingState.DeleteFileAsync(dataSource.Id, file.FullName, token);
|
await embeddingState.DeleteFileAsync(dataSource.Id, file.FullName, token);
|
||||||
|
|
||||||
logger.LogWarning(exception, "Failed to embed file '{FilePath}' for data source '{DataSourceName}'.", file.FullName, dataSource.Name);
|
logger.LogWarning(exception, "Failed to embed file '{FilePath}' for data source '{DataSourceName}'.", file.FullName, dataSource.Name);
|
||||||
this.UpsertStatus(this.CreateStatus(dataSource, DataSourceEmbeddingState.RUNNING, totalFiles, skippedFiles + completedFiles, failedFiles, file.Name, exception.Message));
|
this.UpsertStatus(this.CreateStatus(dataSource, DataSourceEmbeddingState.RUNNING, totalFiles, skippedFiles + completedFiles, failedFiles, file.Name, exception.Message, failureDetails));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.UpsertStatus(this.CreateCompletedStatus(dataSource, totalFiles, skippedFiles + completedFiles, failedFiles, lastError));
|
this.UpsertStatus(this.CreateCompletedStatus(dataSource, totalFiles, skippedFiles + completedFiles, failedFiles, lastError, failureDetails));
|
||||||
logger.LogInformation(
|
logger.LogInformation(
|
||||||
"Finished background embeddings for data source '{DataSourceName}' ({DataSourceId}). Indexed={IndexedFiles}, Failed={FailedFiles}, Total={TotalFiles}.",
|
"Finished background embeddings for data source '{DataSourceName}' ({DataSourceId}). Indexed={IndexedFiles}, Failed={FailedFiles}, Total={TotalFiles}.",
|
||||||
dataSource.Name,
|
dataSource.Name,
|
||||||
@ -558,6 +587,14 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
return dataSource is DataSourceLocalDirectory or DataSourceLocalFile;
|
return dataSource is DataSourceLocalDirectory or DataSourceLocalFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryGetConfiguredDataSource(string dataSourceId, [NotNullWhen(true)] out IDataSource? dataSource)
|
||||||
|
{
|
||||||
|
dataSource = settingsManager.ConfigurationData.DataSources
|
||||||
|
.FirstOrDefault(source => source.Id.Equals(dataSourceId, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
return dataSource is not null;
|
||||||
|
}
|
||||||
|
|
||||||
private bool TryResolveEmbeddingProvider(IDataSource dataSource, [NotNullWhen(true)] out EmbeddingProvider? embeddingProvider)
|
private bool TryResolveEmbeddingProvider(IDataSource dataSource, [NotNullWhen(true)] out EmbeddingProvider? embeddingProvider)
|
||||||
{
|
{
|
||||||
embeddingProvider = settingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(provider =>
|
embeddingProvider = settingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(provider =>
|
||||||
@ -641,7 +678,8 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
int indexedFiles,
|
int indexedFiles,
|
||||||
int failedFiles,
|
int failedFiles,
|
||||||
string currentFile = "",
|
string currentFile = "",
|
||||||
string lastError = "")
|
string lastError = "",
|
||||||
|
IReadOnlyList<DataSourceEmbeddingFailure>? failures = null)
|
||||||
{
|
{
|
||||||
return new DataSourceEmbeddingStatus(
|
return new DataSourceEmbeddingStatus(
|
||||||
dataSource.Id,
|
dataSource.Id,
|
||||||
@ -652,10 +690,11 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
indexedFiles,
|
indexedFiles,
|
||||||
failedFiles,
|
failedFiles,
|
||||||
currentFile,
|
currentFile,
|
||||||
lastError);
|
lastError,
|
||||||
|
failures?.ToList() ?? []);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataSourceEmbeddingStatus CreateCompletedStatus(IDataSource dataSource, int totalFiles, int indexedFiles, int failedFiles, string lastError)
|
private DataSourceEmbeddingStatus CreateCompletedStatus(IDataSource dataSource, int totalFiles, int indexedFiles, int failedFiles, string lastError, IReadOnlyList<DataSourceEmbeddingFailure>? failures = null)
|
||||||
{
|
{
|
||||||
return this.CreateStatus(
|
return this.CreateStatus(
|
||||||
dataSource,
|
dataSource,
|
||||||
@ -667,12 +706,20 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
? string.IsNullOrWhiteSpace(lastError)
|
? string.IsNullOrWhiteSpace(lastError)
|
||||||
? "Some files could not be embedded. See the logs for details."
|
? "Some files could not be embedded. See the logs for details."
|
||||||
: lastError
|
: lastError
|
||||||
: string.Empty);
|
: string.Empty,
|
||||||
|
failures: failures);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataSourceEmbeddingStatus GetFallbackStatus(IDataSource dataSource, string errorMessage)
|
private DataSourceEmbeddingStatus GetFallbackStatus(IDataSource dataSource, string errorMessage)
|
||||||
{
|
{
|
||||||
return this.CreateStatus(dataSource, DataSourceEmbeddingState.FAILED, 0, 0, 1, lastError: errorMessage);
|
return this.CreateStatus(
|
||||||
|
dataSource,
|
||||||
|
DataSourceEmbeddingState.FAILED,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
lastError: errorMessage,
|
||||||
|
failures: [new DataSourceEmbeddingFailure(dataSource.Name, errorMessage)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataSourceQueueRequestResult TryReserveDataSourceQueueSlot(string dataSourceId, bool queueAfterCurrentRun)
|
private DataSourceQueueRequestResult TryReserveDataSourceQueueSlot(string dataSourceId, bool queueAfterCurrentRun)
|
||||||
@ -749,7 +796,8 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
|||||||
currentStatus?.TotalFiles ?? 0,
|
currentStatus?.TotalFiles ?? 0,
|
||||||
currentStatus?.IndexedFiles ?? 0,
|
currentStatus?.IndexedFiles ?? 0,
|
||||||
currentStatus?.FailedFiles ?? 0,
|
currentStatus?.FailedFiles ?? 0,
|
||||||
lastError: currentStatus?.LastError ?? string.Empty));
|
lastError: currentStatus?.LastError ?? string.Empty,
|
||||||
|
failures: currentStatus?.Failures ?? []));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user