diff --git a/dotnet/samples/Concepts/Concepts.csproj b/dotnet/samples/Concepts/Concepts.csproj index 0ac3dc6a4586..808841ad2d37 100644 --- a/dotnet/samples/Concepts/Concepts.csproj +++ b/dotnet/samples/Concepts/Concepts.csproj @@ -8,7 +8,7 @@ false true - $(NoWarn);CS8618,IDE0009,IDE1006,CA1051,CA1050,CA1707,CA1054,CA2007,VSTHRD111,CS1591,RCS1110,RCS1243,CA5394,SKEXP0001,SKEXP0010,SKEXP0020,SKEXP0040,SKEXP0050,SKEXP0060,SKEXP0070,SKEXP0101,SKEXP0110,OPENAI001,CA1724 + $(NoWarn);CS8618,IDE0009,IDE1006,CA1051,CA1050,CA1707,CA1054,CA2007,VSTHRD111,CS1591,RCS1110,RCS1243,CA5394,SKEXP0001,SKEXP0010,SKEXP0020,SKEXP0040,SKEXP0050,SKEXP0060,SKEXP0070,SKEXP0101,SKEXP0110,OPENAI001,CA1724,MEVD9000 Library 5ee045b0-aea3-4f08-8d31-32d1a6f8fed0 diff --git a/dotnet/samples/Concepts/Memory/VectorStoreEmbeddingGeneration/TextEmbeddingVectorStore.cs b/dotnet/samples/Concepts/Memory/VectorStoreEmbeddingGeneration/TextEmbeddingVectorStore.cs index 6848b38af48f..4fd62592adf3 100644 --- a/dotnet/samples/Concepts/Memory/VectorStoreEmbeddingGeneration/TextEmbeddingVectorStore.cs +++ b/dotnet/samples/Concepts/Memory/VectorStoreEmbeddingGeneration/TextEmbeddingVectorStore.cs @@ -40,6 +40,16 @@ public IVectorStoreRecordCollection GetCollection( return embeddingStore; } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + ArgumentNullException.ThrowIfNull(serviceType); + + return + serviceKey is null && serviceType.IsInstanceOfType(this) ? this : + this._decoratedVectorStore.GetService(serviceType, serviceKey); + } + /// public IAsyncEnumerable ListCollectionNamesAsync(CancellationToken cancellationToken = default) { diff --git a/dotnet/samples/Concepts/Memory/VectorStoreEmbeddingGeneration/TextEmbeddingVectorStoreRecordCollection.cs b/dotnet/samples/Concepts/Memory/VectorStoreEmbeddingGeneration/TextEmbeddingVectorStoreRecordCollection.cs index 9702e938b2d9..8e53b42711af 100644 --- a/dotnet/samples/Concepts/Memory/VectorStoreEmbeddingGeneration/TextEmbeddingVectorStoreRecordCollection.cs +++ b/dotnet/samples/Concepts/Memory/VectorStoreEmbeddingGeneration/TextEmbeddingVectorStoreRecordCollection.cs @@ -132,6 +132,16 @@ public async Task> VectorizableTextSearchAsync(stri return await this.VectorizedSearchAsync(embeddingValue, top, options, cancellationToken).ConfigureAwait(false); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + ArgumentNullException.ThrowIfNull(serviceType); + + return + serviceKey is null && serviceType.IsInstanceOfType(this) ? this : + this._decoratedVectorStoreRecordCollection.GetService(serviceType, serviceKey); + } + /// /// Generate and add embeddings for each embedding field that has a on the provided record. /// diff --git a/dotnet/samples/Concepts/Search/VectorStore_TextSearch.cs b/dotnet/samples/Concepts/Search/VectorStore_TextSearch.cs index f5d39c702790..490a379c5cd8 100644 --- a/dotnet/samples/Concepts/Search/VectorStore_TextSearch.cs +++ b/dotnet/samples/Concepts/Search/VectorStore_TextSearch.cs @@ -150,6 +150,16 @@ public async Task> VectorizableTextSearchAsync(stri return await vectorizedSearch.VectorizedSearchAsync(vectorizedQuery, top, options, cancellationToken); } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + ArgumentNullException.ThrowIfNull(serviceType); + + return + serviceKey is null && serviceType.IsInstanceOfType(this) ? this : + vectorizedSearch.GetService(serviceType, serviceKey); + } } /// diff --git a/dotnet/src/Connectors/Connectors.AzureAISearch.UnitTests/AzureAISearchVectorStoreRecordCollectionTests.cs b/dotnet/src/Connectors/Connectors.AzureAISearch.UnitTests/AzureAISearchVectorStoreRecordCollectionTests.cs index e9be1d92180c..9cdc26661a0c 100644 --- a/dotnet/src/Connectors/Connectors.AzureAISearch.UnitTests/AzureAISearchVectorStoreRecordCollectionTests.cs +++ b/dotnet/src/Connectors/Connectors.AzureAISearch.UnitTests/AzureAISearchVectorStoreRecordCollectionTests.cs @@ -41,6 +41,7 @@ public AzureAISearchVectorStoreRecordCollectionTests() this._searchClientMock = new Mock(MockBehavior.Strict); this._searchIndexClientMock = new Mock(MockBehavior.Strict); this._searchIndexClientMock.Setup(x => x.GetSearchClient(TestCollectionName)).Returns(this._searchClientMock.Object); + this._searchIndexClientMock.Setup(x => x.ServiceName).Returns("TestService"); } [Theory] diff --git a/dotnet/src/Connectors/Connectors.AzureAISearch.UnitTests/AzureAISearchVectorStoreTests.cs b/dotnet/src/Connectors/Connectors.AzureAISearch.UnitTests/AzureAISearchVectorStoreTests.cs index b79b048a5f38..f4eed15172fb 100644 --- a/dotnet/src/Connectors/Connectors.AzureAISearch.UnitTests/AzureAISearchVectorStoreTests.cs +++ b/dotnet/src/Connectors/Connectors.AzureAISearch.UnitTests/AzureAISearchVectorStoreTests.cs @@ -32,6 +32,7 @@ public AzureAISearchVectorStoreTests() this._searchClientMock = new Mock(MockBehavior.Strict); this._searchIndexClientMock = new Mock(MockBehavior.Strict); this._searchIndexClientMock.Setup(x => x.GetSearchClient(TestCollectionName)).Returns(this._searchClientMock.Object); + this._searchIndexClientMock.Setup(x => x.ServiceName).Returns("TestService"); } [Fact] diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchConstants.cs b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchConstants.cs index 75ceb3b8a632..0ae13cf923ab 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchConstants.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchConstants.cs @@ -8,6 +8,8 @@ namespace Microsoft.SemanticKernel.Connectors.AzureAISearch; internal static class AzureAISearchConstants { + internal const string VectorStoreSystemName = "azure.aisearch"; + /// A set of types that a key on the provided model may have. private static readonly HashSet s_supportedKeyTypes = [typeof(string)]; diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStore.cs index 409c36d1e05a..b270d699b6ec 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStore.cs @@ -19,8 +19,8 @@ namespace Microsoft.SemanticKernel.Connectors.AzureAISearch; /// public class AzureAISearchVectorStore : IVectorStore { - /// The name of this database for telemetry purposes. - private const string DatabaseName = "AzureAISearch"; + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; /// Azure AI Search client that can be used to manage the list of indices in an Azure AI Search Service. private readonly SearchIndexClient _searchIndexClient; @@ -39,6 +39,12 @@ public AzureAISearchVectorStore(SearchIndexClient searchIndexClient, AzureAISear this._searchIndexClient = searchIndexClient; this._options = options ?? new AzureAISearchVectorStoreOptions(); + + this._metadata = new() + { + VectorStoreSystemName = AzureAISearchConstants.VectorStoreSystemName, + VectorStoreName = searchIndexClient.ServiceName + }; } /// @@ -83,6 +89,19 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat } } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(SearchIndexClient) ? this._searchIndexClient : + serviceType.IsInstanceOfType(this) ? this : + null; + } + /// /// Helper method to get the next index name from the enumerator with a try catch around the move next call to convert /// any to , since try catch is not supported @@ -90,7 +109,8 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat /// /// The enumerator to get the next result from. /// A value indicating whether there are more results and the current string if true. - private static async Task<(string name, bool more)> GetNextIndexNameAsync(ConfiguredCancelableAsyncEnumerable.Enumerator enumerator) + private static async Task<(string name, bool more)> GetNextIndexNameAsync( + ConfiguredCancelableAsyncEnumerable.Enumerator enumerator) { const string OperationName = "GetIndexNames"; @@ -103,7 +123,7 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = AzureAISearchConstants.VectorStoreSystemName, OperationName = OperationName }; } @@ -111,7 +131,7 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = AzureAISearchConstants.VectorStoreSystemName, OperationName = OperationName }; } diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreRecordCollection.cs index 5d9b8ddc9269..daed4951624a 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreRecordCollection.cs @@ -30,8 +30,8 @@ public class AzureAISearchVectorStoreRecordCollection : IKeywordHybridSearch #pragma warning restore CA1711 // Identifiers should not have incorrect suffix { - /// The name of this database for telemetry purposes. - private const string DatabaseName = "AzureAISearch"; + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; /// The default options for vector search. private static readonly VectorSearchOptions s_defaultVectorSearchOptions = new(); @@ -95,7 +95,13 @@ public AzureAISearchVectorStoreRecordCollection(SearchIndexClient searchIndexCli { this._mapper = new AzureAISearchGenericDataModelMapper(this._model) as IVectorStoreRecordMapper; } -#pragma warning restore CS0618 + + this._collectionMetadata = new() + { + VectorStoreSystemName = AzureAISearchConstants.VectorStoreSystemName, + VectorStoreName = searchIndexClient.ServiceName, + CollectionName = collectionName + }; } /// @@ -117,7 +123,7 @@ public virtual async Task CollectionExistsAsync(CancellationToken cancella { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = AzureAISearchConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = "GetIndex" }; @@ -462,6 +468,20 @@ public Task> HybridSearchAsync(TVector vec return this.SearchAndMapToDataModelAsync(keywordsCombined, searchOptions, internalOptions.IncludeVectors, cancellationToken); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(SearchIndexClient) ? this._searchIndexClient : + serviceType == typeof(SearchClient) ? this._searchClient : + serviceType.IsInstanceOfType(this) ? this : + null; + } + /// /// Get the document with the given key and map it to the data model using the configured mapper type. /// @@ -491,7 +511,7 @@ public Task> HybridSearchAsync(TVector vec } return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureAISearchConstants.VectorStoreSystemName, this._collectionName, OperationName, () => this._mapper!.MapFromStorageToDataModel(jsonObject, new() { IncludeVectors = includeVectors })); @@ -554,7 +574,7 @@ private Task> MapToStorageModelAndUploadDocumentA if (this._mapper is not null) { var jsonObjects = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureAISearchConstants.VectorStoreSystemName!, this._collectionName, OperationName, () => records.Select(this._mapper!.MapFromDataToStorageModel)); @@ -582,7 +602,7 @@ private async IAsyncEnumerable> MapSearchResultsAsyn await foreach (var result in results.ConfigureAwait(false)) { var document = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureAISearchConstants.VectorStoreSystemName, this._collectionName, operationName, () => this._mapper!.MapFromStorageToDataModel(result.Document, new() { IncludeVectors = includeVectors })); @@ -666,7 +686,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = AzureAISearchConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = operationName }; @@ -675,7 +695,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = AzureAISearchConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBConstants.cs b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBConstants.cs new file mode 100644 index 000000000000..b6a003c3e548 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBConstants.cs @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.SemanticKernel.Connectors.AzureCosmosDBMongoDB; + +internal static class AzureCosmosDBMongoDBConstants +{ + public const string VectorStoreSystemName = "azure.cosmosdbmongodb"; +} diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBVectorStore.cs index 76dc9e8500a4..7a94c003a28c 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBVectorStore.cs @@ -17,6 +17,9 @@ namespace Microsoft.SemanticKernel.Connectors.AzureCosmosDBMongoDB; /// public class AzureCosmosDBMongoDBVectorStore : IVectorStore { + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; + /// that can be used to manage the collections in Azure CosmosDB MongoDB. private readonly IMongoDatabase _mongoDatabase; @@ -34,6 +37,12 @@ public AzureCosmosDBMongoDBVectorStore(IMongoDatabase mongoDatabase, AzureCosmos this._mongoDatabase = mongoDatabase; this._options = options ?? new(); + + this._metadata = new() + { + VectorStoreSystemName = AzureCosmosDBMongoDBConstants.VectorStoreSystemName, + VectorStoreName = mongoDatabase.DatabaseNamespace?.DatabaseName + }; } /// @@ -75,4 +84,17 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat } } } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(IMongoDatabase) ? this._mongoDatabase : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBVectorStoreRecordCollection.cs index 1bf8c8b9110b..2a48e74ecea3 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBMongoDB/AzureCosmosDBMongoDBVectorStoreRecordCollection.cs @@ -26,8 +26,8 @@ namespace Microsoft.SemanticKernel.Connectors.AzureCosmosDBMongoDB; public class AzureCosmosDBMongoDBVectorStoreRecordCollection : IVectorStoreRecordCollection #pragma warning restore CA1711 // Identifiers should not have incorrect suffix { - /// The name of this database for telemetry purposes. - private const string DatabaseName = "AzureCosmosDBMongoDB"; + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; /// Property name to be used for search similarity score value. private const string ScorePropertyName = "similarityScore"; @@ -80,6 +80,13 @@ public AzureCosmosDBMongoDBVectorStoreRecordCollection( this._options = options ?? new AzureCosmosDBMongoDBVectorStoreRecordCollectionOptions(); this._model = new MongoDBModelBuilder().Build(typeof(TRecord), this._options.VectorStoreRecordDefinition); this._mapper = this.InitializeMapper(); + + this._collectionMetadata = new() + { + VectorStoreSystemName = AzureCosmosDBMongoDBConstants.VectorStoreSystemName, + VectorStoreName = mongoDatabase.DatabaseNamespace?.DatabaseName, + CollectionName = collectionName + }; } /// @@ -95,7 +102,7 @@ public virtual async Task CreateCollectionAsync(CancellationToken cancellationTo { throw new VectorStoreOperationException("Collection already exists.") { - VectorStoreType = DatabaseName, + VectorStoreType = AzureCosmosDBMongoDBConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = "CreateCollection" }; @@ -160,7 +167,7 @@ public virtual Task DeleteCollectionAsync(CancellationToken cancellationToken = } return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureCosmosDBMongoDBConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(record, new() { IncludeVectors = includeVectors })); @@ -187,7 +194,7 @@ public virtual async IAsyncEnumerable GetAsync( if (record is not null) { yield return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureCosmosDBMongoDBConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(record, new())); @@ -205,7 +212,7 @@ public virtual Task UpsertAsync(TRecord record, CancellationToken cancel var replaceOptions = new ReplaceOptions { IsUpsert = true }; var storageModel = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureCosmosDBMongoDBConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromDataToStorageModel(record)); @@ -310,6 +317,20 @@ public virtual async Task> VectorizedSearchAsync(this.EnumerateAndMapSearchResultsAsync(cursor, searchOptions, cancellationToken)); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(IMongoDatabase) ? this._mongoDatabase : + serviceType == typeof(IMongoCollection) ? this._mongoCollection : + serviceType.IsInstanceOfType(this) ? this : + null; + } + #region private private async Task CreateIndexesAsync(string collectionName, CancellationToken cancellationToken) @@ -383,7 +404,7 @@ private async IAsyncEnumerable> EnumerateAndMapSearc { var score = response[ScorePropertyName].AsDouble; var record = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureCosmosDBMongoDBConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(response[DocumentPropertyName].AsBsonDocument, new())); @@ -422,7 +443,7 @@ private async Task RunOperationAsync(string operationName, Func operation) { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = AzureCosmosDBMongoDBConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; @@ -439,7 +460,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = AzureCosmosDBMongoDBConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLConstants.cs b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLConstants.cs index 6dbb0d440b45..f667488e7fd9 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLConstants.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLConstants.cs @@ -4,6 +4,8 @@ namespace Microsoft.SemanticKernel.Connectors.AzureCosmosDBNoSQL; internal static class AzureCosmosDBNoSQLConstants { + internal const string VectorStoreSystemName = "azure.cosmosdbnosql"; + /// /// Reserved key property name in Azure CosmosDB NoSQL. /// diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLVectorStore.cs index 39320e0a8ae2..0f1cc01c4b29 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLVectorStore.cs @@ -17,6 +17,9 @@ namespace Microsoft.SemanticKernel.Connectors.AzureCosmosDBNoSQL; /// public class AzureCosmosDBNoSQLVectorStore : IVectorStore { + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; + /// that can be used to manage the collections in Azure CosmosDB NoSQL. private readonly Database _database; @@ -34,6 +37,12 @@ public AzureCosmosDBNoSQLVectorStore(Database database, AzureCosmosDBNoSQLVector this._database = database; this._options = options ?? new(); + + this._metadata = new() + { + VectorStoreSystemName = AzureCosmosDBNoSQLConstants.VectorStoreSystemName, + VectorStoreName = database.Id + }; } /// @@ -84,4 +93,17 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat } } } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(Database) ? this._database : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLVectorStoreRecordCollection.cs index 9a490a032060..d1941dc52129 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureCosmosDBNoSQL/AzureCosmosDBNoSQLVectorStoreRecordCollection.cs @@ -29,8 +29,8 @@ public class AzureCosmosDBNoSQLVectorStoreRecordCollection : IKeywordHybridSearch #pragma warning restore CA1711 // Identifiers should not have incorrect { - /// The name of this database for telemetry purposes. - private const string DatabaseName = "AzureCosmosDBNoSQL"; + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; /// The default options for vector search. private static readonly VectorSearchOptions s_defaultVectorSearchOptions = new(); @@ -105,6 +105,13 @@ public AzureCosmosDBNoSQLVectorStoreRecordCollection( // If partition key is not provided, use key property as a partition key. this._partitionKeyProperty = this._model.KeyProperty; } + + this._collectionMetadata = new() + { + VectorStoreSystemName = AzureCosmosDBNoSQLConstants.VectorStoreSystemName, + VectorStoreName = database.Id, + CollectionName = collectionName + }; } /// @@ -378,6 +385,19 @@ public Task> HybridSearchAsync(TVector vec #endregion + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(Database) ? this._database : + serviceType.IsInstanceOfType(this) ? this : + null; + } + #region private private void VerifyVectorType(TVector? vector) @@ -404,7 +424,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = AzureCosmosDBNoSQLConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; @@ -564,7 +584,7 @@ private async IAsyncEnumerable InternalGetAsync( await foreach (var jsonObject in this.GetItemsAsync(queryDefinition, cancellationToken).ConfigureAwait(false)) { yield return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureCosmosDBNoSQLConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(jsonObject, new() { IncludeVectors = includeVectors })); @@ -580,7 +600,7 @@ private async Task InternalUpsertAsync( const string OperationName = "UpsertItem"; var jsonObject = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureCosmosDBNoSQLConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromDataToStorageModel(record)); @@ -660,7 +680,7 @@ private async IAsyncEnumerable> MapSearchResultsAsyn jsonObject.Remove(scorePropertyName); var record = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + AzureCosmosDBNoSQLConstants.VectorStoreSystemName, this.CollectionName, operationName, () => this._mapper.MapFromStorageToDataModel(jsonObject, new() { IncludeVectors = includeVectors })); diff --git a/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryConstants.cs b/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryConstants.cs new file mode 100644 index 000000000000..af318ef12622 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryConstants.cs @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.SemanticKernel.Connectors.InMemory; + +internal static class InMemoryConstants +{ + internal const string VectorStoreSystemName = "inmemory"; +} diff --git a/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryVectorStore.cs index 2db7013b0d27..3710cfea1dcd 100644 --- a/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryVectorStore.cs @@ -14,6 +14,9 @@ namespace Microsoft.SemanticKernel.Connectors.InMemory; /// public sealed class InMemoryVectorStore : IVectorStore { + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; + /// Internal storage for the record collection. private readonly ConcurrentDictionary> _internalCollection; @@ -26,6 +29,11 @@ public sealed class InMemoryVectorStore : IVectorStore public InMemoryVectorStore() { this._internalCollection = new(); + + this._metadata = new() + { + VectorStoreSystemName = InMemoryConstants.VectorStoreSystemName, + }; } /// @@ -35,6 +43,11 @@ public InMemoryVectorStore() internal InMemoryVectorStore(ConcurrentDictionary> internalCollection) { this._internalCollection = internalCollection; + + this._metadata = new() + { + VectorStoreSystemName = InMemoryConstants.VectorStoreSystemName + }; } /// @@ -59,4 +72,17 @@ public IAsyncEnumerable ListCollectionNamesAsync(CancellationToken cance { return this._internalCollection.Keys.ToAsyncEnumerable(); } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(ConcurrentDictionary>) ? this._internalCollection : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryVectorStoreRecordCollection.cs index a59501d662b1..0608ae865587 100644 --- a/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.InMemory/InMemoryVectorStoreRecordCollection.cs @@ -23,6 +23,9 @@ public sealed class InMemoryVectorStoreRecordCollection : IVector #pragma warning restore CA1711 // Identifiers should not have incorrect suffix where TKey : notnull { + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; + /// The default options for vector search. private static readonly VectorSearchOptions s_defaultVectorSearchOptions = new(); @@ -103,6 +106,12 @@ public InMemoryVectorStoreRecordCollection(string collectionName, InMemoryVector return property.GetValueAsObject(record!); }; #pragma warning restore MEVD9000 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + + this._collectionMetadata = new() + { + VectorStoreSystemName = InMemoryConstants.VectorStoreSystemName, + CollectionName = collectionName + }; } /// @@ -144,7 +153,7 @@ public Task CreateCollectionAsync(CancellationToken cancellationToken = default) return Task.FromException(new VectorStoreOperationException("Collection already exists.") { - VectorStoreType = "InMemory", + VectorStoreType = InMemoryConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = "CreateCollection" }); @@ -302,6 +311,19 @@ public async Task> VectorizedSearchAsync(T return new VectorSearchResults(vectorSearchResultList) { TotalCount = count }; } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(ConcurrentDictionary>) ? this._internalCollections : + serviceType.IsInstanceOfType(this) ? this : + null; + } + /// /// Get the collection dictionary from the internal storage, throws if it does not exist. /// diff --git a/dotnet/src/Connectors/Connectors.Memory.MongoDB/MongoDBVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.MongoDB/MongoDBVectorStore.cs index 27169e3e9557..47f79724b382 100644 --- a/dotnet/src/Connectors/Connectors.Memory.MongoDB/MongoDBVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.MongoDB/MongoDBVectorStore.cs @@ -17,6 +17,9 @@ namespace Microsoft.SemanticKernel.Connectors.MongoDB; /// public class MongoDBVectorStore : IVectorStore { + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; + /// that can be used to manage the collections in MongoDB. private readonly IMongoDatabase _mongoDatabase; @@ -34,6 +37,12 @@ public MongoDBVectorStore(IMongoDatabase mongoDatabase, MongoDBVectorStoreOption this._mongoDatabase = mongoDatabase; this._options = options ?? new(); + + this._metadata = new() + { + VectorStoreSystemName = MongoDBConstants.VectorStoreSystemName, + VectorStoreName = mongoDatabase.DatabaseNamespace?.DatabaseName + }; } /// @@ -75,4 +84,17 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat } } } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(IMongoDatabase) ? this._mongoDatabase : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.MongoDB/MongoDBVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.MongoDB/MongoDBVectorStoreRecordCollection.cs index 48f629f8aa64..8652fb70ebfc 100644 --- a/dotnet/src/Connectors/Connectors.Memory.MongoDB/MongoDBVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.MongoDB/MongoDBVectorStoreRecordCollection.cs @@ -23,8 +23,8 @@ namespace Microsoft.SemanticKernel.Connectors.MongoDB; public class MongoDBVectorStoreRecordCollection : IVectorStoreRecordCollection, IKeywordHybridSearch #pragma warning restore CA1711 // Identifiers should not have incorrect suffix { - /// The name of this database for telemetry purposes. - private const string DatabaseName = "MongoDB"; + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; /// Property name to be used for search similarity score value. private const string ScorePropertyName = "similarityScore"; @@ -80,6 +80,13 @@ public MongoDBVectorStoreRecordCollection( this._options = options ?? new MongoDBVectorStoreRecordCollectionOptions(); this._model = new MongoDBModelBuilder().Build(typeof(TRecord), this._options.VectorStoreRecordDefinition); this._mapper = this.InitializeMapper(); + + this._collectionMetadata = new() + { + VectorStoreSystemName = MongoDBConstants.VectorStoreSystemName, + VectorStoreName = mongoDatabase.DatabaseNamespace?.DatabaseName, + CollectionName = collectionName + }; } /// @@ -95,7 +102,7 @@ public virtual async Task CreateCollectionAsync(CancellationToken cancellationTo { throw new VectorStoreOperationException("Collection already exists.") { - VectorStoreType = DatabaseName, + VectorStoreType = MongoDBConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = "CreateCollection" }; @@ -166,7 +173,7 @@ public virtual Task DeleteCollectionAsync(CancellationToken cancellationToken = } return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + MongoDBConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(record, new() { IncludeVectors = includeVectors })); @@ -193,7 +200,7 @@ public virtual async IAsyncEnumerable GetAsync( if (record is not null) { yield return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + MongoDBConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(record, new())); @@ -211,7 +218,7 @@ public virtual Task UpsertAsync(TRecord record, CancellationToken cancel var replaceOptions = new ReplaceOptions { IsUpsert = true }; var storageModel = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + MongoDBConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromDataToStorageModel(record)); @@ -358,6 +365,20 @@ public async Task> HybridSearchAsync(TVect cancellationToken).ConfigureAwait(false); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(IMongoDatabase) ? this._mongoDatabase : + serviceType == typeof(IMongoCollection) ? this._mongoCollection : + serviceType.IsInstanceOfType(this) ? this : + null; + } + #region private private async Task CreateIndexesAsync(string collectionName, CancellationToken cancellationToken) @@ -468,7 +489,7 @@ private async IAsyncEnumerable> EnumerateAndMapSearc { var score = response[ScorePropertyName].AsDouble; var record = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + MongoDBConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(response[DocumentPropertyName].AsBsonDocument, new() { IncludeVectors = includeVectors })); @@ -507,7 +528,7 @@ private async Task RunOperationAsync(string operationName, Func operation) { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = MongoDBConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; @@ -524,7 +545,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = MongoDBConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; @@ -555,7 +576,7 @@ private async Task RunOperationWithRetryAsync( { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = MongoDBConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; @@ -589,7 +610,7 @@ private async Task RunOperationWithRetryAsync( { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = MongoDBConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeConstants.cs b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeConstants.cs new file mode 100644 index 000000000000..a8b4cfadfed2 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeConstants.cs @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.SemanticKernel.Connectors.Pinecone; + +internal static class PineconeConstants +{ + internal const string VectorStoreSystemName = "pinecone"; +} diff --git a/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeVectorStore.cs index a072ea6e7336..7e8da0194443 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeVectorStore.cs @@ -18,11 +18,12 @@ namespace Microsoft.SemanticKernel.Connectors.Pinecone; /// public class PineconeVectorStore : IVectorStore { - private const string DatabaseName = "Pinecone"; - private readonly Sdk.PineconeClient _pineconeClient; private readonly PineconeVectorStoreOptions _options; + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; + /// /// Initializes a new instance of the class. /// @@ -34,6 +35,11 @@ public PineconeVectorStore(Sdk.PineconeClient pineconeClient, PineconeVectorStor this._pineconeClient = pineconeClient; this._options = options ?? new PineconeVectorStoreOptions(); + + this._metadata = new() + { + VectorStoreSystemName = PineconeConstants.VectorStoreSystemName + }; } /// @@ -71,7 +77,7 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = PineconeConstants.VectorStoreSystemName, OperationName = "ListCollections" }; } @@ -84,4 +90,17 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat } } } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(Sdk.PineconeClient) ? this._pineconeClient : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeVectorStoreRecordCollection.cs index 43c744d1d47d..201bf69cb3fe 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeVectorStoreRecordCollection.cs @@ -22,10 +22,11 @@ namespace Microsoft.SemanticKernel.Connectors.Pinecone; public class PineconeVectorStoreRecordCollection : IVectorStoreRecordCollection #pragma warning restore CA1711 // Identifiers should not have incorrect suffix { - private const string DatabaseName = "Pinecone"; - private static readonly VectorSearchOptions s_defaultVectorSearchOptions = new(); + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; + private readonly Sdk.PineconeClient _pineconeClient; private readonly PineconeVectorStoreRecordCollectionOptions _options; private readonly VectorStoreRecordModel _model; @@ -59,6 +60,12 @@ public PineconeVectorStoreRecordCollection(Sdk.PineconeClient pineconeClient, st #pragma warning disable CS0618 // IVectorStoreRecordMapper is obsolete this._mapper = this._options.VectorCustomMapper ?? new PineconeVectorStoreRecordMapper(this._model); #pragma warning restore CS0618 + + this._collectionMetadata = new() + { + VectorStoreSystemName = PineconeConstants.VectorStoreSystemName, + CollectionName = collectionName + }; } /// @@ -134,7 +141,7 @@ public virtual async Task DeleteCollectionAsync(CancellationToken cancellationTo { throw new VectorStoreOperationException("Call to vector store failed.", other) { - VectorStoreType = DatabaseName, + VectorStoreType = PineconeConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = "DeleteCollection" }; @@ -164,7 +171,7 @@ public virtual async Task DeleteCollectionAsync(CancellationToken cancellationTo StorageToDataModelMapperOptions mapperOptions = new() { IncludeVectors = options?.IncludeVectors is true }; return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + PineconeConstants.VectorStoreSystemName, this.CollectionName, "Get", () => this._mapper.MapFromStorageToDataModel(result, mapperOptions)); @@ -200,7 +207,7 @@ public virtual async IAsyncEnumerable GetAsync( StorageToDataModelMapperOptions mapperOptions = new() { IncludeVectors = options?.IncludeVectors is true }; var records = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + PineconeConstants.VectorStoreSystemName, this.CollectionName, "GetBatch", () => response.Vectors.Values.Select(x => this._mapper.MapFromStorageToDataModel(x, mapperOptions))); @@ -255,7 +262,7 @@ public virtual async Task UpsertAsync(TRecord record, CancellationToken Verify.NotNull(record); var vector = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + PineconeConstants.VectorStoreSystemName, this.CollectionName, "Upsert", () => this._mapper.MapFromDataToStorageModel(record)); @@ -279,7 +286,7 @@ public virtual async IAsyncEnumerable UpsertAsync(IEnumerable r Verify.NotNull(records); var vectors = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + PineconeConstants.VectorStoreSystemName, this.CollectionName, "UpsertBatch", () => records.Select(this._mapper.MapFromDataToStorageModel).ToList()); @@ -354,7 +361,7 @@ public virtual async Task> VectorizedSearchAsync skippedResults.Select(x => new VectorSearchResult(this._mapper.MapFromStorageToDataModel(new Sdk.Vector() @@ -369,6 +376,19 @@ public virtual async Task> VectorizedSearchAsync + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(Sdk.PineconeClient) ? this._pineconeClient : + serviceType.IsInstanceOfType(this) ? this : + null; + } + private async Task RunIndexOperationAsync(string operationName, Func> operation) { try @@ -387,7 +407,7 @@ private async Task RunIndexOperationAsync(string operationName, Func RunCollectionOperationAsync(string operationName, Func< { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = PineconeConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.Postgres/IPostgresVectorStoreDbClient.cs b/dotnet/src/Connectors/Connectors.Memory.Postgres/IPostgresVectorStoreDbClient.cs index 20adedde23af..9b3ff9273182 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Postgres/IPostgresVectorStoreDbClient.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Postgres/IPostgresVectorStoreDbClient.cs @@ -22,6 +22,11 @@ internal interface IPostgresVectorStoreDbClient /// NpgsqlDataSource DataSource { get; } + /// + /// The name of the database. + /// + string? DatabaseName { get; } + /// /// Check if a table exists. /// diff --git a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresConstants.cs b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresConstants.cs index f7d490503b43..21e0f003d4eb 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresConstants.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresConstants.cs @@ -9,8 +9,8 @@ namespace Microsoft.SemanticKernel.Connectors.Postgres; internal static class PostgresConstants { - /// The name of this database for telemetry purposes. - public const string DatabaseName = "Postgres"; + /// The name of this vector store for telemetry purposes. + public const string VectorStoreSystemName = "postgresql"; /// Validation options. public static readonly VectorStoreRecordModelBuildingOptions ModelBuildingOptions = new() diff --git a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStore.cs index a1840384be84..933f61173ebe 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStore.cs @@ -17,6 +17,9 @@ public class PostgresVectorStore : IVectorStore private readonly NpgsqlDataSource? _dataSource; private readonly PostgresVectorStoreOptions _options; + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; + /// /// Initializes a new instance of the class. /// @@ -27,6 +30,12 @@ public PostgresVectorStore(NpgsqlDataSource dataSource, PostgresVectorStoreOptio this._dataSource = dataSource; this._options = options ?? new PostgresVectorStoreOptions(); this._postgresClient = new PostgresVectorStoreDbClient(this._dataSource, this._options.Schema); + + this._metadata = new() + { + VectorStoreSystemName = PostgresConstants.VectorStoreSystemName, + VectorStoreName = this._postgresClient.DatabaseName + }; } /// @@ -38,15 +47,20 @@ internal PostgresVectorStore(IPostgresVectorStoreDbClient postgresDbClient, Post { this._postgresClient = postgresDbClient; this._options = options ?? new PostgresVectorStoreOptions(); + + this._metadata = new() + { + VectorStoreSystemName = PostgresConstants.VectorStoreSystemName, + VectorStoreName = this._postgresClient.DatabaseName + }; } /// public virtual IAsyncEnumerable ListCollectionNamesAsync(CancellationToken cancellationToken = default) { - const string OperationName = "ListCollectionNames"; return PostgresVectorStoreUtils.WrapAsyncEnumerableAsync( this._postgresClient.GetTablesAsync(cancellationToken), - OperationName + "ListCollectionNames" ); } @@ -69,4 +83,17 @@ public virtual IVectorStoreRecordCollection GetCollection ?? throw new InvalidOperationException("Failed to cast record collection."); } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(NpgsqlDataSource) ? this._dataSource : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreDbClient.cs b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreDbClient.cs index fc097e848881..178f60589503 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreDbClient.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreDbClient.cs @@ -27,10 +27,14 @@ internal class PostgresVectorStoreDbClient(NpgsqlDataSource dataSource, string s { private readonly string _schema = schema; + private readonly NpgsqlConnectionStringBuilder _connectionStringBuilder = new(dataSource.ConnectionString); + private IPostgresVectorStoreCollectionSqlBuilder _sqlBuilder = new PostgresVectorStoreCollectionSqlBuilder(); public NpgsqlDataSource DataSource { get; } = dataSource; + public string? DatabaseName => this._connectionStringBuilder.Database; + /// public async Task DoesTableExistsAsync(string tableName, CancellationToken cancellationToken = default) { diff --git a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreRecordCollection.cs index eb9eae628b67..e9b5be465ae8 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreRecordCollection.cs @@ -25,6 +25,9 @@ public class PostgresVectorStoreRecordCollection : IVectorStoreRe /// public string CollectionName { get; } + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; + /// Postgres client that is used to interact with the database. private readonly IPostgresVectorStoreDbClient _client; @@ -79,6 +82,13 @@ internal PostgresVectorStoreRecordCollection(IPostgresVectorStoreDbClient client #pragma warning disable CS0618 // IVectorStoreRecordMapper is obsolete this._mapper = this._options.DictionaryCustomMapper ?? new PostgresVectorStoreRecordMapper(this._model); #pragma warning restore CS0618 + + this._collectionMetadata = new() + { + VectorStoreSystemName = PostgresConstants.VectorStoreSystemName, + VectorStoreName = this._client.DatabaseName, + CollectionName = collectionName + }; } /// @@ -123,7 +133,7 @@ public virtual Task UpsertAsync(TRecord record, CancellationToken cancella const string OperationName = "Upsert"; var storageModel = VectorStoreErrorHandler.RunModelConversion( - PostgresConstants.DatabaseName, + PostgresConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromDataToStorageModel(record)); @@ -150,7 +160,7 @@ public virtual async IAsyncEnumerable UpsertAsync(IEnumerable rec const string OperationName = "UpsertBatch"; var storageModels = records.Select(record => VectorStoreErrorHandler.RunModelConversion( - PostgresConstants.DatabaseName, + PostgresConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromDataToStorageModel(record))).ToList(); @@ -184,7 +194,7 @@ await this.RunOperationAsync(OperationName, () => if (row is null) { return default; } return VectorStoreErrorHandler.RunModelConversion( - PostgresConstants.DatabaseName, + PostgresConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(row, new() { IncludeVectors = includeVectors })); @@ -204,7 +214,7 @@ public virtual IAsyncEnumerable GetAsync(IEnumerable keys, GetRec this._client.GetBatchAsync(this.CollectionName, keys, this._model, includeVectors, cancellationToken) .SelectAsync(row => VectorStoreErrorHandler.RunModelConversion( - PostgresConstants.DatabaseName, + PostgresConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(row, new() { IncludeVectors = includeVectors })), @@ -281,7 +291,7 @@ public virtual Task> VectorizedSearchAsync .SelectAsync(result => { var record = VectorStoreErrorHandler.RunModelConversion( - PostgresConstants.DatabaseName, + PostgresConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel( @@ -295,6 +305,19 @@ public virtual Task> VectorizedSearchAsync }); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(NpgsqlDataSource) ? this._client.DataSource : + serviceType.IsInstanceOfType(this) ? this : + null; + } + private Task InternalCreateCollectionAsync(bool ifNotExists, CancellationToken cancellationToken = default) { return this._client.CreateTableAsync(this.CollectionName, this._model, ifNotExists, cancellationToken); @@ -310,7 +333,7 @@ private async Task RunOperationAsync(string operationName, Func operation) { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = PostgresConstants.DatabaseName, + VectorStoreType = PostgresConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; @@ -327,7 +350,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = PostgresConstants.DatabaseName, + VectorStoreType = PostgresConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreUtils.cs b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreUtils.cs index 27fa7181bdc5..c97280f7f929 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreUtils.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresVectorStoreUtils.cs @@ -19,7 +19,10 @@ internal static class PostgresVectorStoreUtils /// The name of the operation being performed. /// The name of the collection being operated on. /// An async enumerable that will throw a if an exception is thrown while iterating over the original enumerator. - public static async IAsyncEnumerable WrapAsyncEnumerableAsync(IAsyncEnumerable asyncEnumerable, string operationName, string? collectionName = null) + public static async IAsyncEnumerable WrapAsyncEnumerableAsync( + IAsyncEnumerable asyncEnumerable, + string operationName, + string? collectionName = null) { var enumerator = asyncEnumerable.ConfigureAwait(false).GetAsyncEnumerator(); @@ -39,7 +42,10 @@ public static async IAsyncEnumerable WrapAsyncEnumerableAsync(IAsyncEnumer /// The name of the operation being performed. /// The name of the collection being operated on. /// A value indicating whether there are more results and the current string if true. - public static async Task<(T item, bool more)> GetNextAsync(ConfiguredCancelableAsyncEnumerable.Enumerator enumerator, string operationName, string? collectionName = null) + public static async Task<(T item, bool more)> GetNextAsync( + ConfiguredCancelableAsyncEnumerable.Enumerator enumerator, + string operationName, + string? collectionName = null) { try { @@ -50,7 +56,7 @@ public static async IAsyncEnumerable WrapAsyncEnumerableAsync(IAsyncEnumer { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = PostgresConstants.DatabaseName, + VectorStoreType = PostgresConstants.VectorStoreSystemName, CollectionName = collectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantConstants.cs b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantConstants.cs new file mode 100644 index 000000000000..6e983cb76806 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantConstants.cs @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.SemanticKernel.Connectors.Qdrant; + +internal static class QdrantConstants +{ + internal const string VectorStoreSystemName = "qdrant"; +} diff --git a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorStore.cs index bfac788a7cfd..ee2f4f0ec35f 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorStore.cs @@ -18,8 +18,8 @@ namespace Microsoft.SemanticKernel.Connectors.Qdrant; /// public class QdrantVectorStore : IVectorStore { - /// The name of this database for telemetry purposes. - private const string DatabaseName = "Qdrant"; + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; /// Qdrant client that can be used to manage the collections and points in a Qdrant store. private readonly MockableQdrantClient _qdrantClient; @@ -48,6 +48,11 @@ internal QdrantVectorStore(MockableQdrantClient qdrantClient, QdrantVectorStoreO this._qdrantClient = qdrantClient; this._options = options ?? new QdrantVectorStoreOptions(); + + this._metadata = new() + { + VectorStoreSystemName = QdrantConstants.VectorStoreSystemName + }; } /// @@ -88,7 +93,7 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = QdrantConstants.VectorStoreSystemName, OperationName = "ListCollections" }; } @@ -98,4 +103,17 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat yield return collection; } } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(QdrantClient) ? this._qdrantClient.QdrantClient : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorStoreRecordCollection.cs index df33b1e8e54a..d2a3a45b1c82 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorStoreRecordCollection.cs @@ -26,15 +26,15 @@ public class QdrantVectorStoreRecordCollection : IKeywordHybridSearch #pragma warning restore CA1711 // Identifiers should not have incorrect suffix { + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; + /// The default options for vector search. private static readonly VectorSearchOptions s_defaultVectorSearchOptions = new(); /// The default options for hybrid vector search. private static readonly HybridSearchOptions s_defaultKeywordVectorizedHybridSearchOptions = new(); - /// The name of this database for telemetry purposes. - private const string DatabaseName = "Qdrant"; - /// The name of the upsert operation for telemetry purposes. private const string UpsertName = "Upsert"; @@ -96,6 +96,12 @@ internal QdrantVectorStoreRecordCollection(MockableQdrantClient qdrantClient, st #pragma warning disable CS0618 // IVectorStoreRecordMapper is obsolete this._mapper = this._options.PointStructCustomMapper ?? new QdrantVectorStoreRecordMapper(this._model, this._options.HasNamedVectors); #pragma warning restore CS0618 + + this._collectionMetadata = new() + { + VectorStoreSystemName = QdrantConstants.VectorStoreSystemName, + CollectionName = collectionName + }; } /// @@ -318,7 +324,7 @@ public virtual async Task UpsertAsync(TRecord record, CancellationToken c // Create point from record. var pointStruct = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + QdrantConstants.VectorStoreSystemName, this._collectionName, UpsertName, () => this._mapper.MapFromDataToStorageModel(record)); @@ -337,7 +343,7 @@ async Task IVectorStoreRecordCollection.UpsertAsync(TRecord // Create point from record. var pointStruct = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + QdrantConstants.VectorStoreSystemName, this._collectionName, UpsertName, () => this._mapper.MapFromDataToStorageModel(record)); @@ -356,7 +362,7 @@ public virtual async IAsyncEnumerable UpsertAsync(IEnumerable re // Create points from records. var pointStructs = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + QdrantConstants.VectorStoreSystemName, this._collectionName, UpsertName, () => records.Select(this._mapper.MapFromDataToStorageModel).ToList()); @@ -379,7 +385,7 @@ async IAsyncEnumerable IVectorStoreRecordCollection.UpsertA // Create points from records. var pointStructs = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + QdrantConstants.VectorStoreSystemName, this._collectionName, UpsertName, () => records.Select(this._mapper.MapFromDataToStorageModel).ToList()); @@ -437,7 +443,7 @@ private async IAsyncEnumerable GetBatchByPointIdAsync( } yield return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + QdrantConstants.VectorStoreSystemName, this._collectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(pointStruct, new() { IncludeVectors = includeVectors })); @@ -492,7 +498,7 @@ public virtual async Task> VectorizedSearchAsync> HybridSearchAsync(TVect point, this._mapper, internalOptions.IncludeVectors, - DatabaseName, + QdrantConstants.VectorStoreSystemName, this._collectionName, "Query")); return new VectorSearchResults(mappedResults.ToAsyncEnumerable()); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(QdrantClient) ? this._qdrantClient.QdrantClient : + serviceType.IsInstanceOfType(this) ? this : + null; + } + /// /// Run the given operation and wrap any with ."/> /// @@ -600,7 +619,7 @@ private async Task RunOperationAsync(string operationName, Func operation) { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = QdrantConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = operationName }; @@ -624,7 +643,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = QdrantConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.Redis/RedisConstants.cs b/dotnet/src/Connectors/Connectors.Memory.Redis/RedisConstants.cs new file mode 100644 index 000000000000..8d3e442ff671 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.Redis/RedisConstants.cs @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.SemanticKernel.Connectors.Redis; + +internal static class RedisConstants +{ + internal const string VectorStoreSystemName = "redis"; +} diff --git a/dotnet/src/Connectors/Connectors.Memory.Redis/RedisHashSetVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.Redis/RedisHashSetVectorStoreRecordCollection.cs index 656f490c1640..4929c4bb052f 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Redis/RedisHashSetVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Redis/RedisHashSetVectorStoreRecordCollection.cs @@ -23,8 +23,8 @@ namespace Microsoft.SemanticKernel.Connectors.Redis; public class RedisHashSetVectorStoreRecordCollection : IVectorStoreRecordCollection #pragma warning restore CA1711 // Identifiers should not have incorrect suffix { - /// The name of this database for telemetry purposes. - private const string DatabaseName = "Redis"; + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; internal static readonly VectorStoreRecordModelBuildingOptions ModelBuildingOptions = new() { @@ -113,6 +113,13 @@ public RedisHashSetVectorStoreRecordCollection(IDatabase database, string collec #pragma warning disable CS0618 // IVectorStoreRecordMapper is obsolete this._mapper = this._options.HashEntriesCustomMapper ?? new RedisHashSetVectorStoreRecordMapper(this._model); #pragma warning restore CS0618 + + this._collectionMetadata = new() + { + VectorStoreSystemName = RedisConstants.VectorStoreSystemName, + VectorStoreName = database.Database.ToString(), + CollectionName = collectionName + }; } /// @@ -134,7 +141,7 @@ public virtual async Task CollectionExistsAsync(CancellationToken cancella { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = RedisConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = "FT.INFO" }; @@ -223,7 +230,7 @@ await this.RunOperationAsync("FT.DROPINDEX", // Convert to the caller's data model. return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + RedisConstants.VectorStoreSystemName, this._collectionName, operationName, () => @@ -281,7 +288,7 @@ public virtual async Task UpsertAsync(TRecord record, CancellationToken // Map. var redisHashSetRecord = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + RedisConstants.VectorStoreSystemName, this._collectionName, "HSET", () => this._mapper.MapFromDataToStorageModel(record)); @@ -351,7 +358,7 @@ public virtual async Task> VectorizedSearchAsync @@ -370,6 +377,19 @@ public virtual async Task> VectorizedSearchAsync(mappedResults.ToAsyncEnumerable()); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(IDatabase) ? this._database : + serviceType.IsInstanceOfType(this) ? this : + null; + } + /// /// Prefix the key with the collection name if the option is set. /// @@ -419,7 +439,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = RedisConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = operationName }; @@ -442,7 +462,7 @@ private async Task RunOperationAsync(string operationName, Func operation) { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = RedisConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.Redis/RedisJsonVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.Redis/RedisJsonVectorStoreRecordCollection.cs index c1a1d283985f..7c3631aab808 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Redis/RedisJsonVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Redis/RedisJsonVectorStoreRecordCollection.cs @@ -26,6 +26,9 @@ namespace Microsoft.SemanticKernel.Connectors.Redis; public class RedisJsonVectorStoreRecordCollection : IVectorStoreRecordCollection #pragma warning restore CA1711 // Identifiers should not have incorrect suffix { + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; + internal static readonly VectorStoreRecordModelBuildingOptions ModelBuildingOptions = new() { RequiresAtLeastOneVector = false, @@ -48,9 +51,6 @@ public class RedisJsonVectorStoreRecordCollection : IVectorStoreRecordC typeof(ReadOnlyMemory?) ]; - /// The name of this database for telemetry purposes. - private const string DatabaseName = "Redis"; - /// The default options for vector search. private static readonly VectorSearchOptions s_defaultVectorSearchOptions = new(); @@ -121,6 +121,13 @@ public RedisJsonVectorStoreRecordCollection(IDatabase database, string collectio this._mapper = new RedisJsonVectorStoreRecordMapper(this._model.KeyProperty, this._jsonSerializerOptions); } #pragma warning restore CS0618 + + this._collectionMetadata = new() + { + VectorStoreSystemName = RedisConstants.VectorStoreSystemName, + VectorStoreName = database.Database.ToString(), + CollectionName = collectionName + }; } /// @@ -142,7 +149,7 @@ public virtual async Task CollectionExistsAsync(CancellationToken cancella { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = RedisConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = "FT.INFO" }; @@ -231,7 +238,7 @@ await this.RunOperationAsync("FT.DROPINDEX", // Convert to the caller's data model. return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + RedisConstants.VectorStoreSystemName, this._collectionName, "GET", () => @@ -280,7 +287,7 @@ public virtual async IAsyncEnumerable GetAsync(IEnumerable keys // Convert to the caller's data model. yield return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + RedisConstants.VectorStoreSystemName, this._collectionName, "MGET", () => @@ -324,7 +331,7 @@ public virtual async Task UpsertAsync(TRecord record, CancellationToken // Map. var redisJsonRecord = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + RedisConstants.VectorStoreSystemName, this._collectionName, "SET", () => @@ -358,7 +365,7 @@ public virtual async IAsyncEnumerable UpsertAsync(IEnumerable r foreach (var record in records) { var redisJsonRecord = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + RedisConstants.VectorStoreSystemName, this._collectionName, "MSET", () => @@ -416,7 +423,7 @@ public virtual async Task> VectorizedSearchAsync @@ -438,6 +445,19 @@ public virtual async Task> VectorizedSearchAsync(mappedResults.ToAsyncEnumerable()); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(IDatabase) ? this._database : + serviceType.IsInstanceOfType(this) ? this : + null; + } + /// /// Prefix the key with the collection name if the option is set. /// @@ -486,7 +506,7 @@ private async Task RunOperationAsync(string operationName, Func operation) { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = RedisConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = operationName }; @@ -510,7 +530,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = RedisConstants.VectorStoreSystemName, CollectionName = this._collectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.Redis/RedisVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.Redis/RedisVectorStore.cs index 4966917d3990..7deae3f65867 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Redis/RedisVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Redis/RedisVectorStore.cs @@ -18,8 +18,8 @@ namespace Microsoft.SemanticKernel.Connectors.Redis; /// public class RedisVectorStore : IVectorStore { - /// The name of this database for telemetry purposes. - private const string DatabaseName = "Redis"; + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; /// The redis database to read/write indices from. private readonly IDatabase _database; @@ -38,6 +38,12 @@ public RedisVectorStore(IDatabase database, RedisVectorStoreOptions? options = d this._database = database; this._options = options ?? new RedisVectorStoreOptions(); + + this._metadata = new() + { + VectorStoreSystemName = RedisConstants.VectorStoreSystemName, + VectorStoreName = database.Database.ToString() + }; } /// @@ -82,7 +88,7 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = RedisConstants.VectorStoreSystemName, OperationName = OperationName }; } @@ -96,4 +102,17 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat } } } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(IDatabase) ? this._metadata : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.SqlServer/ExceptionWrapper.cs b/dotnet/src/Connectors/Connectors.Memory.SqlServer/ExceptionWrapper.cs index 6690f1d564a4..f24b4a350993 100644 --- a/dotnet/src/Connectors/Connectors.Memory.SqlServer/ExceptionWrapper.cs +++ b/dotnet/src/Connectors/Connectors.Memory.SqlServer/ExceptionWrapper.cs @@ -12,8 +12,6 @@ namespace Microsoft.SemanticKernel.Connectors.SqlServer; internal static class ExceptionWrapper { - internal const string VectorStoreType = "SqlServer"; - internal static async Task WrapAsync( SqlConnection connection, SqlCommand command, @@ -42,7 +40,7 @@ internal static async Task WrapAsync( throw new VectorStoreOperationException(ex.Message, ex) { OperationName = operationName, - VectorStoreType = VectorStoreType, + VectorStoreType = SqlServerConstants.VectorStoreSystemName, CollectionName = collectionName }; } @@ -63,7 +61,7 @@ internal static async Task WrapReadAsync( throw new VectorStoreOperationException(ex.Message, ex) { OperationName = operationName, - VectorStoreType = VectorStoreType, + VectorStoreType = SqlServerConstants.VectorStoreSystemName, CollectionName = collectionName }; } diff --git a/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerConstants.cs b/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerConstants.cs index eed61838df81..f74de4a8fcb5 100644 --- a/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerConstants.cs +++ b/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerConstants.cs @@ -8,6 +8,8 @@ namespace Microsoft.SemanticKernel.Connectors.SqlServer; internal static class SqlServerConstants { + internal const string VectorStoreSystemName = "microsoft.sql_server"; + // The actual number is actually higher (2_100), but we want to avoid any kind of "off by one" errors. internal const int MaxParameterCount = 2_000; diff --git a/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerVectorStore.cs index d9481ffc467d..b8517a49baba 100644 --- a/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerVectorStore.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading; @@ -16,6 +17,9 @@ public sealed class SqlServerVectorStore : IVectorStore private readonly string _connectionString; private readonly SqlServerVectorStoreOptions _options; + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; + /// /// Initializes a new instance of the class. /// @@ -31,6 +35,14 @@ public SqlServerVectorStore(string connectionString, SqlServerVectorStoreOptions this._options = options is not null ? new() { Schema = options.Schema } : SqlServerVectorStoreOptions.Defaults; + + var connectionStringBuilder = new SqlConnectionStringBuilder(connectionString); + + this._metadata = new() + { + VectorStoreSystemName = SqlServerConstants.VectorStoreSystemName, + VectorStoreName = connectionStringBuilder.InitialCatalog + }; } /// @@ -63,4 +75,16 @@ public async IAsyncEnumerable ListCollectionNamesAsync([EnumeratorCancel yield return reader.GetString(reader.GetOrdinal("table_name")); } } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerVectorStoreRecordCollection.cs index 991020d0647d..adb2a6b8b834 100644 --- a/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerVectorStoreRecordCollection.cs @@ -20,6 +20,9 @@ public sealed class SqlServerVectorStoreRecordCollection #pragma warning restore CA1711 : IVectorStoreRecordCollection where TKey : notnull { + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; + private static readonly VectorSearchOptions s_defaultVectorSearchOptions = new(); private static readonly SqlServerVectorStoreRecordCollectionOptions s_defaultOptions = new(); @@ -60,9 +63,17 @@ public SqlServerVectorStoreRecordCollection( Mapper = options.Mapper, RecordDefinition = options.RecordDefinition, }; - this._mapper = this._options.Mapper ?? new RecordMapper(this._model); #pragma warning restore CS0618 + + var connectionStringBuilder = new SqlConnectionStringBuilder(connectionString); + + this._collectionMetadata = new() + { + VectorStoreSystemName = SqlServerConstants.VectorStoreSystemName, + VectorStoreName = connectionStringBuilder.InitialCatalog, + CollectionName = name + }; } /// @@ -205,7 +216,7 @@ public async Task DeleteAsync(IEnumerable keys, CancellationToken cancella throw new VectorStoreOperationException(ex.Message, ex) { OperationName = "DeleteBatch", - VectorStoreType = ExceptionWrapper.VectorStoreType, + VectorStoreType = SqlServerConstants.VectorStoreSystemName, CollectionName = this.CollectionName }; } @@ -377,7 +388,7 @@ public async IAsyncEnumerable UpsertAsync(IEnumerable records, throw new VectorStoreOperationException(ex.Message, ex) { OperationName = "UpsertBatch", - VectorStoreType = ExceptionWrapper.VectorStoreType, + VectorStoreType = SqlServerConstants.VectorStoreSystemName, CollectionName = this.CollectionName }; } @@ -444,6 +455,18 @@ public async Task> VectorizedSearchAsync(T }, cancellationToken, "VectorizedSearch", this.CollectionName).ConfigureAwait(false); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType.IsInstanceOfType(this) ? this : + null; + } + private async IAsyncEnumerable> ReadVectorSearchResultsAsync( SqlConnection connection, SqlCommand command, diff --git a/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteConstants.cs b/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteConstants.cs index 5bcd273203a9..9c40b2668062 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteConstants.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteConstants.cs @@ -8,6 +8,8 @@ namespace Microsoft.SemanticKernel.Connectors.Sqlite; internal static class SqliteConstants { + internal const string VectorStoreSystemName = "sqlite"; + /// /// SQLite extension name for vector search. /// More information here: . diff --git a/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteVectorStore.cs index f5b9615884ff..6e1e5d7bc9ea 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteVectorStore.cs @@ -18,6 +18,9 @@ namespace Microsoft.SemanticKernel.Connectors.Sqlite; /// public class SqliteVectorStore : IVectorStore { + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; + /// The connection string for the SQLite database represented by this . private readonly string _connectionString; @@ -35,6 +38,14 @@ public SqliteVectorStore(string connectionString, SqliteVectorStoreOptions? opti this._connectionString = connectionString; this._options = options ?? new(); + + var connectionStringBuilder = new SqliteConnectionStringBuilder(connectionString); + + this._metadata = new() + { + VectorStoreSystemName = SqliteConstants.VectorStoreSystemName, + VectorStoreName = connectionStringBuilder.DataSource + }; } /// @@ -100,4 +111,16 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat yield return reader.GetString(ordinal); } } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteVectorStoreRecordCollection.cs index 25cd0c07da7a..28e88f7febe0 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteVectorStoreRecordCollection.cs @@ -24,8 +24,8 @@ public class SqliteVectorStoreRecordCollection : IVectorStoreRecordCollection #pragma warning restore CA1711 // Identifiers should not have incorrect { - /// The name of this database for telemetry purposes. - private const string DatabaseName = "SQLite"; + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; /// The connection string for the SQLite database represented by this . private readonly string _connectionString; @@ -131,10 +131,18 @@ public SqliteVectorStoreRecordCollection( throw new UnreachableException(); } } - #pragma warning disable CS0618 // IVectorStoreRecordMapper is obsolete this._mapper = this._options.DictionaryCustomMapper ?? new SqliteVectorStoreRecordMapper(this._model); #pragma warning restore CS0618 + + var connectionStringBuilder = new SqliteConnectionStringBuilder(connectionString); + + this._collectionMetadata = new() + { + VectorStoreSystemName = SqliteConstants.VectorStoreSystemName, + VectorStoreName = connectionStringBuilder.DataSource, + CollectionName = collectionName + }; } /// @@ -362,6 +370,18 @@ public async Task DeleteAsync(IEnumerable keys, CancellationToken cancel #endregion + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType.IsInstanceOfType(this) ? this : + null; + } + #region private private async ValueTask GetConnectionAsync(CancellationToken cancellationToken = default) @@ -567,7 +587,7 @@ private async Task InternalUpsertAsync(SqliteConnection connection, const string OperationName = "Upsert"; var storageModel = VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + SqliteConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromDataToStorageModel(record)); @@ -590,7 +610,7 @@ private IAsyncEnumerable InternalUpsertBatchAsync(SqliteConnection c const string OperationName = "UpsertBatch"; var storageModels = records.Select(record => VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + SqliteConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromDataToStorageModel(record))).ToList(); @@ -720,7 +740,7 @@ private TRecord GetAndMapRecord( } return VectorStoreErrorHandler.RunModelConversion( - DatabaseName, + SqliteConstants.VectorStoreSystemName, this.CollectionName, operationName, () => this._mapper.MapFromStorageToDataModel(storageModel, new() { IncludeVectors = includeVectors })); @@ -736,7 +756,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = DatabaseName, + VectorStoreType = SqliteConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateConstants.cs b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateConstants.cs index 3bb4b18c8991..f98b4ec35fde 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateConstants.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateConstants.cs @@ -4,8 +4,8 @@ namespace Microsoft.SemanticKernel.Connectors.Weaviate; internal sealed class WeaviateConstants { - /// The name of this database for telemetry purposes. - public const string DatabaseName = "Weaviate"; + /// The name of this vector store for telemetry purposes. + public const string VectorStoreSystemName = "weaviate"; /// Reserved key property name in Weaviate. internal const string ReservedKeyPropertyName = "id"; diff --git a/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateVectorStore.cs index 6df456e872b2..91a2944d7658 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateVectorStore.cs @@ -18,6 +18,9 @@ namespace Microsoft.SemanticKernel.Connectors.Weaviate; /// public class WeaviateVectorStore : IVectorStore { + /// Metadata about vector store. + private readonly VectorStoreMetadata _metadata; + /// that is used to interact with Weaviate API. private readonly HttpClient _httpClient; @@ -39,6 +42,11 @@ public WeaviateVectorStore(HttpClient httpClient, WeaviateVectorStoreOptions? op this._httpClient = httpClient; this._options = options ?? new(); + + this._metadata = new() + { + VectorStoreSystemName = WeaviateConstants.VectorStoreSystemName + }; } /// @@ -91,7 +99,7 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat { throw new VectorStoreOperationException("Call to vector store failed.", e) { - VectorStoreType = WeaviateConstants.DatabaseName, + VectorStoreType = WeaviateConstants.VectorStoreSystemName, OperationName = "ListCollectionNames" }; } @@ -104,4 +112,17 @@ public virtual async IAsyncEnumerable ListCollectionNamesAsync([Enumerat } } } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreMetadata) ? this._metadata : + serviceType == typeof(HttpClient) ? this._httpClient : + serviceType.IsInstanceOfType(this) ? this : + null; + } } diff --git a/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateVectorStoreRecordCollection.cs b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateVectorStoreRecordCollection.cs index f50c25d8d573..e3914c5e2f13 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateVectorStoreRecordCollection.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateVectorStoreRecordCollection.cs @@ -24,6 +24,9 @@ namespace Microsoft.SemanticKernel.Connectors.Weaviate; public class WeaviateVectorStoreRecordCollection : IVectorStoreRecordCollection, IKeywordHybridSearch #pragma warning restore CA1711 // Identifiers should not have incorrect suffix { + /// Metadata about vector store record collection. + private readonly VectorStoreRecordCollectionMetadata _collectionMetadata; + /// Default JSON serializer options. private static readonly JsonSerializerOptions s_jsonSerializerOptions = new() { @@ -96,6 +99,12 @@ public WeaviateVectorStoreRecordCollection( // Assign mapper. this._mapper = this.InitializeMapper(); + + this._collectionMetadata = new() + { + VectorStoreSystemName = WeaviateConstants.VectorStoreSystemName, + CollectionName = collectionName + }; } /// @@ -208,7 +217,7 @@ public virtual Task DeleteAsync(IEnumerable keys, CancellationToken cancel } return VectorStoreErrorHandler.RunModelConversion( - WeaviateConstants.DatabaseName, + WeaviateConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromStorageToDataModel(jsonObject!, new() { IncludeVectors = includeVectors })); @@ -250,7 +259,7 @@ public virtual async IAsyncEnumerable UpsertAsync(IEnumerable rec var responses = await this.RunOperationAsync(OperationName, async () => { var jsonObjects = records.Select(record => VectorStoreErrorHandler.RunModelConversion( - WeaviateConstants.DatabaseName, + WeaviateConstants.VectorStoreSystemName, this.CollectionName, OperationName, () => this._mapper.MapFromDataToStorageModel(record))).ToList(); @@ -325,6 +334,19 @@ public async Task> HybridSearchAsync(TVect return await this.ExecuteQueryAsync(query, searchOptions.IncludeVectors, WeaviateConstants.HybridScorePropertyName, OperationName, cancellationToken).ConfigureAwait(false); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + Verify.NotNull(serviceType); + + return + serviceKey is not null ? null : + serviceType == typeof(VectorStoreRecordCollectionMetadata) ? this._collectionMetadata : + serviceType == typeof(HttpClient) ? this._httpClient : + serviceType.IsInstanceOfType(this) ? this : + null; + } + #region private private async Task> ExecuteQueryAsync(string query, bool includeVectors, string scorePropertyName, string operationName, CancellationToken cancellationToken) @@ -339,7 +361,7 @@ private async Task> ExecuteQueryAsync(string query, { throw new VectorStoreOperationException($"Error occurred during vector search. Response: {content}") { - VectorStoreType = WeaviateConstants.DatabaseName, + VectorStoreType = WeaviateConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; @@ -350,7 +372,7 @@ private async Task> ExecuteQueryAsync(string query, var (storageModel, score) = WeaviateVectorStoreCollectionSearchMapping.MapSearchResult(result!, scorePropertyName); var record = VectorStoreErrorHandler.RunModelConversion( - WeaviateConstants.DatabaseName, + WeaviateConstants.VectorStoreSystemName, this.CollectionName, operationName, () => this._mapper.MapFromStorageToDataModel(storageModel, new() { IncludeVectors = includeVectors })); @@ -415,7 +437,7 @@ private async Task RunOperationAsync(string operationName, Func> o { throw new VectorStoreOperationException("Call to vector store failed.", ex) { - VectorStoreType = WeaviateConstants.DatabaseName, + VectorStoreType = WeaviateConstants.VectorStoreSystemName, CollectionName = this.CollectionName, OperationName = operationName }; diff --git a/dotnet/src/Connectors/Connectors.Postgres.UnitTests/PostgresVectorStoreRecordCollectionTests.cs b/dotnet/src/Connectors/Connectors.Postgres.UnitTests/PostgresVectorStoreRecordCollectionTests.cs index a931bbea0b67..74545d03cda3 100644 --- a/dotnet/src/Connectors/Connectors.Postgres.UnitTests/PostgresVectorStoreRecordCollectionTests.cs +++ b/dotnet/src/Connectors/Connectors.Postgres.UnitTests/PostgresVectorStoreRecordCollectionTests.cs @@ -22,6 +22,7 @@ public class PostgresVectorStoreRecordCollectionTests public PostgresVectorStoreRecordCollectionTests() { this._postgresClientMock = new Mock(MockBehavior.Strict); + this._postgresClientMock.Setup(l => l.DatabaseName).Returns("TestDatabase"); } [Fact] diff --git a/dotnet/src/Connectors/Connectors.Postgres.UnitTests/PostgresVectorStoreTests.cs b/dotnet/src/Connectors/Connectors.Postgres.UnitTests/PostgresVectorStoreTests.cs index 33cfc005a7bc..8a89582fc0f8 100644 --- a/dotnet/src/Connectors/Connectors.Postgres.UnitTests/PostgresVectorStoreTests.cs +++ b/dotnet/src/Connectors/Connectors.Postgres.UnitTests/PostgresVectorStoreTests.cs @@ -26,6 +26,7 @@ public class PostgresVectorStoreTests public PostgresVectorStoreTests() { this._postgresClientMock = new Mock(MockBehavior.Strict); + this._postgresClientMock.Setup(l => l.DatabaseName).Returns("TestDatabase"); } [Fact] @@ -60,7 +61,10 @@ public void GetCollectionCallsFactoryIfProvided() var factoryMock = new Mock(MockBehavior.Strict); var collectionMock = new Mock>>(MockBehavior.Strict); var clientMock = new Mock(MockBehavior.Strict); + clientMock.Setup(x => x.DataSource).Returns(null); + clientMock.Setup(x => x.DatabaseName).Returns("TestDatabase"); + factoryMock .Setup(x => x.CreateVectorStoreRecordCollection>(It.IsAny(), TestCollectionName, null)) .Returns(collectionMock.Object); diff --git a/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisHashSetVectorStoreRecordCollectionTests.cs b/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisHashSetVectorStoreRecordCollectionTests.cs index 8b4324a6a98d..e95a83321b05 100644 --- a/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisHashSetVectorStoreRecordCollectionTests.cs +++ b/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisHashSetVectorStoreRecordCollectionTests.cs @@ -28,6 +28,7 @@ public class RedisHashSetVectorStoreRecordCollectionTests public RedisHashSetVectorStoreRecordCollectionTests() { this._redisDatabaseMock = new Mock(MockBehavior.Strict); + this._redisDatabaseMock.Setup(l => l.Database).Returns(0); var batchMock = new Mock(); this._redisDatabaseMock.Setup(x => x.CreateBatch(It.IsAny())).Returns(batchMock.Object); diff --git a/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisJsonVectorStoreRecordCollectionTests.cs b/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisJsonVectorStoreRecordCollectionTests.cs index 5a58000d3b48..50755b9624f0 100644 --- a/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisJsonVectorStoreRecordCollectionTests.cs +++ b/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisJsonVectorStoreRecordCollectionTests.cs @@ -32,6 +32,7 @@ public class RedisJsonVectorStoreRecordCollectionTests public RedisJsonVectorStoreRecordCollectionTests() { this._redisDatabaseMock = new Mock(MockBehavior.Strict); + this._redisDatabaseMock.Setup(l => l.Database).Returns(0); var batchMock = new Mock(); this._redisDatabaseMock.Setup(x => x.CreateBatch(It.IsAny())).Returns(batchMock.Object); diff --git a/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisVectorStoreTests.cs b/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisVectorStoreTests.cs index baf2564c81a2..9280051fd266 100644 --- a/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisVectorStoreTests.cs +++ b/dotnet/src/Connectors/Connectors.Redis.UnitTests/RedisVectorStoreTests.cs @@ -22,6 +22,7 @@ public class RedisVectorStoreTests public RedisVectorStoreTests() { this._redisDatabaseMock = new Mock(MockBehavior.Strict); + this._redisDatabaseMock.Setup(l => l.Database).Returns(0); var batchMock = new Mock(); this._redisDatabaseMock.Setup(x => x.CreateBatch(It.IsAny())).Returns(batchMock.Object); diff --git a/dotnet/src/Connectors/Directory.Build.props b/dotnet/src/Connectors/Directory.Build.props index 46c46d509f83..dd75c63ffd61 100644 --- a/dotnet/src/Connectors/Directory.Build.props +++ b/dotnet/src/Connectors/Directory.Build.props @@ -3,7 +3,7 @@ - $(NoWarn);MEVD9001 + $(NoWarn);MEVD9000,MEVD9001 \ No newline at end of file diff --git a/dotnet/src/Connectors/VectorData.Abstractions/CompatibilitySuppressions.xml b/dotnet/src/Connectors/VectorData.Abstractions/CompatibilitySuppressions.xml index d4b4c39149eb..9e79fa44b1bb 100644 --- a/dotnet/src/Connectors/VectorData.Abstractions/CompatibilitySuppressions.xml +++ b/dotnet/src/Connectors/VectorData.Abstractions/CompatibilitySuppressions.xml @@ -2,141 +2,113 @@ - CP0001 - T:Microsoft.Extensions.VectorData.DeleteRecordOptions + CP0002 + M:Microsoft.Extensions.VectorData.HybridSearchOptions`1.get_Top lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true - CP0001 - T:Microsoft.Extensions.VectorData.UpsertRecordOptions + CP0002 + M:Microsoft.Extensions.VectorData.HybridSearchOptions`1.set_Top(System.Int32) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true - CP0001 - T:Microsoft.Extensions.VectorData.VectorSearchOptions + CP0002 + M:Microsoft.Extensions.VectorData.IKeywordHybridSearch`1.HybridSearchAsync``1(``0,System.Collections.Generic.ICollection{System.String},Microsoft.Extensions.VectorData.HybridSearchOptions{`0},System.Threading.CancellationToken) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true - CP0001 - T:Microsoft.Extensions.VectorData.DeleteRecordOptions - lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll - lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll - true - - - CP0001 - T:Microsoft.Extensions.VectorData.UpsertRecordOptions - lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll - lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll - true - - - CP0001 - T:Microsoft.Extensions.VectorData.VectorSearchOptions - lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll - lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll - true - - - CP0001 - T:Microsoft.Extensions.VectorData.DeleteRecordOptions - lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll - true - - - CP0001 - T:Microsoft.Extensions.VectorData.UpsertRecordOptions - lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + CP0002 + M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.VectorizableTextSearchAsync(System.String,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true - CP0001 - T:Microsoft.Extensions.VectorData.VectorSearchOptions - lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll - lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + CP0002 + M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.VectorizableTextSearchAsync(System.String,Microsoft.Extensions.VectorData.VectorSearchOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteBatchAsync(System.Collections.Generic.IEnumerable{`0},System.Threading.CancellationToken) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,Microsoft.Extensions.VectorData.VectorSearchOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.GetBatchAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.GetRecordOptions,System.Threading.CancellationToken) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(`0,Microsoft.Extensions.VectorData.DeleteRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertBatchAsync(System.Collections.Generic.IEnumerable{`1},System.Threading.CancellationToken) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteBatchAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.DeleteRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.VectorSearchOptions`1.get_Top lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.GetBatchAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.GetRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.VectorSearchOptions`1.set_Top(System.Int32) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertAsync(`1,Microsoft.Extensions.VectorData.UpsertRecordOptions,System.Threading.CancellationToken) - lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll - lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + M:Microsoft.Extensions.VectorData.HybridSearchOptions`1.get_Top + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertBatchAsync(System.Collections.Generic.IEnumerable{`1},Microsoft.Extensions.VectorData.UpsertRecordOptions,System.Threading.CancellationToken) - lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll - lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + M:Microsoft.Extensions.VectorData.HybridSearchOptions`1.set_Top(System.Int32) + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.VectorizableTextSearchAsync(System.String,Microsoft.Extensions.VectorData.VectorSearchOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IKeywordHybridSearch`1.HybridSearchAsync``1(``0,System.Collections.Generic.ICollection{System.String},Microsoft.Extensions.VectorData.HybridSearchOptions{`0},System.Threading.CancellationToken) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,Microsoft.Extensions.VectorData.VectorSearchOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.VectorizableTextSearchAsync(System.String,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(`0,Microsoft.Extensions.VectorData.DeleteRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteBatchAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.DeleteRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteBatchAsync(System.Collections.Generic.IEnumerable{`0},System.Threading.CancellationToken) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true @@ -150,42 +122,63 @@ CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertAsync(`1,Microsoft.Extensions.VectorData.UpsertRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertBatchAsync(System.Collections.Generic.IEnumerable{`1},System.Threading.CancellationToken) + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.VectorData.VectorSearchOptions`1.get_Top lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertBatchAsync(System.Collections.Generic.IEnumerable{`1},Microsoft.Extensions.VectorData.UpsertRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.VectorSearchOptions`1.set_Top(System.Int32) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.VectorizableTextSearchAsync(System.String,Microsoft.Extensions.VectorData.VectorSearchOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.HybridSearchOptions`1.get_Top lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,Microsoft.Extensions.VectorData.VectorSearchOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.HybridSearchOptions`1.set_Top(System.Int32) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(`0,Microsoft.Extensions.VectorData.DeleteRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IKeywordHybridSearch`1.HybridSearchAsync``1(``0,System.Collections.Generic.ICollection{System.String},Microsoft.Extensions.VectorData.HybridSearchOptions{`0},System.Threading.CancellationToken) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteBatchAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.DeleteRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.VectorizableTextSearchAsync(System.String,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteBatchAsync(System.Collections.Generic.IEnumerable{`0},System.Threading.CancellationToken) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true @@ -199,18 +192,46 @@ CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertAsync(`1,Microsoft.Extensions.VectorData.UpsertRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertBatchAsync(System.Collections.Generic.IEnumerable{`1},System.Threading.CancellationToken) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0002 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertBatchAsync(System.Collections.Generic.IEnumerable{`1},Microsoft.Extensions.VectorData.UpsertRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.VectorSearchOptions`1.get_Top + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.VectorData.VectorSearchOptions`1.set_Top(System.Int32) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true + + CP0006 + M:Microsoft.Extensions.VectorData.IKeywordHybridSearch`1.GetService(System.Type,System.Object) + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0006 + M:Microsoft.Extensions.VectorData.IKeywordHybridSearch`1.HybridSearchAsync``1(``0,System.Collections.Generic.ICollection{System.String},System.Int32,Microsoft.Extensions.VectorData.HybridSearchOptions{`0},System.Threading.CancellationToken) + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0006 + M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.GetService(System.Type,System.Object) + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll + true + CP0006 M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.VectorizableTextSearchAsync(System.String,System.Int32,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) @@ -220,35 +241,35 @@ CP0006 - M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,System.Int32,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.GetService(System.Type,System.Object) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(`0,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,System.Int32,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(System.Collections.Generic.IEnumerable{`0},System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStore.GetService(System.Type,System.Object) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.GetAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.GetRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(System.Collections.Generic.IEnumerable{`0},System.Threading.CancellationToken) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertAsync(`1,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.GetAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.GetRecordOptions,System.Threading.CancellationToken) lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true @@ -260,6 +281,27 @@ lib/net462/Microsoft.Extensions.VectorData.Abstractions.dll true + + CP0006 + M:Microsoft.Extensions.VectorData.IKeywordHybridSearch`1.GetService(System.Type,System.Object) + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0006 + M:Microsoft.Extensions.VectorData.IKeywordHybridSearch`1.HybridSearchAsync``1(``0,System.Collections.Generic.ICollection{System.String},System.Int32,Microsoft.Extensions.VectorData.HybridSearchOptions{`0},System.Threading.CancellationToken) + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0006 + M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.GetService(System.Type,System.Object) + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + CP0006 M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.VectorizableTextSearchAsync(System.String,System.Int32,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) @@ -269,35 +311,35 @@ CP0006 - M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,System.Int32,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.GetService(System.Type,System.Object) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(`0,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,System.Int32,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(System.Collections.Generic.IEnumerable{`0},System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStore.GetService(System.Type,System.Object) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.GetAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.GetRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(System.Collections.Generic.IEnumerable{`0},System.Threading.CancellationToken) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertAsync(`1,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.GetAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.GetRecordOptions,System.Threading.CancellationToken) lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true @@ -309,6 +351,27 @@ lib/net8.0/Microsoft.Extensions.VectorData.Abstractions.dll true + + CP0006 + M:Microsoft.Extensions.VectorData.IKeywordHybridSearch`1.GetService(System.Type,System.Object) + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0006 + M:Microsoft.Extensions.VectorData.IKeywordHybridSearch`1.HybridSearchAsync``1(``0,System.Collections.Generic.ICollection{System.String},System.Int32,Microsoft.Extensions.VectorData.HybridSearchOptions{`0},System.Threading.CancellationToken) + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + + + CP0006 + M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.GetService(System.Type,System.Object) + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll + true + CP0006 M:Microsoft.Extensions.VectorData.IVectorizableTextSearch`1.VectorizableTextSearchAsync(System.String,System.Int32,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) @@ -318,35 +381,35 @@ CP0006 - M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,System.Int32,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.GetService(System.Type,System.Object) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(`0,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorizedSearch`1.VectorizedSearchAsync``1(``0,System.Int32,Microsoft.Extensions.VectorData.VectorSearchOptions{`0},System.Threading.CancellationToken) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(System.Collections.Generic.IEnumerable{`0},System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStore.GetService(System.Type,System.Object) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.GetAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.GetRecordOptions,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.DeleteAsync(System.Collections.Generic.IEnumerable{`0},System.Threading.CancellationToken) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true CP0006 - M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.UpsertAsync(`1,System.Threading.CancellationToken) + M:Microsoft.Extensions.VectorData.IVectorStoreRecordCollection`2.GetAsync(System.Collections.Generic.IEnumerable{`0},Microsoft.Extensions.VectorData.GetRecordOptions,System.Threading.CancellationToken) lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll lib/netstandard2.0/Microsoft.Extensions.VectorData.Abstractions.dll true diff --git a/dotnet/src/Connectors/VectorData.Abstractions/VectorData.Abstractions.csproj b/dotnet/src/Connectors/VectorData.Abstractions/VectorData.Abstractions.csproj index 5b8a57c7ed74..c70073466ff8 100644 --- a/dotnet/src/Connectors/VectorData.Abstractions/VectorData.Abstractions.csproj +++ b/dotnet/src/Connectors/VectorData.Abstractions/VectorData.Abstractions.csproj @@ -13,7 +13,7 @@ 9.0.0-preview.1.25161.1 9.0.0.0 - 9.0.0-preview.1.25078.1 + 9.0.0-preview.1.25161.1 Microsoft.Extensions.VectorData.Abstractions $(AssemblyName) Abstractions for vector database access. diff --git a/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IKeywordHybridSearch.cs b/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IKeywordHybridSearch.cs index 7e089fae04c1..671664bf3a74 100644 --- a/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IKeywordHybridSearch.cs +++ b/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IKeywordHybridSearch.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All rights reserved. +using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; @@ -28,4 +30,17 @@ Task> HybridSearchAsync( int top, HybridSearchOptions? options = default, CancellationToken cancellationToken = default); + + /// Asks the for an object of the specified type . + /// The type of object being requested. + /// An optional key that can be used to help identify the target service. + /// The found object, otherwise . + /// is . + /// + /// The purpose of this method is to allow for the retrieval of strongly-typed services that might be provided by the , + /// including itself or any services it might be wrapping. For example, to access the for the instance, + /// may be used to request it. + /// + [Experimental("MEVD9000")] + object? GetService(Type serviceType, object? serviceKey = null); } diff --git a/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IVectorizableTextSearch.cs b/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IVectorizableTextSearch.cs index f300bed658c3..3198e518e9ce 100644 --- a/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IVectorizableTextSearch.cs +++ b/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IVectorizableTextSearch.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; @@ -24,4 +26,17 @@ Task> VectorizableTextSearchAsync( int top, VectorSearchOptions? options = default, CancellationToken cancellationToken = default); + + /// Asks the for an object of the specified type . + /// The type of object being requested. + /// An optional key that can be used to help identify the target service. + /// The found object, otherwise . + /// is . + /// + /// The purpose of this method is to allow for the retrieval of strongly-typed services that might be provided by the , + /// including itself or any services it might be wrapping. For example, to access the for the instance, + /// may be used to request it. + /// + [Experimental("MEVD9000")] + object? GetService(Type serviceType, object? serviceKey = null); } diff --git a/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IVectorizedSearch.cs b/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IVectorizedSearch.cs index b7a5de5c19d2..e4ff7dec7238 100644 --- a/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IVectorizedSearch.cs +++ b/dotnet/src/Connectors/VectorData.Abstractions/VectorSearch/IVectorizedSearch.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; @@ -25,4 +27,17 @@ Task> VectorizedSearchAsync( int top, VectorSearchOptions? options = default, CancellationToken cancellationToken = default); + + /// Asks the for an object of the specified type . + /// The type of object being requested. + /// An optional key that can be used to help identify the target service. + /// The found object, otherwise . + /// is . + /// + /// The purpose of this method is to allow for the retrieval of strongly-typed services that might be provided by the , + /// including itself or any services it might be wrapping. For example, to access the for the instance, + /// may be used to request it. + /// + [Experimental("MEVD9000")] + object? GetService(Type serviceType, object? serviceKey = null); } diff --git a/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/IVectorStore.cs b/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/IVectorStore.cs index a3ac5466323c..6810e99722be 100644 --- a/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/IVectorStore.cs +++ b/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/IVectorStore.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All rights reserved. +using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading; namespace Microsoft.Extensions.VectorData; @@ -38,4 +40,17 @@ IVectorStoreRecordCollection GetCollection(string /// The to monitor for cancellation requests. The default is . /// The list of names of all the collections in the vector store. IAsyncEnumerable ListCollectionNamesAsync(CancellationToken cancellationToken = default); + + /// Asks the for an object of the specified type . + /// The type of object being requested. + /// An optional key that can be used to help identify the target service. + /// The found object, otherwise . + /// is . + /// + /// The purpose of this method is to allow for the retrieval of strongly-typed services that might be provided by the , + /// including itself or any services it might be wrapping. For example, to access the for the instance, + /// may be used to request it. + /// + [Experimental("MEVD9000")] + object? GetService(Type serviceType, object? serviceKey = null); } diff --git a/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/VectorStoreMetadata.cs b/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/VectorStoreMetadata.cs new file mode 100644 index 000000000000..f89884736cb6 --- /dev/null +++ b/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/VectorStoreMetadata.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.Extensions.VectorData; + +/// Provides metadata about an . +[Experimental("MEVD9000")] +public class VectorStoreMetadata +{ + /// The name of the vector store system. + /// + /// Where possible, this maps to the "db.system.name" attribute defined in the + /// OpenTelemetry Semantic Conventions for database calls and systems, see . + /// Example: redis, sqlite, mysql. + /// + public string? VectorStoreSystemName { get; init; } + + /// + /// The name of the vector store (database). + /// + public string? VectorStoreName { get; init; } +} diff --git a/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/VectorStoreRecordCollectionMetadata.cs b/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/VectorStoreRecordCollectionMetadata.cs new file mode 100644 index 000000000000..b2ea092878c3 --- /dev/null +++ b/dotnet/src/Connectors/VectorData.Abstractions/VectorStorage/VectorStoreRecordCollectionMetadata.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.Extensions.VectorData; + +/// Provides metadata about an . +[Experimental("MEVD9000")] +public class VectorStoreRecordCollectionMetadata +{ + /// The name of the vector store system. + /// + /// Where possible, this maps to the "db.system.name" attribute defined in the + /// OpenTelemetry Semantic Conventions for database calls and systems, see . + /// Example: redis, sqlite, mysql. + /// + public string? VectorStoreSystemName { get; init; } + + /// + /// The name of the vector store (database). + /// + public string? VectorStoreName { get; init; } + + /// + /// The name of a collection (table, container) within the vector store (database). + /// + public string? CollectionName { get; init; } +} diff --git a/dotnet/src/IntegrationTests/Data/BaseVectorStoreTextSearchTests.cs b/dotnet/src/IntegrationTests/Data/BaseVectorStoreTextSearchTests.cs index 4831e1720c9c..427f0a123b61 100644 --- a/dotnet/src/IntegrationTests/Data/BaseVectorStoreTextSearchTests.cs +++ b/dotnet/src/IntegrationTests/Data/BaseVectorStoreTextSearchTests.cs @@ -108,6 +108,16 @@ public async Task> VectorizableTextSearchAsync(stri return await vectorizedSearch.VectorizedSearchAsync(vectorizedQuery, top, options, cancellationToken); } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + ArgumentNullException.ThrowIfNull(serviceType); + + return + serviceKey is null && serviceType.IsInstanceOfType(this) ? this : + vectorizedSearch.GetService(serviceType, serviceKey); + } } /// diff --git a/dotnet/src/IntegrationTests/IntegrationTests.csproj b/dotnet/src/IntegrationTests/IntegrationTests.csproj index cb21d20b7f4a..d80c297f4d26 100644 --- a/dotnet/src/IntegrationTests/IntegrationTests.csproj +++ b/dotnet/src/IntegrationTests/IntegrationTests.csproj @@ -5,7 +5,7 @@ net8.0 true false - $(NoWarn);CA2007,CA1861,VSTHRD111,SKEXP0001,SKEXP0010,SKEXP0020,SKEXP0040,SKEXP0050,SKEXP0060,SKEXP0070,SKEXP0080,SKEXP0110,OPENAI001 + $(NoWarn);CA2007,CA1861,VSTHRD111,SKEXP0001,SKEXP0010,SKEXP0020,SKEXP0040,SKEXP0050,SKEXP0060,SKEXP0070,SKEXP0080,SKEXP0110,OPENAI001,MEVD9000 b7762d10-e29b-4bb1-8b74-b6d69a667dd4 diff --git a/dotnet/src/InternalUtilities/connectors/Memory/MongoDB/MongoDBConstants.cs b/dotnet/src/InternalUtilities/connectors/Memory/MongoDB/MongoDBConstants.cs index 456ab0b44e1a..279da36b7895 100644 --- a/dotnet/src/InternalUtilities/connectors/Memory/MongoDB/MongoDBConstants.cs +++ b/dotnet/src/InternalUtilities/connectors/Memory/MongoDB/MongoDBConstants.cs @@ -13,6 +13,8 @@ namespace Microsoft.SemanticKernel.Connectors.MongoDB; [ExcludeFromCodeCoverage] internal static class MongoDBConstants { + internal const string VectorStoreSystemName = "mongodb"; + /// Default ratio of number of nearest neighbors to number of documents to return. internal const int DefaultNumCandidatesRatio = 10; diff --git a/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/MockVectorizableTextSearch.cs b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/MockVectorizableTextSearch.cs index b6f824a16b0f..eb9ed46823e3 100644 --- a/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/MockVectorizableTextSearch.cs +++ b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/MockVectorizableTextSearch.cs @@ -18,6 +18,16 @@ public Task> VectorizableTextSearchAsync(string sea return Task.FromResult(new VectorSearchResults(this._searchResults)); } + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + ArgumentNullException.ThrowIfNull(serviceType); + + return + serviceKey is null && serviceType.IsInstanceOfType(this) ? this : + null; + } + private static async IAsyncEnumerable> ToAsyncEnumerable(IEnumerable> searchResults) { foreach (var result in searchResults) diff --git a/dotnet/src/SemanticKernel.UnitTests/Data/VectorStoreTextSearchTestBase.cs b/dotnet/src/SemanticKernel.UnitTests/Data/VectorStoreTextSearchTestBase.cs index 968ff4fdac7f..7882846ab2a8 100644 --- a/dotnet/src/SemanticKernel.UnitTests/Data/VectorStoreTextSearchTestBase.cs +++ b/dotnet/src/SemanticKernel.UnitTests/Data/VectorStoreTextSearchTestBase.cs @@ -131,6 +131,16 @@ public async Task> VectorizableTextSearchAsync(stri var vectorizedQuery = await textEmbeddingGeneration!.GenerateEmbeddingAsync(searchText, cancellationToken: cancellationToken).ConfigureAwait(false); return await vectorizedSearch.VectorizedSearchAsync(vectorizedQuery, top, options, cancellationToken); } + + /// + public object? GetService(Type serviceType, object? serviceKey = null) + { + ArgumentNullException.ThrowIfNull(serviceType); + + return + serviceKey is null && serviceType.IsInstanceOfType(this) ? this : + vectorizedSearch.GetService(serviceType, serviceKey); + } } /// diff --git a/dotnet/src/SemanticKernel.UnitTests/SemanticKernel.UnitTests.csproj b/dotnet/src/SemanticKernel.UnitTests/SemanticKernel.UnitTests.csproj index 8580c9a173ab..3311fb3b3553 100644 --- a/dotnet/src/SemanticKernel.UnitTests/SemanticKernel.UnitTests.csproj +++ b/dotnet/src/SemanticKernel.UnitTests/SemanticKernel.UnitTests.csproj @@ -6,7 +6,7 @@ net8.0 true false - $(NoWarn);CA2007,CA1861,IDE1006,VSTHRD111,SKEXP0001,SKEXP0010,SKEXP0020,SKEXP0050,SKEXP0110,SKEXP0120 + $(NoWarn);CA2007,CA1861,IDE1006,VSTHRD111,SKEXP0001,SKEXP0010,SKEXP0020,SKEXP0050,SKEXP0110,SKEXP0120,MEVD9000 diff --git a/dotnet/src/VectorDataIntegrationTests/SqlServerIntegrationTests/CRUD/SqlServerBatchConformanceTests.cs b/dotnet/src/VectorDataIntegrationTests/SqlServerIntegrationTests/CRUD/SqlServerBatchConformanceTests.cs index b9e6f54eb752..1e7273aa9a7c 100644 --- a/dotnet/src/VectorDataIntegrationTests/SqlServerIntegrationTests/CRUD/SqlServerBatchConformanceTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/SqlServerIntegrationTests/CRUD/SqlServerBatchConformanceTests.cs @@ -66,7 +66,11 @@ public async Task UpsertBatchIsAtomic() VectorStoreOperationException ex = await Assert.ThrowsAsync(() => collection.UpsertAsync(inserted).ToArrayAsync().AsTask()); Assert.Equal("UpsertBatch", ex.OperationName); - Assert.Equal(collection.CollectionName, ex.CollectionName); + + var metadata = collection.GetService(typeof(VectorStoreRecordCollectionMetadata)) as VectorStoreRecordCollectionMetadata; + + Assert.NotNull(metadata?.CollectionName); + Assert.Equal(metadata.CollectionName, ex.CollectionName); // Make sure that no records were inserted! Assert.Empty(await collection.GetAsync(keys).ToArrayAsync()); diff --git a/dotnet/src/VectorDataIntegrationTests/SqlServerIntegrationTests/SqlServerIntegrationTests.csproj b/dotnet/src/VectorDataIntegrationTests/SqlServerIntegrationTests/SqlServerIntegrationTests.csproj index ba0e332abc73..d15fc2fc0058 100644 --- a/dotnet/src/VectorDataIntegrationTests/SqlServerIntegrationTests/SqlServerIntegrationTests.csproj +++ b/dotnet/src/VectorDataIntegrationTests/SqlServerIntegrationTests/SqlServerIntegrationTests.csproj @@ -11,7 +11,7 @@ $(NoWarn);CA2007,SKEXP0001,SKEXP0020,VSTHRD111;CS1685 b7762d10-e29b-4bb1-8b74-b6d69a667dd4 - $(NoWarn);MEVD9001 + $(NoWarn);MEVD9000,MEVD9001 diff --git a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Collections/CollectionConformanceTests.cs b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Collections/CollectionConformanceTests.cs index 16f8679df842..be3becc603cc 100644 --- a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Collections/CollectionConformanceTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Collections/CollectionConformanceTests.cs @@ -86,7 +86,17 @@ private async Task CreateCollection() try { Assert.True(await collection.CollectionExistsAsync()); - Assert.True(await fixture.TestStore.DefaultVectorStore.ListCollectionNamesAsync().ContainsAsync(collection.CollectionName)); + +#pragma warning disable MEVD9000 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + var collectionMetadata = collection.GetService(typeof(VectorStoreRecordCollectionMetadata)) as VectorStoreRecordCollectionMetadata; +#pragma warning restore MEVD9000 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + + Assert.NotNull(collectionMetadata); + Assert.NotNull(collectionMetadata.VectorStoreSystemName); + Assert.NotNull(collectionMetadata.VectorStoreName); + Assert.NotNull(collectionMetadata.CollectionName); + + Assert.True(await fixture.TestStore.DefaultVectorStore.ListCollectionNamesAsync().ContainsAsync(collectionMetadata.CollectionName)); } finally { @@ -103,7 +113,17 @@ private async Task CreateCollectionIfNotExistsMoreThanOnce() try { Assert.True(await collection.CollectionExistsAsync()); - Assert.True(await fixture.TestStore.DefaultVectorStore.ListCollectionNamesAsync().ContainsAsync(collection.CollectionName)); + +#pragma warning disable MEVD9000 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + var collectionMetadata = collection.GetService(typeof(VectorStoreRecordCollectionMetadata)) as VectorStoreRecordCollectionMetadata; +#pragma warning restore MEVD9000 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + + Assert.NotNull(collectionMetadata); + Assert.NotNull(collectionMetadata.VectorStoreSystemName); + Assert.NotNull(collectionMetadata.VectorStoreName); + Assert.NotNull(collectionMetadata.CollectionName); + + Assert.True(await fixture.TestStore.DefaultVectorStore.ListCollectionNamesAsync().ContainsAsync(collectionMetadata.CollectionName)); await collection.CreateCollectionIfNotExistsAsync(); } @@ -122,7 +142,17 @@ private async Task CreateCollectionMoreThanOnce() try { Assert.True(await collection.CollectionExistsAsync()); - Assert.True(await fixture.TestStore.DefaultVectorStore.ListCollectionNamesAsync().ContainsAsync(collection.CollectionName)); + +#pragma warning disable MEVD9000 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + var collectionMetadata = collection.GetService(typeof(VectorStoreRecordCollectionMetadata)) as VectorStoreRecordCollectionMetadata; +#pragma warning restore MEVD9000 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + + Assert.NotNull(collectionMetadata); + Assert.NotNull(collectionMetadata.VectorStoreSystemName); + Assert.NotNull(collectionMetadata.VectorStoreName); + Assert.NotNull(collectionMetadata.CollectionName); + + Assert.True(await fixture.TestStore.DefaultVectorStore.ListCollectionNamesAsync().ContainsAsync(collectionMetadata.CollectionName)); await collection.CreateCollectionIfNotExistsAsync();