background embed

This commit is contained in:
PaulKoudelka committed 2026-05-08 17:37:34 +02:00
1 parent e3cb7e9734
commit ac677c5ac7
20 files changed
+1623 -98

No files matched your search

@@ -0,0 +1,64 @@
@attribute [Route(Routes.EMBEDDINGS)]
@inherits MSGComponentBase
<MudStack Spacing="3">
<MudPaper Class="pa-4 border-dashed border rounded-lg" Elevation="0">
<MudText Typo="Typo.h5">@T("Background embeddings")</MudText>
<MudText Typo="Typo.body1" Class="mt-2">
@T("AI Studio indexes local RAG data sources in the background. Finished files stay recorded so unchanged files can be skipped after a restart, while added or deleted files are detected during the next run.")
</MudText>
<MudStack Row="true" Class="mt-3" Wrap="Wrap.Wrap" Spacing="2">
<MudChip T="string" Color="Color.Success" Variant="Variant.Filled">@string.Format(T("Indexed files: {0}"), this.TotalIndexedFiles)</MudChip>
<MudChip T="string" Color="Color.Info" Variant="Variant.Filled">@string.Format(T("Pending files: {0}"), this.TotalPendingFiles)</MudChip>
<MudChip T="string" Color="Color.Error" Variant="Variant.Filled">@string.Format(T("Failed files: {0}"), this.TotalFailedFiles)</MudChip>
</MudStack>
</MudPaper>
@if (this.Statuses.Count == 0)
{
<MudAlert Severity="Severity.Info" Variant="Variant.Outlined">
@T("No local data source has been queued for embedding yet.")
</MudAlert>
}
else
{
@foreach (var status in this.Statuses)
{
<MudPaper Class="pa-4 border rounded-lg" Elevation="0">
<MudStack Spacing="2">
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
<MudText Typo="Typo.h6">@status.DataSourceName</MudText>
<MudChip T="string" Color="@GetStatusColor(status)" Variant="Variant.Filled">@status.StateLabel</MudChip>
</MudStack>
<MudProgressLinear Value="@status.ProgressPercent" Rounded="@true" Color="@GetStatusColor(status)" />
<MudText Typo="Typo.body2">
@string.Format(T("{0} of {1} files are indexed."), status.IndexedFiles, status.TotalFiles)
</MudText>
@if (status.FailedFiles > 0)
{
<MudText Typo="Typo.body2">
@string.Format(T("Failed files: {0}"), status.FailedFiles)
</MudText>
}
@if (!string.IsNullOrWhiteSpace(status.CurrentFile))
{
<MudText Typo="Typo.body2">
@string.Format(T("Current file: {0}"), status.CurrentFile)
</MudText>
}
@if (!string.IsNullOrWhiteSpace(status.LastError))
{
<MudAlert Severity="Severity.Warning" Variant="Variant.Text">
@status.LastError
</MudAlert>
}
</MudStack>
</MudPaper>
}
}
</MudStack>
@@ -0,0 +1,57 @@
using AIStudio.Components;
using AIStudio.Tools.Services;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Pages;
public partial class Embeddings : MSGComponentBase
{
[Inject]
private DataSourceEmbeddingService DataSourceEmbeddingService { get; init; } = null!;
private IReadOnlyList<DataSourceEmbeddingStatus> Statuses { get; set; } = [];
private int TotalIndexedFiles => this.Statuses.Sum(status => status.IndexedFiles);
private int TotalPendingFiles => this.Statuses.Sum(status => Math.Max(0, status.TotalFiles - status.IndexedFiles - status.FailedFiles));
private int TotalFailedFiles => this.Statuses.Sum(status => status.FailedFiles);
protected override async Task OnInitializedAsync()
{
this.ApplyFilters([], [ Event.RAG_EMBEDDING_STATUS_CHANGED, Event.CONFIGURATION_CHANGED ]);
await base.OnInitializedAsync();
this.ReloadStatuses();
}
protected override Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
{
if (triggeredEvent is Event.RAG_EMBEDDING_STATUS_CHANGED or Event.CONFIGURATION_CHANGED)
{
this.ReloadStatuses();
this.StateHasChanged();
}
return Task.CompletedTask;
}
private void ReloadStatuses()
{
this.Statuses = this.DataSourceEmbeddingService
.GetStatuses()
.OrderBy(status => status.SortOrder)
.ThenBy(status => status.DataSourceName, StringComparer.OrdinalIgnoreCase)
.ToList();
}
private static Color GetStatusColor(DataSourceEmbeddingStatus status) => status.State switch
{
DataSourceEmbeddingState.RUNNING => Color.Warning,
DataSourceEmbeddingState.QUEUED => Color.Info,
DataSourceEmbeddingState.FAILED => Color.Error,
DataSourceEmbeddingState.COMPLETED when status.FailedFiles > 0 => Color.Warning,
DataSourceEmbeddingState.COMPLETED => Color.Success,
_ => Color.Default,
};
}
@@ -29,7 +29,7 @@ public partial class Information : MSGComponentBase
private ISnackbar Snackbar { get; init; } = null!;
[Inject]
private DatabaseClient DatabaseClient { get; init; } = null!;
private EmbeddingStore EmbeddingStore { get; init; } = null!;
private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly();
private static readonly MetaDataAttribute META_DATA = ASSEMBLY.GetCustomAttribute<MetaDataAttribute>()!;
@@ -59,9 +59,9 @@ public partial class Information : MSGComponentBase
private string VersionPdfium => $"{T("Used PDFium version")}: v{META_DATA_LIBRARIES.PdfiumVersion}";
private string VersionDatabase => this.DatabaseClient.IsAvailable
? $"{T("Database version")}: {this.DatabaseClient.Name} v{META_DATA_DATABASES.DatabaseVersion}"
: $"{T("Database")}: {this.DatabaseClient.Name} - {T("not available")}";
private string VersionDatabase => this.EmbeddingStore.IsAvailable
? $"{T("Database version")}: {this.EmbeddingStore.Name} v{META_DATA_DATABASES.DatabaseVersion}"
: $"{T("Database")}: {this.EmbeddingStore.Name} - {T("not available")}";
private string versionPandoc = TB("Determine Pandoc version, please wait...");
private PandocInstallation pandocInstallation;
@@ -130,7 +130,7 @@ public partial class Information : MSGComponentBase
this.osLanguage = await this.RustService.ReadUserLanguage();
this.logPaths = await this.RustService.GetLogPaths();
await foreach (var (label, value) in this.DatabaseClient.GetDisplayInfo())
await foreach (var (label, value) in this.EmbeddingStore.GetDisplayInfo())
{
this.databaseDisplayInfo.Add(new DatabaseDisplayInfo(label, value));
}