chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests.ModelTests;
|
||||
|
||||
public class QdrantBasicModelTests(QdrantBasicModelTests.Fixture fixture)
|
||||
: BasicModelTests<ulong>(fixture), IClassFixture<QdrantBasicModelTests.Fixture>
|
||||
{
|
||||
public override async Task GetAsync_with_filter_and_multiple_OrderBys()
|
||||
{
|
||||
var exception = await Assert.ThrowsAsync<NotSupportedException>(base.GetAsync_with_filter_and_multiple_OrderBys);
|
||||
|
||||
Assert.Equal("Qdrant does not support ordering by more than one property.", exception.Message);
|
||||
}
|
||||
|
||||
public new class Fixture : BasicModelTests<ulong>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests.ModelTests;
|
||||
|
||||
public class QdrantDynamicModelTests_NamedVectors(QdrantDynamicModelTests_NamedVectors.Fixture fixture)
|
||||
: DynamicModelTests<ulong>(fixture), IClassFixture<QdrantDynamicModelTests_NamedVectors.Fixture>
|
||||
{
|
||||
public override async Task GetAsync_with_filter_and_multiple_OrderBys()
|
||||
{
|
||||
var exception = await Assert.ThrowsAsync<NotSupportedException>(base.GetAsync_with_filter_and_multiple_OrderBys);
|
||||
|
||||
Assert.Equal("Qdrant does not support ordering by more than one property.", exception.Message);
|
||||
}
|
||||
|
||||
public new class Fixture : DynamicModelTests<ulong>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public class QdrantDynamicModelTests_UnnamedVector(QdrantDynamicModelTests_UnnamedVector.Fixture fixture)
|
||||
: DynamicModelTests<ulong>(fixture), IClassFixture<QdrantDynamicModelTests_UnnamedVector.Fixture>
|
||||
{
|
||||
public override async Task GetAsync_with_filter_and_multiple_OrderBys()
|
||||
{
|
||||
var exception = await Assert.ThrowsAsync<NotSupportedException>(base.GetAsync_with_filter_and_multiple_OrderBys);
|
||||
|
||||
Assert.Equal("Qdrant does not support ordering by more than one property.", exception.Message);
|
||||
}
|
||||
|
||||
public new class Fixture : DynamicModelTests<ulong>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.UnnamedVectorInstance;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests.ModelTests;
|
||||
|
||||
public class QdrantMultiVectorModelTests(QdrantMultiVectorModelTests.Fixture fixture)
|
||||
: MultiVectorModelTests<ulong>(fixture), IClassFixture<QdrantMultiVectorModelTests.Fixture>
|
||||
{
|
||||
public new class Fixture : MultiVectorModelTests<ulong>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests.ModelTests;
|
||||
|
||||
public class QdrantNoDataModelTests_NamedVectors(QdrantNoDataModelTests_NamedVectors.Fixture fixture)
|
||||
: NoDataModelTests<ulong>(fixture), IClassFixture<QdrantNoDataModelTests_NamedVectors.Fixture>
|
||||
{
|
||||
public new class Fixture : NoDataModelTests<ulong>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public class QdrantNoDataModelTests_UnnamedVectors(QdrantNoDataModelTests_UnnamedVectors.Fixture fixture)
|
||||
: NoDataModelTests<ulong>(fixture), IClassFixture<QdrantNoDataModelTests_UnnamedVectors.Fixture>
|
||||
{
|
||||
public new class Fixture : NoDataModelTests<ulong>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.UnnamedVectorInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0;net472</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<IsPackable>false</IsPackable>
|
||||
<RootNamespace>Qdrant.ConformanceTests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="Testcontainers" />
|
||||
<PackageReference Include="Testcontainers.Qdrant" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\VectorData\Qdrant\Qdrant.csproj" />
|
||||
<ProjectReference Include="..\VectorData.ConformanceTests\VectorData.ConformanceTests.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests;
|
||||
|
||||
public class QdrantCollectionManagementTests_NamedVectors(QdrantNamedVectorsFixture fixture)
|
||||
: CollectionManagementTests<ulong>(fixture), IClassFixture<QdrantNamedVectorsFixture>
|
||||
{
|
||||
}
|
||||
|
||||
public class QdrantCollectionManagementTests_UnnamedVector(QdrantUnnamedVectorFixture fixture)
|
||||
: CollectionManagementTests<ulong>(fixture), IClassFixture<QdrantUnnamedVectorFixture>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel.Connectors.Qdrant;
|
||||
using Qdrant.Client;
|
||||
using VectorData.ConformanceTests;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests;
|
||||
|
||||
public class QdrantDependencyInjectionTests
|
||||
: DependencyInjectionTests<QdrantVectorStore, QdrantCollection<ulong, DependencyInjectionTests<ulong>.Record>, ulong, DependencyInjectionTests<ulong>.Record>
|
||||
{
|
||||
private const string Host = "localhost";
|
||||
private const int Port = 8080;
|
||||
private const string ApiKey = "fakeKey";
|
||||
|
||||
protected override void PopulateConfiguration(ConfigurationManager configuration, object? serviceKey = null)
|
||||
=> configuration.AddInMemoryCollection(
|
||||
[
|
||||
new(CreateConfigKey("Qdrant", serviceKey, "Host"), Host),
|
||||
new(CreateConfigKey("Qdrant", serviceKey, "Port"), Port.ToString()),
|
||||
new(CreateConfigKey("Qdrant", serviceKey, "ApiKey"), ApiKey),
|
||||
]);
|
||||
|
||||
private static string HostProvider(IServiceProvider sp, object? serviceKey = null)
|
||||
=> sp.GetRequiredService<IConfiguration>().GetRequiredSection(CreateConfigKey("Qdrant", serviceKey, "Host")).Value!;
|
||||
|
||||
private static int PortProvider(IServiceProvider sp, object? serviceKey = null)
|
||||
=> int.Parse(sp.GetRequiredService<IConfiguration>().GetRequiredSection(CreateConfigKey("Qdrant", serviceKey, "Port")).Value!);
|
||||
|
||||
private static string ApiKeyProvider(IServiceProvider sp, object? serviceKey = null)
|
||||
=> sp.GetRequiredService<IConfiguration>().GetRequiredSection(CreateConfigKey("Qdrant", serviceKey, "ApiKey")).Value!;
|
||||
|
||||
public override IEnumerable<Func<IServiceCollection, object?, string, ServiceLifetime, IServiceCollection>> CollectionDelegates
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return (services, serviceKey, name, lifetime) => serviceKey is null
|
||||
? services
|
||||
.AddSingleton<QdrantClient>(sp => new QdrantClient(Host, Port, apiKey: ApiKey))
|
||||
.AddQdrantCollection<ulong, Record>(name, lifetime: lifetime)
|
||||
: services
|
||||
.AddSingleton<QdrantClient>(sp => new QdrantClient(Host, Port, apiKey: ApiKey))
|
||||
.AddKeyedQdrantCollection<ulong, Record>(serviceKey, name, lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, name, lifetime) => serviceKey is null
|
||||
? services.AddQdrantCollection<ulong, Record>(
|
||||
name, Host, Port, apiKey: ApiKey, lifetime: lifetime)
|
||||
: services.AddKeyedQdrantCollection<ulong, Record>(
|
||||
serviceKey, name, Host, Port, apiKey: ApiKey, lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, name, lifetime) => serviceKey is null
|
||||
? services.AddQdrantCollection<ulong, Record>(
|
||||
name, sp => new QdrantClient(HostProvider(sp), PortProvider(sp), apiKey: ApiKeyProvider(sp)), lifetime: lifetime)
|
||||
: services.AddKeyedQdrantCollection<ulong, Record>(
|
||||
serviceKey, name, sp => new QdrantClient(HostProvider(sp, serviceKey), PortProvider(sp, serviceKey), apiKey: ApiKeyProvider(sp, serviceKey)), lifetime: lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Func<IServiceCollection, object?, ServiceLifetime, IServiceCollection>> StoreDelegates
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return (services, serviceKey, lifetime) => serviceKey is null
|
||||
? services.AddQdrantVectorStore(
|
||||
Host, Port, apiKey: ApiKey, lifetime: lifetime)
|
||||
: services.AddKeyedQdrantVectorStore(
|
||||
serviceKey, Host, Port, apiKey: ApiKey, lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, lifetime) => serviceKey is null
|
||||
? services
|
||||
.AddSingleton<QdrantClient>(sp => new QdrantClient(Host, Port, apiKey: ApiKey))
|
||||
.AddQdrantVectorStore(lifetime: lifetime)
|
||||
: services
|
||||
.AddSingleton<QdrantClient>(sp => new QdrantClient(Host, Port, apiKey: ApiKey))
|
||||
.AddKeyedQdrantVectorStore(serviceKey, lifetime: lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HostCantBeNullOrEmpty()
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddQdrantVectorStore(host: null!));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedQdrantVectorStore(serviceKey: "notNull", host: null!));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddQdrantCollection<ulong, Record>(
|
||||
name: "notNull", host: null!));
|
||||
Assert.Throws<ArgumentException>(() => services.AddQdrantCollection<ulong, Record>(
|
||||
name: "notNull", host: ""));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedQdrantCollection<ulong, Record>(
|
||||
serviceKey: "notNull", name: "notNull", host: null!));
|
||||
Assert.Throws<ArgumentException>(() => services.AddKeyedQdrantCollection<ulong, Record>(
|
||||
serviceKey: "notNull", name: "notNull", host: ""));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests;
|
||||
|
||||
public class QdrantDistanceFunctionTests(QdrantDistanceFunctionTests.Fixture fixture)
|
||||
: DistanceFunctionTests<ulong>(fixture), IClassFixture<QdrantDistanceFunctionTests.Fixture>
|
||||
{
|
||||
public override Task CosineDistance() => Assert.ThrowsAsync<NotSupportedException>(base.CosineDistance);
|
||||
public override Task NegativeDotProductSimilarity() => Assert.ThrowsAsync<NotSupportedException>(base.NegativeDotProductSimilarity);
|
||||
public override Task EuclideanSquaredDistance() => Assert.ThrowsAsync<NotSupportedException>(base.EuclideanSquaredDistance);
|
||||
public override Task HammingDistance() => Assert.ThrowsAsync<NotSupportedException>(base.HammingDistance);
|
||||
|
||||
public new class Fixture() : DistanceFunctionTests<ulong>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests;
|
||||
|
||||
public class QdrantEmbeddingGenerationTests(QdrantEmbeddingGenerationTests.StringVectorFixture stringVectorFixture, QdrantEmbeddingGenerationTests.RomOfFloatVectorFixture romOfFloatVectorFixture)
|
||||
: EmbeddingGenerationTests<Guid>(stringVectorFixture, romOfFloatVectorFixture), IClassFixture<QdrantEmbeddingGenerationTests.StringVectorFixture>, IClassFixture<QdrantEmbeddingGenerationTests.RomOfFloatVectorFixture>
|
||||
{
|
||||
public new class StringVectorFixture : EmbeddingGenerationTests<Guid>.StringVectorFixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.UnnamedVectorInstance;
|
||||
|
||||
public override VectorStore CreateVectorStore(IEmbeddingGenerator? embeddingGenerator)
|
||||
=> QdrantTestStore.UnnamedVectorInstance.GetVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionStoreRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(QdrantTestStore.UnnamedVectorInstance.Client)
|
||||
.AddQdrantVectorStore()
|
||||
];
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionCollectionRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(QdrantTestStore.UnnamedVectorInstance.Client)
|
||||
.AddQdrantCollection<Guid, RecordWithAttributes>(this.CollectionName)
|
||||
];
|
||||
}
|
||||
|
||||
public new class RomOfFloatVectorFixture : EmbeddingGenerationTests<Guid>.RomOfFloatVectorFixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.UnnamedVectorInstance;
|
||||
|
||||
public override VectorStore CreateVectorStore(IEmbeddingGenerator? embeddingGenerator)
|
||||
=> QdrantTestStore.UnnamedVectorInstance.GetVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionStoreRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(QdrantTestStore.UnnamedVectorInstance.Client)
|
||||
.AddQdrantVectorStore()
|
||||
];
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionCollectionRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(QdrantTestStore.UnnamedVectorInstance.Client)
|
||||
.AddQdrantCollection<Guid, RecordWithAttributes>(this.CollectionName)
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests;
|
||||
|
||||
public class QdrantFilterTests(QdrantFilterTests.Fixture fixture)
|
||||
: FilterTests<ulong>(fixture), IClassFixture<QdrantFilterTests.Fixture>
|
||||
{
|
||||
public new class Fixture : FilterTests<ulong>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests;
|
||||
|
||||
public class QdrantHybridSearchTests_NamedVectors(
|
||||
QdrantHybridSearchTests_NamedVectors.VectorAndStringFixture vectorAndStringFixture,
|
||||
QdrantHybridSearchTests_NamedVectors.MultiTextFixture multiTextFixture)
|
||||
: HybridSearchTests<ulong>(vectorAndStringFixture, multiTextFixture),
|
||||
IClassFixture<QdrantHybridSearchTests_NamedVectors.VectorAndStringFixture>,
|
||||
IClassFixture<QdrantHybridSearchTests_NamedVectors.MultiTextFixture>
|
||||
{
|
||||
public new class VectorAndStringFixture : HybridSearchTests<ulong>.VectorAndStringFixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
|
||||
public new class MultiTextFixture : HybridSearchTests<ulong>.MultiTextFixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public class QdrantHybridSearchTests_UnnamedVectors(
|
||||
QdrantHybridSearchTests_UnnamedVectors.VectorAndStringFixture vectorAndStringFixture,
|
||||
QdrantHybridSearchTests_UnnamedVectors.MultiTextFixture multiTextFixture)
|
||||
: HybridSearchTests<ulong>(vectorAndStringFixture, multiTextFixture),
|
||||
IClassFixture<QdrantHybridSearchTests_UnnamedVectors.VectorAndStringFixture>,
|
||||
IClassFixture<QdrantHybridSearchTests_UnnamedVectors.MultiTextFixture>
|
||||
{
|
||||
public new class VectorAndStringFixture : HybridSearchTests<ulong>.VectorAndStringFixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.UnnamedVectorInstance;
|
||||
}
|
||||
|
||||
public new class MultiTextFixture : HybridSearchTests<ulong>.MultiTextFixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.UnnamedVectorInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests;
|
||||
|
||||
public class QdrantIndexKindTests(QdrantIndexKindTests.Fixture fixture)
|
||||
: IndexKindTests<ulong>(fixture), IClassFixture<QdrantIndexKindTests.Fixture>
|
||||
{
|
||||
// Qdrant does not support index-less searching
|
||||
public override Task Flat() => Assert.ThrowsAsync<NotSupportedException>(base.Flat);
|
||||
|
||||
[ConditionalFact]
|
||||
public virtual Task Hnsw()
|
||||
=> this.Test(IndexKind.Hnsw);
|
||||
|
||||
public new class Fixture() : IndexKindTests<ulong>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using VectorData.ConformanceTests;
|
||||
|
||||
namespace Qdrant.ConformanceTests;
|
||||
|
||||
public class QdrantTestSuiteImplementationTests : TestSuiteImplementationTests;
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using VectorData.ConformanceTests.Support;
|
||||
|
||||
namespace Qdrant.ConformanceTests.Support;
|
||||
|
||||
public class QdrantNamedVectorsFixture : VectorStoreFixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel.Connectors.Qdrant;
|
||||
using Qdrant.Client;
|
||||
using Testcontainers.Qdrant;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
|
||||
namespace Qdrant.ConformanceTests.Support;
|
||||
|
||||
#pragma warning disable CA1001 // Type owns disposable fields but is not disposable
|
||||
|
||||
internal sealed class QdrantTestStore : TestStore
|
||||
{
|
||||
public static QdrantTestStore NamedVectorsInstance { get; } = new(hasNamedVectors: true);
|
||||
public static QdrantTestStore UnnamedVectorInstance { get; } = new(hasNamedVectors: false);
|
||||
|
||||
// Qdrant doesn't support the default Flat index kind
|
||||
public override string DefaultIndexKind => IndexKind.Hnsw;
|
||||
|
||||
private readonly QdrantContainer _container = new QdrantBuilder("qdrant/qdrant:v1.17.0").Build();
|
||||
private readonly bool _hasNamedVectors;
|
||||
private QdrantClient? _client;
|
||||
|
||||
public QdrantClient Client => this._client ?? throw new InvalidOperationException("Not initialized");
|
||||
|
||||
public QdrantVectorStore GetVectorStore(QdrantVectorStoreOptions options)
|
||||
=> new(this.Client,
|
||||
ownsClient: false, // The client is shared, it's not owned by the vector store.
|
||||
new()
|
||||
{
|
||||
HasNamedVectors = options.HasNamedVectors,
|
||||
EmbeddingGenerator = options.EmbeddingGenerator
|
||||
});
|
||||
|
||||
private QdrantTestStore(bool hasNamedVectors) => this._hasNamedVectors = hasNamedVectors;
|
||||
|
||||
/// <summary>
|
||||
/// Qdrant normalizes vectors on upsert, so we cannot compare
|
||||
/// what we upserted and what we retrieve, we can only check
|
||||
/// that a vector was returned.
|
||||
/// https://github.com/qdrant/qdrant-client/discussions/727
|
||||
/// </summary>
|
||||
public override bool VectorsComparable => false;
|
||||
|
||||
protected override async Task StartAsync()
|
||||
{
|
||||
await this._container.StartAsync();
|
||||
this._client = new QdrantClient(this._container.Hostname, this._container.GetMappedPublicPort(QdrantBuilder.QdrantGrpcPort));
|
||||
// The client is shared, it's not owned by the vector store.
|
||||
this.DefaultVectorStore = new QdrantVectorStore(this._client, ownsClient: false, new() { HasNamedVectors = this._hasNamedVectors });
|
||||
}
|
||||
|
||||
protected override async Task StopAsync()
|
||||
{
|
||||
this._client?.Dispose();
|
||||
await this._container.StopAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using VectorData.ConformanceTests.Support;
|
||||
|
||||
namespace Qdrant.ConformanceTests.Support;
|
||||
|
||||
public class QdrantUnnamedVectorFixture : VectorStoreFixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.UnnamedVectorInstance;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.TypeTests;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests.TypeTests;
|
||||
|
||||
public class QdrantDataTypeTests(QdrantDataTypeTests.Fixture fixture)
|
||||
: DataTypeTests<Guid, DataTypeTests<Guid>.DefaultRecord>(fixture), IClassFixture<QdrantDataTypeTests.Fixture>
|
||||
{
|
||||
// Qdrant doesn't seem to support filtering on float/double or string ararys,
|
||||
// https://qdrant.tech/documentation/concepts/filtering/#match
|
||||
[ConditionalFact]
|
||||
public override Task Float()
|
||||
=> this.Test<float>("Float", 8.5f, 9.5f, isFilterable: false);
|
||||
|
||||
[ConditionalFact]
|
||||
public override Task Double()
|
||||
=> this.Test<double>("Double", 8.5d, 9.5d, isFilterable: false);
|
||||
|
||||
[ConditionalFact]
|
||||
public override Task String_array()
|
||||
=> this.Test<string[]>(
|
||||
"StringArray",
|
||||
["foo", "bar"],
|
||||
["foo", "baz"],
|
||||
isFilterable: false);
|
||||
|
||||
public new class Fixture : DataTypeTests<Guid, DataTypeTests<Guid>.DefaultRecord>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.UnnamedVectorInstance;
|
||||
|
||||
public override Type[] UnsupportedDefaultTypes { get; } =
|
||||
[
|
||||
typeof(byte),
|
||||
typeof(short),
|
||||
typeof(decimal),
|
||||
typeof(Guid),
|
||||
#if NET
|
||||
typeof(TimeOnly)
|
||||
#endif
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.TypeTests;
|
||||
using Xunit;
|
||||
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
|
||||
namespace Qdrant.ConformanceTests.TypeTests;
|
||||
|
||||
public class QdrantEmbeddingTypeTests(QdrantEmbeddingTypeTests.Fixture fixture)
|
||||
: EmbeddingTypeTests<Guid>(fixture), IClassFixture<QdrantEmbeddingTypeTests.Fixture>
|
||||
{
|
||||
public new class Fixture : EmbeddingTypeTests<Guid>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Qdrant.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.TypeTests;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Qdrant.ConformanceTests.TypeTests;
|
||||
|
||||
public class QdrantKeyTypeTests(QdrantKeyTypeTests.Fixture fixture)
|
||||
: KeyTypeTests(fixture), IClassFixture<QdrantKeyTypeTests.Fixture>
|
||||
{
|
||||
[ConditionalFact]
|
||||
public virtual Task ULong() => this.Test<ulong>(8UL);
|
||||
|
||||
public new class Fixture : KeyTypeTests.Fixture
|
||||
{
|
||||
public override TestStore TestStore => QdrantTestStore.NamedVectorsInstance;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user