Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions dotnet/src/VectorData/PgVector/PostgresCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ public override async Task UpsertAsync(TRecord record, CancellationToken cancell
generatedEmbeddings[vectorProperty] = [await halfTask.ConfigureAwait(false)];
}
#endif
else if (vectorProperty.TryGenerateEmbedding<TRecord, BinaryEmbedding>(record, cancellationToken, out var binaryTask))
{
generatedEmbeddings ??= new Dictionary<VectorPropertyModel, IReadOnlyList<Embedding>>(vectorPropertyCount);
generatedEmbeddings[vectorProperty] = [await binaryTask.ConfigureAwait(false)];
}
else
{
throw new InvalidOperationException(
Expand Down Expand Up @@ -420,10 +425,9 @@ _ when vectorProperty.EmbeddingGenerator is IEmbeddingGenerator<TInput, Embeddin

// Dense Binary
BitArray b => b,
// TODO: Uncomment once we sync to the latest MEAI
// BinaryEmbedding e => e.Vector,
// _ when vectorProperty.EmbeddingGenerator is IEmbeddingGenerator<TVector, BinaryEmbedding> generator
// => (await generator.GenerateEmbeddingAsync(value, cancellationToken: cancellationToken).ConfigureAwait(false)).Vector,
BinaryEmbedding e => e.Vector,
_ when vectorProperty.EmbeddingGenerator is IEmbeddingGenerator<TInput, BinaryEmbedding> generator
=> await generator.GenerateAsync(searchValue, cancellationToken: cancellationToken).ConfigureAwait(false),

// Sparse
SparseVector sv => sv,
Expand Down
4 changes: 4 additions & 0 deletions dotnet/src/VectorData/PgVector/PostgresMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ public TRecord MapFromStorageToDataModel(NpgsqlDataReader reader, bool includeVe
}
#endif

case BitArray bitArray when vectorProperty.Type == typeof(BinaryEmbedding):
vectorProperty.SetValueAsObject(record, new BinaryEmbedding(bitArray));
continue;

case BitArray bitArray:
vectorProperty.SetValueAsObject(record, bitArray);
continue;
Expand Down
5 changes: 3 additions & 2 deletions dotnet/src/VectorData/PgVector/PostgresModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.SemanticKernel.Connectors.PgVector;

internal class PostgresModelBuilder() : CollectionModelBuilder(PostgresModelBuilder.ModelBuildingOptions)
{
internal const string SupportedVectorTypes = "ReadOnlyMemory<float>, Embedding<float>, float[], ReadOnlyMemory<Half>, Embedding<Half>, Half[], BitArray, or SparseVector";
internal const string SupportedVectorTypes = "ReadOnlyMemory<float>, Embedding<float>, float[], ReadOnlyMemory<Half>, Embedding<Half>, Half[], BinaryEmbedding, BitArray, or SparseVector";

public static readonly CollectionModelBuildingOptions ModelBuildingOptions = new()
{
Expand Down Expand Up @@ -80,6 +80,7 @@ internal static bool IsVectorPropertyTypeValidCore(Type type, [NotNullWhen(false
type == typeof(Embedding<Half>) ||
type == typeof(Half[]) ||
#endif
type == typeof(BinaryEmbedding) ||
type == typeof(BitArray) ||
type == typeof(SparseVector);
}
Expand All @@ -93,5 +94,5 @@ internal static bool IsVectorPropertyTypeValidCore(Type type, [NotNullWhen(false
#if NET8_0_OR_GREATER
?? vectorProperty.ResolveEmbeddingType<Embedding<Half>>(embeddingGenerator, userRequestedEmbeddingType)
#endif
;
?? vectorProperty.ResolveEmbeddingType<BinaryEmbedding>(embeddingGenerator, userRequestedEmbeddingType);
}
2 changes: 2 additions & 0 deletions dotnet/src/VectorData/PgVector/PostgresPropertyMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ internal static class PostgresPropertyMapping
#endif

BitArray bitArray => bitArray,
BinaryEmbedding binaryEmbedding => binaryEmbedding.Vector,
SparseVector sparseVector => sparseVector,

null => null,
Expand Down Expand Up @@ -136,6 +137,7 @@ public static (string PgType, bool IsNullable) GetPgVectorTypeName(VectorPropert

Type t when t == typeof(SparseVector) => "SPARSEVEC",
Type t when t == typeof(BitArray) => "BIT",
Type t when t == typeof(BinaryEmbedding) => "BIT",

_ => throw new NotSupportedException($"Type {vectorProperty.EmbeddingType.Name} is not supported by this store.")
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Collections;
#if NET8_0_OR_GREATER
using Microsoft.Extensions.AI;
#endif
using Microsoft.Extensions.VectorData;
using Pgvector;
using PgVector.ConformanceTests.Support;
Expand Down Expand Up @@ -41,16 +39,27 @@ public virtual Task Array_of_Half()
new ReadOnlyMemoryEmbeddingGenerator<Half>([(byte)1, (byte)2, (byte)3]));
#endif

// TODO: Figure out the embedding generation story for binaryvec/sparsevec - need an Embedding wrapper

[ConditionalFact]
public virtual Task BitArray()
=> this.Test<BitArray>(new BitArray(new bool[] { true, false, true }), distanceFunction: DistanceFunction.HammingDistance, embeddingGenerator: null);
=> this.Test<BitArray>(
new BitArray([true, false, true]),
new BinaryEmbeddingGenerator(new BitArray([true, false, true])),
distanceFunction: DistanceFunction.HammingDistance);

[ConditionalFact]
public virtual Task BinaryEmbedding()
=> this.Test<BinaryEmbedding>(
new BinaryEmbedding(new([true, false, true])),
new BinaryEmbeddingGenerator(new BitArray([true, false, true])),
distanceFunction: DistanceFunction.HammingDistance,
vectorEqualityAsserter: (e, a) => Assert.Equal(e.Vector, a.Vector));

[ConditionalFact]
public virtual Task SparseVector()
=> this.Test<SparseVector>(new SparseVector(new ReadOnlyMemory<float>([1, 2, 3])), embeddingGenerator: null);

// TODO: Figure out the embedding generation story for sparsevec - need an Embedding wrapper

public new class Fixture : EmbeddingTypeTests<int>.Fixture
{
public override TestStore TestStore => PostgresTestStore.Instance;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Collections;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.VectorData;
using VectorData.ConformanceTests.Support;
Expand Down Expand Up @@ -178,13 +179,28 @@ protected virtual async Task Test<TVector>(

protected sealed class ReadOnlyMemoryEmbeddingGenerator<T>(T[] data) : IEmbeddingGenerator<string, Embedding<T>>
{
public Task<GeneratedEmbeddings<Embedding<T>>> GenerateAsync(IEnumerable<string> values, EmbeddingGenerationOptions? options = null, CancellationToken cancellationToken = default)
public Task<GeneratedEmbeddings<Embedding<T>>> GenerateAsync(
IEnumerable<string> values,
EmbeddingGenerationOptions? options = null,
CancellationToken cancellationToken = default)
=> Task.FromResult(new GeneratedEmbeddings<Embedding<T>>([new(data)]));

public object? GetService(Type serviceType, object? serviceKey = null) => null;
public void Dispose() { }
}

protected sealed class BinaryEmbeddingGenerator(BitArray data) : IEmbeddingGenerator<string, BinaryEmbedding>
{
public Task<GeneratedEmbeddings<BinaryEmbedding>> GenerateAsync(
IEnumerable<string> values,
EmbeddingGenerationOptions? options = null,
CancellationToken cancellationToken = default)
=> Task.FromResult(new GeneratedEmbeddings<BinaryEmbedding>([new(data)]));

public object? GetService(Type serviceType, object? serviceKey = null) => null;
public void Dispose() { }
}

public class RecordWithString
{
public TKey Key { get; set; }
Expand Down
Loading