mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-09-27 01:53:36 +00:00
Show the local RAG index on the information page
This commit is contained in:
parent
1e712f5f83
commit
bcc1a3b5eb
@ -9538,6 +9538,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2929232062"] = "Copies the confi
|
||||
-- Copies the root certificate fingerprint to the clipboard
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2989678330"] = "Copies the root certificate fingerprint to the clipboard"
|
||||
|
||||
-- Local RAG index
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2990297806"] = "Local RAG index"
|
||||
|
||||
-- The toml crate parses the embedded prompt-injection phrase catalog when the runtime starts. This keeps the detection rules separate from the Rust implementation and easier to maintain.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2999154325"] = "The toml crate parses the embedded prompt-injection phrase catalog when the runtime starts. This keeps the detection rules separate from the Rust implementation and easier to maintain."
|
||||
|
||||
@ -9700,6 +9703,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T4058524336"] = "Allowed hosts: n
|
||||
-- This library is used by the Rust runtime to read the current user's username, e.g. when an organization-managed ERI server uses the OS username for authentication.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T4060906280"] = "This library is used by the Rust runtime to read the current user's username, e.g. when an organization-managed ERI server uses the OS username for authentication."
|
||||
|
||||
-- Local RAG index version
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T4061134614"] = "Local RAG index version"
|
||||
|
||||
-- This library is used to create asynchronous streams in Rust. It allows us to work with streams of data that can be produced asynchronously, making it easier to handle events or data that arrive over time. We use this, e.g., to stream arbitrary data from the file system to the embedding system.
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T4079152443"] = "This library is used to create asynchronous streams in Rust. It allows us to work with streams of data that can be produced asynchronously, making it easier to handle events or data that arrive over time. We use this, e.g., to stream arbitrary data from the file system to the embedding system."
|
||||
|
||||
@ -10699,33 +10705,96 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T10
|
||||
-- Starting
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T1233211769"] = "Starting"
|
||||
|
||||
-- unknown
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T2608177081"] = "unknown"
|
||||
|
||||
-- Native library path
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T3089048804"] = "Native library path"
|
||||
|
||||
-- Unavailable
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T3662391977"] = "Unavailable"
|
||||
|
||||
-- Process architecture
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T563161633"] = "Process architecture"
|
||||
|
||||
-- Status
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T6222351"] = "Status"
|
||||
|
||||
-- Native library
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T634426545"] = "Native library"
|
||||
|
||||
-- no migration applied
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1014567907"] = "no migration applied"
|
||||
|
||||
-- Database path
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1100578143"] = "Database path"
|
||||
|
||||
-- Storage size
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1230141403"] = "Storage size"
|
||||
|
||||
-- Full-text search (FTS5)
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1396060361"] = "Full-text search (FTS5)"
|
||||
|
||||
-- Wrapper version
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1469427584"] = "Wrapper version"
|
||||
|
||||
-- available
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1727918744"] = "available"
|
||||
|
||||
-- not determined
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1959939977"] = "not determined"
|
||||
|
||||
-- Indexed files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2235289713"] = "Indexed files"
|
||||
|
||||
-- {0} ({1} applied)
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2286846332"] = "{0} ({1} applied)"
|
||||
|
||||
-- Search chunks
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2333737457"] = "Search chunks"
|
||||
|
||||
-- Journal mode
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2411639995"] = "Journal mode"
|
||||
|
||||
-- unknown
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2608177081"] = "unknown"
|
||||
|
||||
-- Native library path
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3089048804"] = "Native library path"
|
||||
|
||||
-- Database tables
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3279078157"] = "Database tables"
|
||||
|
||||
-- Indexed data sources
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3524534748"] = "Indexed data sources"
|
||||
|
||||
-- Reported version
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3556099842"] = "Reported version"
|
||||
|
||||
-- not available
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3574465749"] = "not available"
|
||||
|
||||
-- Permanently skipped files
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3965853089"] = "Permanently skipped files"
|
||||
|
||||
-- Library source ID
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T4168112546"] = "Library source ID"
|
||||
|
||||
-- Schema version
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T424290830"] = "Schema version"
|
||||
|
||||
-- Process architecture
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T563161633"] = "Process architecture"
|
||||
|
||||
-- Native library
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T634426545"] = "Native library"
|
||||
|
||||
-- System architecture
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T818259255"] = "System architecture"
|
||||
|
||||
-- {0} ({1} applied, {2} pending)
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T983802795"] = "{0} ({1} applied, {2} pending)"
|
||||
|
||||
-- Reason
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::NODATABASECLIENT::T1093747001"] = "Reason"
|
||||
|
||||
@ -10750,6 +10819,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::NOVECTORSTORECLIENT::T
|
||||
-- Storage size
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T1230141403"] = "Storage size"
|
||||
|
||||
-- unknown
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T2608177081"] = "unknown"
|
||||
|
||||
-- Number of vector stores
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T2785004838"] = "Number of vector stores"
|
||||
|
||||
@ -10759,6 +10831,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEM
|
||||
-- Status
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T6222351"] = "Status"
|
||||
|
||||
-- Stored vectors
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T701689894"] = "Stored vectors"
|
||||
|
||||
-- Qdrant Edge is not available.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T744445696"] = "Qdrant Edge is not available."
|
||||
|
||||
|
||||
@ -22,25 +22,40 @@
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Build" Text="@this.VersionRust"/>
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Storage">
|
||||
<MudText Typo="Typo.body1">
|
||||
@this.VersionVectorStore
|
||||
@this.DatabaseHeaderText(this.vectorStoreSection)
|
||||
</MudText>
|
||||
<MudCollapse Expanded="@this.showVectorStoreDetails">
|
||||
<MudCollapse Expanded="@this.vectorStoreSection.ShowDetails">
|
||||
<MudText Typo="Typo.body1" Class="mt-2 mb-2">
|
||||
@foreach (var item in this.vectorStoreDisplayInfo)
|
||||
@foreach (var item in this.BuildDatabaseInfoItems(this.vectorStoreSection))
|
||||
{
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<MudIcon Icon="@Icons.Material.Filled.ArrowRightAlt"/>
|
||||
<span>@item.Label: @item.Value</span>
|
||||
<MudCopyClipboardButton TooltipMessage="@(T("Copies the following to the clipboard")+": "+item.Value)" StringContent=@item.Value/>
|
||||
</div>
|
||||
<ConfigInfoRow Item="@item"/>
|
||||
}
|
||||
</MudText>
|
||||
</MudCollapse>
|
||||
<MudButton StartIcon="@(this.showVectorStoreDetails ? Icons.Material.Filled.ExpandLess : Icons.Material.Filled.ExpandMore)"
|
||||
<MudButton StartIcon="@(this.vectorStoreSection.ShowDetails ? Icons.Material.Filled.ExpandLess : Icons.Material.Filled.ExpandMore)"
|
||||
Size="Size.Small"
|
||||
Variant="Variant.Text"
|
||||
OnClick="@this.ToggleVectorStoreDetails">
|
||||
@(this.showVectorStoreDetails ? T("Hide Details") : T("Show Details"))
|
||||
OnClick="@(() => this.ToggleDatabaseDetails(this.vectorStoreSection))">
|
||||
@(this.vectorStoreSection.ShowDetails ? T("Hide Details") : T("Show Details"))
|
||||
</MudButton>
|
||||
</MudListItem>
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.ManageSearch">
|
||||
<MudText Typo="Typo.body1">
|
||||
@this.DatabaseHeaderText(this.indexStoreSection)
|
||||
</MudText>
|
||||
<MudCollapse Expanded="@this.indexStoreSection.ShowDetails">
|
||||
<MudText Typo="Typo.body1" Class="mt-2 mb-2">
|
||||
@foreach (var item in this.BuildDatabaseInfoItems(this.indexStoreSection))
|
||||
{
|
||||
<ConfigInfoRow Item="@item"/>
|
||||
}
|
||||
</MudText>
|
||||
</MudCollapse>
|
||||
<MudButton StartIcon="@(this.indexStoreSection.ShowDetails ? Icons.Material.Filled.ExpandLess : Icons.Material.Filled.ExpandMore)"
|
||||
Size="Size.Small"
|
||||
Variant="Variant.Text"
|
||||
OnClick="@(() => this.ToggleDatabaseDetails(this.indexStoreSection))">
|
||||
@(this.indexStoreSection.ShowDetails ? T("Hide Details") : T("Show Details"))
|
||||
</MudButton>
|
||||
</MudListItem>
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.DocumentScanner" Text="@this.VersionPdfium"/>
|
||||
|
||||
@ -4,7 +4,6 @@ using AIStudio.Components;
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.Databases;
|
||||
using AIStudio.Tools.Databases.VectorStore;
|
||||
using AIStudio.Tools.Metadata;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.Rust;
|
||||
@ -98,22 +97,40 @@ public partial class Information : MSGComponentBase
|
||||
|
||||
private string VersionPdfium => $"{T("Used PDFium version")}: v{META_DATA_LIBRARIES.PdfiumVersion}";
|
||||
|
||||
private string VersionVectorStore
|
||||
/// <summary>
|
||||
/// Builds the headline of one database block.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The vector store names the version from the build metadata, which is what this page always
|
||||
/// showed. The index store names the one its client read from the running database instead:
|
||||
/// there, which SQLite build actually got loaded is the whole point of showing it.
|
||||
/// </remarks>
|
||||
private string DatabaseHeaderText(DatabaseSection section)
|
||||
{
|
||||
get
|
||||
var (nameLabel, versionLabel) = section.Role switch
|
||||
{
|
||||
if (this.vectorStore is null)
|
||||
return $"{T("Vector store")}: {T("checking availability")}";
|
||||
DatabaseRole.VECTOR_STORE => (T("Vector store"), T("Vector store version")),
|
||||
_ => (T("Local RAG index"), T("Local RAG index version"))
|
||||
};
|
||||
|
||||
return this.vectorStore.Status switch
|
||||
{
|
||||
DatabaseClientStatus.AVAILABLE => $"{T("Vector store version")}: {this.vectorStore.Name} v{META_DATA_VECTOR_STORE.VectorStoreVersion}",
|
||||
DatabaseClientStatus.STARTING => $"{T("Vector store")}: {this.vectorStore.Name} - {T("starting")}",
|
||||
_ => $"{T("Vector store")}: {this.vectorStore.Name} - {T("not available")}"
|
||||
};
|
||||
}
|
||||
if (section.Client is null)
|
||||
return $"{nameLabel}: {T("checking availability")}";
|
||||
|
||||
var version = section.Role switch
|
||||
{
|
||||
DatabaseRole.VECTOR_STORE => META_DATA_VECTOR_STORE.VectorStoreVersion,
|
||||
_ => section.Client.Version
|
||||
};
|
||||
|
||||
return section.Client.Status switch
|
||||
{
|
||||
DatabaseClientStatus.AVAILABLE when !string.IsNullOrWhiteSpace(version) => $"{versionLabel}: {section.Client.Name} v{version}",
|
||||
DatabaseClientStatus.AVAILABLE => $"{nameLabel}: {section.Client.Name}",
|
||||
DatabaseClientStatus.STARTING => $"{nameLabel}: {section.Client.Name} - {T("starting")}",
|
||||
_ => $"{nameLabel}: {section.Client.Name} - {T("not available")}"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private string versionPandoc = TB("Determine Pandoc version, please wait...");
|
||||
private PandocInstallation pandocInstallation;
|
||||
|
||||
@ -121,7 +138,6 @@ public partial class Information : MSGComponentBase
|
||||
|
||||
private bool showEnterpriseConfigDetails;
|
||||
|
||||
private bool showVectorStoreDetails;
|
||||
private bool showExternalHttpCustomRootCertificateDetails;
|
||||
|
||||
private List<IAvailablePlugin> configPlugins = [];
|
||||
@ -141,10 +157,30 @@ public partial class Information : MSGComponentBase
|
||||
|
||||
private sealed record MandatoryInfoPanelData(string HeaderText, string PluginName, DataMandatoryInfo Info, DataMandatoryInfoAcceptance? Acceptance);
|
||||
|
||||
private sealed record VectorStoreDisplayInfo(string Label, string Value);
|
||||
private readonly List<VectorStoreDisplayInfo> vectorStoreDisplayInfo = new();
|
||||
private DatabaseClient? vectorStore;
|
||||
private CancellationTokenSource? vectorStoreRefreshCancellationTokenSource;
|
||||
private sealed record DatabaseDisplayInfo(string Label, string Value);
|
||||
|
||||
/// <summary>
|
||||
/// Everything one database block on this page needs to show itself.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Both blocks work the same way, so they share their state and their methods and differ only
|
||||
/// in their role. Whoever adds a third database adds one field here, not another set of methods.
|
||||
/// </remarks>
|
||||
private sealed class DatabaseSection(DatabaseRole role)
|
||||
{
|
||||
public DatabaseRole Role => role;
|
||||
|
||||
public DatabaseClient? Client { get; set; }
|
||||
|
||||
public bool ShowDetails { get; set; }
|
||||
|
||||
public List<DatabaseDisplayInfo> DisplayInfo { get; } = [];
|
||||
|
||||
public CancellationTokenSource? RefreshCancellationTokenSource { get; set; }
|
||||
}
|
||||
|
||||
private readonly DatabaseSection vectorStoreSection = new(DatabaseRole.VECTOR_STORE);
|
||||
private readonly DatabaseSection indexStoreSection = new(DatabaseRole.INDEX_STORE);
|
||||
|
||||
private bool HasAnyActiveEnvironment => this.enterpriseEnvironments.Any(e => e.IsActive);
|
||||
|
||||
@ -191,9 +227,16 @@ public partial class Information : MSGComponentBase
|
||||
this.updatePolicyMode = this.UpdatePolicy.CurrentMode;
|
||||
this.logPaths = await this.RustService.GetLogPaths();
|
||||
|
||||
await this.RefreshVectorStoreInfo(CancellationToken.None);
|
||||
if (this.vectorStore?.Status is DatabaseClientStatus.STARTING)
|
||||
this.StartShortVectorStoreRefreshLoop();
|
||||
// The index store goes first: the vector store asks it for the number of stored vectors,
|
||||
// and this way that client is already cached when it does.
|
||||
await this.RefreshDatabaseInfo(this.indexStoreSection, CancellationToken.None);
|
||||
await this.RefreshDatabaseInfo(this.vectorStoreSection, CancellationToken.None);
|
||||
|
||||
if (this.indexStoreSection.Client?.Status is DatabaseClientStatus.STARTING)
|
||||
this.StartShortDatabaseRefreshLoop(this.indexStoreSection);
|
||||
|
||||
if (this.vectorStoreSection.Client?.Status is DatabaseClientStatus.STARTING)
|
||||
this.StartShortDatabaseRefreshLoop(this.vectorStoreSection);
|
||||
|
||||
// Determine the Pandoc version may take some time, so we start it here
|
||||
// without waiting for the result:
|
||||
@ -301,22 +344,31 @@ public partial class Information : MSGComponentBase
|
||||
this.showExternalHttpCustomRootCertificateDetails = !this.showExternalHttpCustomRootCertificateDetails;
|
||||
}
|
||||
|
||||
private void ToggleVectorStoreDetails()
|
||||
private void ToggleDatabaseDetails(DatabaseSection section)
|
||||
{
|
||||
this.showVectorStoreDetails = !this.showVectorStoreDetails;
|
||||
section.ShowDetails = !section.ShowDetails;
|
||||
}
|
||||
|
||||
private async Task RefreshVectorStoreInfo(CancellationToken cancellationToken)
|
||||
private IReadOnlyList<ConfigInfoRowItem> BuildDatabaseInfoItems(DatabaseSection section) => section.DisplayInfo
|
||||
.Select((item, index) => new ConfigInfoRowItem(
|
||||
Icons.Material.Filled.ArrowRightAlt,
|
||||
$"{item.Label}: {item.Value}",
|
||||
item.Value,
|
||||
$"{T("Copies the following to the clipboard")}: {item.Value}",
|
||||
index == 0 ? string.Empty : "margin-top: 4px;"))
|
||||
.ToList();
|
||||
|
||||
private async Task RefreshDatabaseInfo(DatabaseSection section, CancellationToken cancellationToken)
|
||||
{
|
||||
var refreshedClient = await this.DatabaseClientProvider.RefreshClientAsync(DatabaseRole.VECTOR_STORE, cancellationToken);
|
||||
this.vectorStore = refreshedClient;
|
||||
this.vectorStoreDisplayInfo.Clear();
|
||||
var refreshedClient = await this.DatabaseClientProvider.RefreshClientAsync(section.Role, cancellationToken);
|
||||
section.Client = refreshedClient;
|
||||
section.DisplayInfo.Clear();
|
||||
|
||||
try
|
||||
{
|
||||
await foreach (var (label, value) in refreshedClient.GetDisplayInfo().WithCancellation(cancellationToken))
|
||||
{
|
||||
this.vectorStoreDisplayInfo.Add(new VectorStoreDisplayInfo(label, value));
|
||||
section.DisplayInfo.Add(new DatabaseDisplayInfo(label, value));
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@ -325,20 +377,24 @@ public partial class Information : MSGComponentBase
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.vectorStore = new NoVectorStoreClient(refreshedClient.Name, e.Message, DatabaseClientStatus.STARTING);
|
||||
await foreach (var (label, value) in this.vectorStore.GetDisplayInfo().WithCancellation(cancellationToken))
|
||||
// Drop whatever came in before the failure: those lines would otherwise stand next to
|
||||
// the status and reason of the stand-in client and read like current values.
|
||||
section.DisplayInfo.Clear();
|
||||
|
||||
section.Client = DatabaseClientProvider.CreateUnavailableClient(section.Role, refreshedClient.Name, e.Message, DatabaseClientStatus.STARTING);
|
||||
await foreach (var (label, value) in section.Client.GetDisplayInfo().WithCancellation(cancellationToken))
|
||||
{
|
||||
this.vectorStoreDisplayInfo.Add(new VectorStoreDisplayInfo(label, value));
|
||||
section.DisplayInfo.Add(new DatabaseDisplayInfo(label, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StartShortVectorStoreRefreshLoop()
|
||||
private void StartShortDatabaseRefreshLoop(DatabaseSection section)
|
||||
{
|
||||
this.vectorStoreRefreshCancellationTokenSource?.Cancel();
|
||||
this.vectorStoreRefreshCancellationTokenSource?.Dispose();
|
||||
this.vectorStoreRefreshCancellationTokenSource = new CancellationTokenSource();
|
||||
var cancellationToken = this.vectorStoreRefreshCancellationTokenSource.Token;
|
||||
section.RefreshCancellationTokenSource?.Cancel();
|
||||
section.RefreshCancellationTokenSource?.Dispose();
|
||||
section.RefreshCancellationTokenSource = new CancellationTokenSource();
|
||||
var cancellationToken = section.RefreshCancellationTokenSource.Token;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
@ -350,11 +406,11 @@ public partial class Information : MSGComponentBase
|
||||
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
|
||||
await this.InvokeAsync(async () =>
|
||||
{
|
||||
await this.RefreshVectorStoreInfo(cancellationToken);
|
||||
await this.RefreshDatabaseInfo(section, cancellationToken);
|
||||
this.StateHasChanged();
|
||||
});
|
||||
|
||||
if (this.vectorStore?.Status is not DatabaseClientStatus.STARTING)
|
||||
if (section.Client?.Status is not DatabaseClientStatus.STARTING)
|
||||
return;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@ -366,7 +422,14 @@ public partial class Information : MSGComponentBase
|
||||
return;
|
||||
}
|
||||
}
|
||||
}, cancellationToken).Observe($"{nameof(Information)}: refreshing the vector store info");
|
||||
}, cancellationToken).Observe($"{nameof(Information)}: refreshing the {section.Role} info");
|
||||
}
|
||||
|
||||
private void CancelDatabaseRefreshLoop(DatabaseSection section)
|
||||
{
|
||||
section.RefreshCancellationTokenSource?.Cancel();
|
||||
section.RefreshCancellationTokenSource?.Dispose();
|
||||
section.RefreshCancellationTokenSource = null;
|
||||
}
|
||||
|
||||
private IAvailablePlugin? FindManagedConfigurationPlugin(Guid configurationId)
|
||||
@ -525,8 +588,8 @@ public partial class Information : MSGComponentBase
|
||||
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
this.vectorStoreRefreshCancellationTokenSource?.Cancel();
|
||||
this.vectorStoreRefreshCancellationTokenSource?.Dispose();
|
||||
this.CancelDatabaseRefreshLoop(this.vectorStoreSection);
|
||||
this.CancelDatabaseRefreshLoop(this.indexStoreSection);
|
||||
base.DisposeResources();
|
||||
}
|
||||
|
||||
|
||||
@ -69,6 +69,25 @@ public sealed class DatabaseClientProvider(RustService rustService, ILoggerFacto
|
||||
client.Status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the client which stands in for a database role that cannot serve right now.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Callers outside this namespace get their stand-in from here instead of naming the concrete
|
||||
/// type themselves, so a new role does not have to be spelled out in every one of them.
|
||||
/// </remarks>
|
||||
/// <param name="databaseRole">The role the stand-in has to fill.</param>
|
||||
/// <param name="name">The name to show for the database.</param>
|
||||
/// <param name="reason">Why the database is not available.</param>
|
||||
/// <param name="status">Whether the database is starting or unavailable.</param>
|
||||
/// <returns>A client which answers every operation without a database behind it.</returns>
|
||||
public static DatabaseClient CreateUnavailableClient(DatabaseRole databaseRole, string name, string? reason, DatabaseClientStatus status) => databaseRole switch
|
||||
{
|
||||
DatabaseRole.VECTOR_STORE => new NoVectorStoreClient(name, reason, status),
|
||||
DatabaseRole.INDEX_STORE => new NoIndexStoreClient(name, reason, status),
|
||||
_ => new NoDatabaseClient(name, reason, status)
|
||||
};
|
||||
|
||||
private DatabaseClient CacheIfAvailable(DatabaseRole databaseRole, DatabaseClient client)
|
||||
{
|
||||
if (!client.IsAvailable)
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
using System.Globalization;
|
||||
|
||||
using AIStudio.Tools.Databases.IndexStore;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.Rust;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user