mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-05 05:49:40 +00:00
Merge branch 'main' into chunk-data
This commit is contained in:
commit
b7b18aa45c
109 files changed
+6469
-1691
No files matched your search
@@ -2,14 +2,6 @@
|
||||
|
||||
public interface IVectorStoreClient
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
DatabaseClientStatus Status { get; }
|
||||
|
||||
bool IsAvailable { get; }
|
||||
|
||||
IAsyncEnumerable<(string Label, string Value)> GetDisplayInfo();
|
||||
|
||||
Task EnsureVectorStoreExists(string storeName, int vectorSize, CancellationToken token);
|
||||
|
||||
Task InsertEmbedding(string storeName, IReadOnlyList<VectorStoragePoint> points, CancellationToken token);
|
||||
|
||||
@@ -2,19 +2,19 @@ using AIStudio.Tools.PluginSystem;
|
||||
|
||||
namespace AIStudio.Tools.Databases.VectorStore;
|
||||
|
||||
public sealed class NoVectorStoreClient(string name, string? unavailableReason, DatabaseClientStatus status = DatabaseClientStatus.UNAVAILABLE) : IVectorStoreClient
|
||||
public sealed class NoVectorStoreClient(string name, string? unavailableReason, DatabaseClientStatus status = DatabaseClientStatus.UNAVAILABLE) : DatabaseClient(name, string.Empty), IVectorStoreClient
|
||||
{
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(NoVectorStoreClient).Namespace, nameof(NoVectorStoreClient));
|
||||
|
||||
public string Name => name;
|
||||
public override DatabaseClientStatus Status => status;
|
||||
|
||||
public DatabaseClientStatus Status => status;
|
||||
|
||||
public bool IsAvailable => false;
|
||||
|
||||
public async IAsyncEnumerable<(string Label, string Value)> GetDisplayInfo()
|
||||
public override async IAsyncEnumerable<(string Label, string Value)> GetDisplayInfo()
|
||||
{
|
||||
yield return (TB("Status"), TB("Unavailable"));
|
||||
yield return (TB("Status"), status switch
|
||||
{
|
||||
DatabaseClientStatus.STARTING => TB("Starting"),
|
||||
_ => TB("Unavailable")
|
||||
});
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(unavailableReason))
|
||||
yield return (TB("Reason"), unavailableReason);
|
||||
@@ -36,4 +36,8 @@ public sealed class NoVectorStoreClient(string name, string? unavailableReason,
|
||||
|
||||
private InvalidOperationException CreateUnavailableException() =>
|
||||
new(unavailableReason ?? "The vector store is not available.");
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.Rust;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
namespace AIStudio.Tools.Databases.VectorStore;
|
||||
|
||||
public sealed class QdrantEdgeClientImplementation(
|
||||
string name,
|
||||
string path,
|
||||
string version,
|
||||
int storesCount,
|
||||
RustService rustService) : DatabaseClient(name, path), IVectorStoreClient
|
||||
{
|
||||
private const string DATABASE_NAME = "Qdrant Edge";
|
||||
private const string INFO_PATH = "/system/qdrant-edge/info";
|
||||
private const string ENSURE_PATH = "/system/qdrant-edge/ensure";
|
||||
private const string INSERT_PATH = "/system/qdrant-edge/insert";
|
||||
private const string DELETE_FILE_PATH = "/system/qdrant-edge/delete-file";
|
||||
private const string DELETE_STORE_PATH = "/system/qdrant-edge/delete-store";
|
||||
|
||||
private readonly string path = path;
|
||||
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(QdrantEdgeClientImplementation).Namespace, nameof(QdrantEdgeClientImplementation));
|
||||
|
||||
public override string CacheKey => $"{this.Name}:{this.path}:{version}";
|
||||
|
||||
public static async Task<DatabaseClient> CreateAsync(
|
||||
RustService rustService,
|
||||
ILogger logger,
|
||||
ILogger<DatabaseClient> databaseClientLogger,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var qdrantEdgeInfo = await rustService.GetDatabaseInfo(
|
||||
DATABASE_NAME,
|
||||
INFO_PATH,
|
||||
QdrantEdgeInfo.Unavailable,
|
||||
cancellationToken);
|
||||
|
||||
if (qdrantEdgeInfo.Status is QdrantEdgeStatus.STARTING)
|
||||
{
|
||||
return CreateNoVectorStoreClient(
|
||||
DATABASE_NAME,
|
||||
$"{DATABASE_NAME} is starting. Details will appear shortly.",
|
||||
DatabaseClientStatus.STARTING,
|
||||
databaseClientLogger);
|
||||
}
|
||||
|
||||
if (!qdrantEdgeInfo.IsAvailable || qdrantEdgeInfo.Status is QdrantEdgeStatus.UNAVAILABLE)
|
||||
{
|
||||
var reason = qdrantEdgeInfo.UnavailableReason ?? "unknown";
|
||||
// ReSharper disable DuplicateItemInLoggerTemplate
|
||||
logger.LogWarning("{VectorStoreName} is not available. Starting without {VectorStoreName} vector store. Reason: '{Reason}'.", DATABASE_NAME, DATABASE_NAME, reason);
|
||||
// ReSharper restore DuplicateItemInLoggerTemplate
|
||||
return CreateNoVectorStoreClient(DATABASE_NAME, qdrantEdgeInfo.UnavailableReason, DatabaseClientStatus.UNAVAILABLE, databaseClientLogger);
|
||||
}
|
||||
|
||||
if (qdrantEdgeInfo.Path == string.Empty)
|
||||
return CreateNoVectorStoreClient(DATABASE_NAME, $"Failed to get the {DATABASE_NAME} path from Rust.", DatabaseClientStatus.UNAVAILABLE, databaseClientLogger);
|
||||
|
||||
var name = string.IsNullOrWhiteSpace(qdrantEdgeInfo.Name) ? DATABASE_NAME : qdrantEdgeInfo.Name;
|
||||
var client = new QdrantEdgeClientImplementation(name, qdrantEdgeInfo.Path, qdrantEdgeInfo.Version, qdrantEdgeInfo.StoresCount, rustService);
|
||||
client.SetLogger(databaseClientLogger);
|
||||
return client;
|
||||
}
|
||||
|
||||
public override async IAsyncEnumerable<(string Label, string Value)> GetDisplayInfo()
|
||||
{
|
||||
var currentInfo = await rustService.GetDatabaseInfo(
|
||||
DATABASE_NAME,
|
||||
INFO_PATH,
|
||||
QdrantEdgeInfo.Unavailable);
|
||||
var displayVersion = currentInfo.IsAvailable && !string.IsNullOrWhiteSpace(currentInfo.Version) ? currentInfo.Version : version;
|
||||
var displayStoresCount = currentInfo.IsAvailable ? currentInfo.StoresCount : storesCount;
|
||||
|
||||
if (!currentInfo.IsAvailable)
|
||||
yield return (TB("Status"), currentInfo.UnavailableReason ?? TB("Qdrant Edge is not available."));
|
||||
|
||||
yield return (TB("Reported version"), displayVersion);
|
||||
yield return (TB("Storage size"), $"{this.GetStorageSize()}");
|
||||
yield return (TB("Number of vector stores"), displayStoresCount.ToString());
|
||||
}
|
||||
|
||||
public Task EnsureVectorStoreExists(string storeName, int vectorSize, CancellationToken token) =>
|
||||
rustService.ExecuteDatabaseOperation(DATABASE_NAME, ENSURE_PATH, new EnsureVectorStoreRequest(storeName, vectorSize), token);
|
||||
|
||||
public Task InsertEmbedding(string storeName, IReadOnlyList<VectorStoragePoint> points, CancellationToken token) =>
|
||||
rustService.ExecuteDatabaseOperation(DATABASE_NAME, INSERT_PATH, new InsertEmbeddingRequest(storeName, points), token);
|
||||
|
||||
public Task DeleteEmbeddingByFile(string storeName, string filePath, CancellationToken token) =>
|
||||
rustService.ExecuteDatabaseOperation(DATABASE_NAME, DELETE_FILE_PATH, new DeleteEmbeddingByFileRequest(storeName, filePath), token);
|
||||
|
||||
public Task DeleteVectorStore(string storeName, CancellationToken token) =>
|
||||
rustService.ExecuteDatabaseOperation(DATABASE_NAME, DELETE_STORE_PATH, new DeleteVectorStoreRequest(storeName), token);
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
private static NoVectorStoreClient CreateNoVectorStoreClient(string name, string? unavailableReason, DatabaseClientStatus status, ILogger<DatabaseClient> databaseClientLogger)
|
||||
{
|
||||
var client = new NoVectorStoreClient(name, unavailableReason, status);
|
||||
client.SetLogger(databaseClientLogger);
|
||||
return client;
|
||||
}
|
||||
|
||||
// ReSharper disable NotAccessedPositionalProperty.Local
|
||||
private sealed record EnsureVectorStoreRequest(string StoreName, int VectorSize);
|
||||
|
||||
private sealed record InsertEmbeddingRequest(string StoreName, IReadOnlyList<VectorStoragePoint> Points);
|
||||
|
||||
private sealed record DeleteEmbeddingByFileRequest(string StoreName, string FilePath);
|
||||
|
||||
private sealed record DeleteVectorStoreRequest(string StoreName);
|
||||
// ReSharper restore NotAccessedPositionalProperty.Local
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace AIStudio.Tools.Databases.VectorStore;
|
||||
|
||||
public sealed record VectorStoragePoint(
|
||||
string PointId,
|
||||
IReadOnlyList<float> Vector,
|
||||
string DataSourceId,
|
||||
string DataSourceName,
|
||||
string DataSourceType,
|
||||
string FilePath,
|
||||
string FileName,
|
||||
string RelativePath,
|
||||
int ChunkIndex,
|
||||
string Text,
|
||||
string Fingerprint,
|
||||
DateTime LastWriteUtc,
|
||||
DateTime EmbeddedAtUtc);
|
||||
Reference in new issue
Block a user