diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchConfigConditionAttribute.cs b/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchConfigConditionAttribute.cs
deleted file mode 100644
index d53e7174f5e3..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchConfigConditionAttribute.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Threading.Tasks;
-using SemanticKernel.IntegrationTests.Connectors.Memory.Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.AzureAISearch;
-
-///
-/// Attribute to use to skip tests if the settings for Azure AI Search is not set.
-///
-[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
-public sealed class AzureAISearchConfigConditionAttribute : Attribute, ITestCondition
-{
- public ValueTask IsMetAsync()
- {
- var config = AzureAISearchVectorStoreFixture.GetAzureAISearchConfiguration();
- var isMet = config is not null && !string.IsNullOrWhiteSpace(config?.ServiceUrl) && !string.IsNullOrWhiteSpace(config?.ApiKey);
-
- return ValueTask.FromResult(isMet);
- }
-
- public string SkipReason
- => "Azure AI Search ServiceUrl or ApiKey was not specified in user secrets. Use the following command to set them: dotnet user-secrets set \"AzureAISearch:ServiceUrl\" \"your_service_url\" and dotnet user-secrets set \"AzureAISearch:ApiKey\" \"your_api_key\"";
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchHotel.cs b/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchHotel.cs
deleted file mode 100644
index c77edf7fc438..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchHotel.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Text.Json.Serialization;
-using Azure.Search.Documents.Indexes;
-using Azure.Search.Documents.Indexes.Models;
-using Microsoft.Extensions.VectorData;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.AzureAISearch;
-
-#pragma warning disable CS8618
-
-public class AzureAISearchHotel
-{
- [SimpleField(IsKey = true, IsFilterable = true)]
- [VectorStoreKey]
- public string HotelId { get; set; }
-
- [SearchableField(IsFilterable = true, IsSortable = true)]
- [VectorStoreData(IsIndexed = true, IsFullTextIndexed = true)]
- public string HotelName { get; set; }
-
- [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)]
- [VectorStoreData]
- public string Description { get; set; }
-
- [VectorStoreVector(1536)]
- public ReadOnlyMemory? DescriptionEmbedding { get; set; }
-
- [SearchableField(IsFilterable = true, IsFacetable = true)]
- [VectorStoreData(IsIndexed = true)]
-#pragma warning disable CA1819 // Properties should not return arrays
- public string[] Tags { get; set; }
-#pragma warning restore CA1819 // Properties should not return arrays
-
- [JsonPropertyName("parking_is_included")]
- [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
- [VectorStoreData(IsIndexed = true)]
- public bool? ParkingIncluded { get; set; }
-
- [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
- [VectorStoreData(IsIndexed = true)]
- public DateTimeOffset? LastRenovationDate { get; set; }
-
- [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
- [VectorStoreData]
- public double? Rating { get; set; }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchTextSearchTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchTextSearchTests.cs
deleted file mode 100644
index aaf65fa5cb4a..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchTextSearchTests.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Threading.Tasks;
-using Azure.AI.OpenAI;
-using Azure.Identity;
-using Microsoft.Extensions.AI;
-using Microsoft.Extensions.Configuration;
-using Microsoft.SemanticKernel.Connectors.AzureAISearch;
-using Microsoft.SemanticKernel.Data;
-using SemanticKernel.IntegrationTests.Data;
-using SemanticKernel.IntegrationTests.TestSettings;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.AzureAISearch;
-
-///
-/// Integration tests for using with .
-///
-[Collection("AzureAISearchVectorStoreCollection")]
-public class AzureAISearchTextSearchTests(AzureAISearchVectorStoreFixture fixture) : BaseVectorStoreTextSearchTests
-{
- // If null, all tests will be enabled
- private const string SkipReason = "Requires Azure AI Search Service instance up and running";
-
- [Fact(Skip = SkipReason)]
- public override async Task CanSearchAsync()
- {
- await base.CanSearchAsync();
- }
-
- [Fact(Skip = SkipReason)]
- public override async Task CanGetTextSearchResultsAsync()
- {
- await base.CanGetTextSearchResultsAsync();
- }
-
- [Fact(Skip = SkipReason)]
- public override async Task CanGetSearchResultsAsync()
- {
- await base.CanGetSearchResultsAsync();
- }
-
- [Fact(Skip = SkipReason)]
- public override async Task UsingTextSearchWithAFilterAsync()
- {
- await base.UsingTextSearchWithAFilterAsync();
- }
-
- [Fact(Skip = SkipReason)]
- public override async Task FunctionCallingUsingCreateWithSearchAsync()
- {
- await base.FunctionCallingUsingCreateWithSearchAsync();
- }
-
- [Fact(Skip = SkipReason)]
- public override async Task FunctionCallingUsingCreateWithGetSearchResultsAsync()
- {
- await base.FunctionCallingUsingCreateWithGetSearchResultsAsync();
- }
-
- [Fact(Skip = SkipReason)]
- public override async Task FunctionCallingUsingGetTextSearchResultsAsync()
- {
- await base.FunctionCallingUsingGetTextSearchResultsAsync();
- }
-
- ///
- public override Task CreateTextSearchAsync()
- {
- if (this.VectorStore is null)
- {
- AzureOpenAIConfiguration? azureOpenAIConfiguration = this.Configuration.GetSection("AzureOpenAIEmbeddings").Get();
- Assert.NotNull(azureOpenAIConfiguration);
- Assert.NotEmpty(azureOpenAIConfiguration.DeploymentName);
- Assert.NotEmpty(azureOpenAIConfiguration.Endpoint);
-
- this.EmbeddingGenerator = new AzureOpenAIClient(new Uri(azureOpenAIConfiguration.Endpoint), new AzureCliCredential())
- .GetEmbeddingClient(azureOpenAIConfiguration.DeploymentName)
- .AsIEmbeddingGenerator();
-
- this.VectorStore = new AzureAISearchVectorStore(fixture.SearchIndexClient, new() { EmbeddingGenerator = this.EmbeddingGenerator });
- }
-
- var vectorSearch = this.VectorStore.GetCollection(fixture.TestIndexName);
- var stringMapper = new HotelTextSearchStringMapper();
- var resultMapper = new HotelTextSearchResultMapper();
-
- // TODO: Once OpenAITextEmbeddingGenerationService implements MEAI's IEmbeddingGenerator (#10811), configure it with the AzureAISearchVectorStore above instead of passing it here.
- var result = new VectorStoreTextSearch(vectorSearch, this.EmbeddingGenerator!, stringMapper, resultMapper);
-
- return Task.FromResult(result);
- }
-
- ///
- public override string GetQuery() => "Find a great hotel";
-
- ///
- public override TextSearchFilter GetTextSearchFilter() => new TextSearchFilter().Equality("Rating", 3.6);
-
- ///
- public override bool VerifySearchResults(object[] results, string query, TextSearchFilter? filter = null)
- {
- Assert.NotNull(results);
- Assert.NotEmpty(results);
- Assert.Equal(filter is null ? 4 : 2, results.Length);
- foreach (var result in results)
- {
- Assert.NotNull(result);
- Assert.IsType(result);
- }
-
- return true;
- }
-
- ///
- /// String mapper which converts a Hotel to a string.
- ///
- protected sealed class HotelTextSearchStringMapper : ITextSearchStringMapper
- {
- ///
- public string MapFromResultToString(object result)
- {
- if (result is AzureAISearchHotel hotel)
- {
- return $"{hotel.HotelName} {hotel.Description}";
- }
- throw new ArgumentException("Invalid result type.");
- }
- }
-
- ///
- /// Result mapper which converts a Hotel to a TextSearchResult.
- ///
- protected sealed class HotelTextSearchResultMapper : ITextSearchResultMapper
- {
- ///
- public TextSearchResult MapFromResultToTextSearchResult(object result)
- {
- if (result is AzureAISearchHotel hotel)
- {
- return new TextSearchResult(value: hotel.Description) { Name = hotel.HotelName, Link = $"id://{hotel.HotelId}" };
- }
- throw new ArgumentException("Invalid result type.");
- }
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreCollectionFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreCollectionFixture.cs
deleted file mode 100644
index 6c9870cf0327..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreCollectionFixture.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.AzureAISearch;
-
-[CollectionDefinition("AzureAISearchVectorStoreCollection")]
-public class AzureAISearchVectorStoreCollectionFixture : ICollectionFixture
-{
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreFixture.cs
deleted file mode 100644
index d70c4e444efa..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreFixture.cs
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Linq;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using Azure;
-using Azure.AI.OpenAI;
-using Azure.Identity;
-using Azure.Search.Documents;
-using Azure.Search.Documents.Indexes;
-using Azure.Search.Documents.Indexes.Models;
-using Azure.Search.Documents.Models;
-using Microsoft.Extensions.AI;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.VectorData;
-using SemanticKernel.IntegrationTests.TestSettings;
-using SemanticKernel.IntegrationTests.TestSettings.Memory;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.AzureAISearch;
-
-///
-/// Helper class for setting up and tearing down Azure AI Search indexes for testing purposes.
-///
-public class AzureAISearchVectorStoreFixture : IAsyncLifetime
-{
- ///
- /// Test index name which consists out of "hotels-" and the machine name with any non-alphanumeric characters removed.
- ///
- private readonly string _testIndexName = "hotels-" + TestIndexPostfix;
-
- ///
- /// Gets the test index name postfix that is derived from the local machine name used to avoid clashes between test runs from different callers.
- ///
-#pragma warning disable CA1308 // Normalize strings to uppercase
- public static string TestIndexPostfix { get; private set; } = new Regex("[^a-zA-Z0-9]").Replace(Environment.MachineName.ToLowerInvariant(), "");
-#pragma warning restore CA1308 // Normalize strings to uppercase
-
- ///
- /// Test Configuration setup.
- ///
- private static readonly IConfigurationRoot s_configuration = new ConfigurationBuilder()
- .AddJsonFile(path: "testsettings.json", optional: false, reloadOnChange: true)
- .AddJsonFile(path: "testsettings.development.json", optional: true, reloadOnChange: true)
- .AddEnvironmentVariables()
- .AddUserSecrets()
- .Build();
-
- ///
- /// Get the test configuration for Azure AI Search.
- ///
- public static AzureAISearchConfiguration? GetAzureAISearchConfiguration()
- {
- return s_configuration.GetSection("AzureAISearch").Get();
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public AzureAISearchVectorStoreFixture()
- {
- var config = GetAzureAISearchConfiguration();
- Assert.NotNull(config);
- this.Config = config;
- this.SearchIndexClient = new SearchIndexClient(new Uri(config.ServiceUrl), new AzureKeyCredential(config.ApiKey));
- this.VectorStoreRecordDefinition = new VectorStoreCollectionDefinition
- {
- Properties =
- [
- new VectorStoreKeyProperty("HotelId", typeof(string)),
- new VectorStoreDataProperty("HotelName", typeof(string)) { IsIndexed = true, IsFullTextIndexed = true },
- new VectorStoreDataProperty("Description", typeof(string)),
- new VectorStoreVectorProperty("DescriptionEmbedding", typeof(ReadOnlyMemory?), 1536),
- new VectorStoreDataProperty("Tags", typeof(string[])) { IsIndexed = true },
- new VectorStoreDataProperty("ParkingIncluded", typeof(bool?)) { IsIndexed = true, StorageName = "parking_is_included" },
- new VectorStoreDataProperty("LastRenovationDate", typeof(DateTimeOffset?)) { IsIndexed = true },
- new VectorStoreDataProperty("Rating", typeof(double?))
- ]
- };
- AzureOpenAIConfiguration? embeddingsConfig = s_configuration.GetSection("AzureOpenAIEmbeddings").Get();
- Assert.NotNull(embeddingsConfig);
- Assert.NotEmpty(embeddingsConfig.DeploymentName);
- Assert.NotEmpty(embeddingsConfig.Endpoint);
-
- this.EmbeddingGenerator = new AzureOpenAIClient(new Uri(embeddingsConfig.Endpoint), new AzureCliCredential())
- .GetEmbeddingClient(embeddingsConfig.DeploymentName)
- .AsIEmbeddingGenerator();
- }
-
- ///
- /// Gets the Search Index Client to use for connecting to the Azure AI Search service.
- ///
- public SearchIndexClient SearchIndexClient { get; private set; }
-
- ///
- /// Gets the name of the index that this fixture sets up and tears down.
- ///
- public string TestIndexName { get => this._testIndexName; }
-
- ///
- /// Gets the manually created vector store record definition for our test model.
- ///
- public VectorStoreCollectionDefinition VectorStoreRecordDefinition { get; private set; }
-
- ///
- /// Gets the configuration for the Azure AI Search service.
- ///
- public AzureAISearchConfiguration Config { get; private set; }
-
- ///
- /// Gets the embedding generator to use for generating embeddings for text.
- ///
- public IEmbeddingGenerator> EmbeddingGenerator { get; private set; }
-
- ///
- /// Gets the embedding used for all test documents that the collection is seeded with.
- ///
- public ReadOnlyMemory Embedding { get; private set; }
-
- ///
- /// Create / Recreate index and upload documents before test run.
- ///
- /// An async task.
- public async Task InitializeAsync()
- {
- await AzureAISearchVectorStoreFixture.DeleteIndexIfExistsAsync(this._testIndexName, this.SearchIndexClient);
- await AzureAISearchVectorStoreFixture.CreateIndexAsync(this._testIndexName, this.SearchIndexClient);
- await this.UploadDocumentsAsync(this.SearchIndexClient.GetSearchClient(this._testIndexName), this.EmbeddingGenerator);
- }
-
- ///
- /// Delete the index after the test run.
- ///
- /// An async task.
- public async Task DisposeAsync()
- {
- await AzureAISearchVectorStoreFixture.DeleteIndexIfExistsAsync(this._testIndexName, this.SearchIndexClient);
- }
-
- ///
- /// Delete the index if it exists.
- ///
- /// The name of the index to delete.
- /// The search index client to use for deleting the index.
- /// An async task.
- public static async Task DeleteIndexIfExistsAsync(string indexName, SearchIndexClient adminClient)
- {
- adminClient.GetIndexNames();
- {
- await adminClient.DeleteIndexAsync(indexName);
- }
- }
-
- ///
- /// Create an index with the given name.
- ///
- /// The name of the index to create.
- /// The search index client to use for creating the index.
- /// An async task.
- public static async Task CreateIndexAsync(string indexName, SearchIndexClient adminClient)
- {
- AzureOpenAIConfiguration openAIConfiguration = s_configuration.GetRequiredSection("AzureOpenAIEmbeddings").Get()!;
-
- // Build the list of fields from the model, and then replace the DescriptionEmbedding field with a vector field, to work around
- // issue where the field is not recognized as an array on parsing on the server side when apply the VectorSearchFieldAttribute.
- FieldBuilder fieldBuilder = new();
- var searchFields = fieldBuilder.Build(typeof(AzureAISearchHotel));
- var embeddingfield = searchFields.First(x => x.Name == "DescriptionEmbedding");
- searchFields.Remove(embeddingfield);
- searchFields.Add(new VectorSearchField("DescriptionEmbedding", 1536, "my-vector-profile"));
-
- // Create an index definition with a vectorizer to use when doing vector searches using text.
- var definition = new SearchIndex(indexName, searchFields)
- {
- VectorSearch = new VectorSearch()
- };
- definition.VectorSearch.Vectorizers.Add(new AzureOpenAIVectorizer("text-embedding-vectorizer")
- {
- Parameters = new AzureOpenAIVectorizerParameters
- {
- ResourceUri = new Uri(openAIConfiguration.Endpoint),
- DeploymentName = openAIConfiguration.DeploymentName,
- ApiKey = openAIConfiguration.ApiKey,
- ModelName = openAIConfiguration.EmbeddingModelId
- }
- });
- definition.VectorSearch.Algorithms.Add(new HnswAlgorithmConfiguration("my-hnsw-vector-config-1") { Parameters = new HnswParameters { Metric = VectorSearchAlgorithmMetric.Cosine } });
- definition.VectorSearch.Profiles.Add(new VectorSearchProfile("my-vector-profile", "my-hnsw-vector-config-1") { VectorizerName = "text-embedding-vectorizer" });
-
- var suggester = new SearchSuggester("sg", new[] { "HotelName" });
- definition.Suggesters.Add(suggester);
-
- await adminClient.CreateOrUpdateIndexAsync(definition);
- }
-
- ///
- /// Upload test documents to the index.
- ///
- /// The client to use for uploading the documents.
- /// An instance of to generate embeddings.
- public async Task UploadDocumentsAsync(SearchClient searchClient, IEmbeddingGenerator> embeddingGenerator)
- {
- this.Embedding = (await embeddingGenerator.GenerateAsync("This is a great hotel")).Vector;
-
- IndexDocumentsBatch batch = IndexDocumentsBatch.Create(
- IndexDocumentsAction.Upload(
- new AzureAISearchHotel()
- {
- HotelId = "BaseSet-1",
- HotelName = "Hotel 1",
- Description = "This is a great hotel",
- DescriptionEmbedding = this.Embedding,
- Tags = new[] { "pool", "air conditioning", "concierge" },
- ParkingIncluded = false,
- LastRenovationDate = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
- Rating = 3.6
- }),
- IndexDocumentsAction.Upload(
- new AzureAISearchHotel()
- {
- HotelId = "BaseSet-2",
- HotelName = "Hotel 2",
- Description = "This is a great hotel",
- DescriptionEmbedding = this.Embedding,
- Tags = new[] { "pool", "free wifi", "concierge" },
- ParkingIncluded = false,
- LastRenovationDate = new DateTimeOffset(1979, 2, 18, 0, 0, 0, TimeSpan.Zero),
- Rating = 3.60
- }),
- IndexDocumentsAction.Upload(
- new AzureAISearchHotel()
- {
- HotelId = "BaseSet-3",
- HotelName = "Hotel 3",
- Description = "This is a great hotel",
- DescriptionEmbedding = this.Embedding,
- Tags = new[] { "air conditioning", "bar", "continental breakfast" },
- ParkingIncluded = true,
- LastRenovationDate = new DateTimeOffset(2015, 9, 20, 0, 0, 0, TimeSpan.Zero),
- Rating = 4.80
- }),
- IndexDocumentsAction.Upload(
- new AzureAISearchHotel()
- {
- HotelId = "BaseSet-4",
- HotelName = "Hotel 4",
- Description = "This is a great hotel",
- DescriptionEmbedding = this.Embedding,
- Tags = new[] { "concierge", "view", "24-hour front desk service" },
- ParkingIncluded = true,
- LastRenovationDate = new DateTimeOffset(1960, 2, 06, 0, 0, 0, TimeSpan.Zero),
- Rating = 4.60
- })
- );
-
- await searchClient.IndexDocumentsAsync(batch);
-
- // Add some delay to allow time for the documents to get indexed and show up in search.
- await Task.Delay(5000);
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreRecordCollectionTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreRecordCollectionTests.cs
deleted file mode 100644
index 4d7a7c5a725b..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreRecordCollectionTests.cs
+++ /dev/null
@@ -1,426 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Azure;
-using Azure.Search.Documents.Indexes;
-using Microsoft.Extensions.VectorData;
-using Microsoft.SemanticKernel.Connectors.AzureAISearch;
-using Xunit;
-using Xunit.Abstractions;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.AzureAISearch;
-
-#pragma warning disable CS0618 // VectorSearchFilter is obsolete
-
-///
-/// Integration tests for class.
-/// Tests work with an Azure AI Search Instance.
-///
-[Collection("AzureAISearchVectorStoreCollection")]
-public sealed class AzureAISearchVectorStoreRecordCollectionTests(ITestOutputHelper output, AzureAISearchVectorStoreFixture fixture)
-{
- // If null, all tests will be enabled
- private const string SkipReason = "Requires Azure AI Search Service instance up and running";
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task CollectionExistsReturnsCollectionStateAsync(bool expectedExists)
- {
- // Arrange.
- var collectionName = expectedExists ? fixture.TestIndexName : "nonexistentcollection";
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, collectionName);
-
- // Act.
- var actual = await sut.CollectionExistsAsync();
-
- // Assert.
- Assert.Equal(expectedExists, actual);
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task ItCanCreateACollectionUpsertGetAndSearchAsync(bool useRecordDefinition)
- {
- // Arrange
- var hotel = this.CreateTestHotel("Upsert-1");
- var testCollectionName = $"{fixture.TestIndexName}-createtest";
- var options = new AzureAISearchCollectionOptions
- {
- Definition = useRecordDefinition ? fixture.VectorStoreRecordDefinition : null
- };
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, testCollectionName, options);
-
- await sut.EnsureCollectionDeletedAsync();
-
- // Act
- await sut.EnsureCollectionExistsAsync();
- await sut.UpsertAsync(hotel);
- var getResult = await sut.GetAsync("Upsert-1", new() { IncludeVectors = true });
- var embedding = fixture.Embedding;
- var searchResults = await sut.SearchAsync(
- embedding,
- top: 3,
- new()
- {
- IncludeVectors = true,
- OldFilter = new VectorSearchFilter().EqualTo("HotelName", "MyHotel Upsert-1")
- }).ToListAsync();
-
- // Assert
- var collectionExistResult = await sut.CollectionExistsAsync();
- Assert.True(collectionExistResult);
- await sut.EnsureCollectionDeletedAsync();
-
- Assert.NotNull(getResult);
- Assert.Equal(hotel.HotelName, getResult.HotelName);
- Assert.Equal(hotel.Description, getResult.Description);
- Assert.NotNull(getResult.DescriptionEmbedding);
- Assert.Equal(hotel.DescriptionEmbedding?.ToArray(), getResult.DescriptionEmbedding?.ToArray());
- Assert.Equal(hotel.Tags, getResult.Tags);
- Assert.Equal(hotel.ParkingIncluded, getResult.ParkingIncluded);
- Assert.Equal(hotel.LastRenovationDate, getResult.LastRenovationDate);
- Assert.Equal(hotel.Rating, getResult.Rating);
-
- Assert.Single(searchResults);
- var searchResultRecord = searchResults.First().Record;
- Assert.Equal(hotel.HotelName, searchResultRecord.HotelName);
- Assert.Equal(hotel.Description, searchResultRecord.Description);
- Assert.NotNull(searchResultRecord.DescriptionEmbedding);
- Assert.Equal(hotel.DescriptionEmbedding?.ToArray(), searchResultRecord.DescriptionEmbedding?.ToArray());
- Assert.Equal(hotel.Tags, searchResultRecord.Tags);
- Assert.Equal(hotel.ParkingIncluded, searchResultRecord.ParkingIncluded);
- Assert.Equal(hotel.LastRenovationDate, searchResultRecord.LastRenovationDate);
- Assert.Equal(hotel.Rating, searchResultRecord.Rating);
-
- // Output
- output.WriteLine(collectionExistResult.ToString());
- output.WriteLine(getResult.ToString());
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanDeleteCollectionAsync()
- {
- // Arrange
- var tempCollectionName = fixture.TestIndexName + "-delete";
- await AzureAISearchVectorStoreFixture.CreateIndexAsync(tempCollectionName, fixture.SearchIndexClient);
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, tempCollectionName);
-
- // Act
- await sut.EnsureCollectionDeletedAsync();
-
- // Assert
- Assert.False(await sut.CollectionExistsAsync());
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task ItCanUpsertDocumentToVectorStoreAsync(bool useRecordDefinition)
- {
- // Arrange
- var options = new AzureAISearchCollectionOptions
- {
- Definition = useRecordDefinition ? fixture.VectorStoreRecordDefinition : null
- };
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, fixture.TestIndexName, options);
-
- // Act
- var hotel = this.CreateTestHotel("Upsert-1");
- await sut.UpsertAsync(hotel);
- var getResult = await sut.GetAsync("Upsert-1", new() { IncludeVectors = true });
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal(hotel.HotelName, getResult.HotelName);
- Assert.Equal(hotel.Description, getResult.Description);
- Assert.NotNull(getResult.DescriptionEmbedding);
- Assert.Equal(hotel.DescriptionEmbedding?.ToArray(), getResult.DescriptionEmbedding?.ToArray());
- Assert.Equal(hotel.Tags, getResult.Tags);
- Assert.Equal(hotel.ParkingIncluded, getResult.ParkingIncluded);
- Assert.Equal(hotel.LastRenovationDate, getResult.LastRenovationDate);
- Assert.Equal(hotel.Rating, getResult.Rating);
-
- // Output
- output.WriteLine(getResult.ToString());
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanUpsertManyDocumentsToVectorStoreAsync()
- {
- // Arrange
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, fixture.TestIndexName);
-
- // Act
- await sut.UpsertAsync(
- [
- this.CreateTestHotel("UpsertMany-1"),
- this.CreateTestHotel("UpsertMany-2"),
- this.CreateTestHotel("UpsertMany-3"),
- ]);
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true, true)]
- [InlineData(true, false)]
- [InlineData(false, true)]
- [InlineData(false, false)]
- public async Task ItCanGetDocumentFromVectorStoreAsync(bool includeVectors, bool useRecordDefinition)
- {
- // Arrange
- var options = new AzureAISearchCollectionOptions
- {
- Definition = useRecordDefinition ? fixture.VectorStoreRecordDefinition : null
- };
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, fixture.TestIndexName, options);
-
- // Act
- var getResult = await sut.GetAsync("BaseSet-1", new RecordRetrievalOptions { IncludeVectors = includeVectors });
-
- // Assert
- Assert.NotNull(getResult);
-
- Assert.Equal("Hotel 1", getResult.HotelName);
- Assert.Equal("This is a great hotel", getResult.Description);
- Assert.Equal(includeVectors, getResult.DescriptionEmbedding != null);
- if (includeVectors)
- {
- var embedding = fixture.Embedding;
- Assert.Equal(embedding, getResult.DescriptionEmbedding!.Value.ToArray());
- }
- else
- {
- Assert.Null(getResult.DescriptionEmbedding);
- }
- Assert.Equal(new[] { "pool", "air conditioning", "concierge" }, getResult.Tags);
- Assert.False(getResult.ParkingIncluded);
- Assert.Equal(new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero), getResult.LastRenovationDate);
- Assert.Equal(3.6, getResult.Rating);
-
- // Output
- output.WriteLine(getResult.ToString());
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanGetManyDocumentsFromVectorStoreAsync()
- {
- // Arrange
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, fixture.TestIndexName);
-
- // Act
- // Also include one non-existing key to test that the operation does not fail for these and returns only the found ones.
- var hotels = sut.GetAsync(["BaseSet-1", "BaseSet-2", "BaseSet-3", "BaseSet-5", "BaseSet-4"], new RecordRetrievalOptions { IncludeVectors = true });
-
- // Assert
- Assert.NotNull(hotels);
- var hotelsList = await hotels.ToListAsync();
- Assert.Equal(4, hotelsList.Count);
-
- // Output
- foreach (var hotel in hotelsList)
- {
- output.WriteLine(hotel.ToString());
- }
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task ItCanRemoveDocumentFromVectorStoreAsync(bool useRecordDefinition)
- {
- // Arrange
- var options = new AzureAISearchCollectionOptions
- {
- Definition = useRecordDefinition ? fixture.VectorStoreRecordDefinition : null
- };
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, fixture.TestIndexName);
- await sut.UpsertAsync(this.CreateTestHotel("Remove-1"));
-
- // Act
- await sut.DeleteAsync("Remove-1");
- // Also delete a non-existing key to test that the operation does not fail for these.
- await sut.DeleteAsync("Remove-2");
-
- // Assert
- Assert.Null(await sut.GetAsync("Remove-1", new RecordRetrievalOptions { IncludeVectors = true }));
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanRemoveManyDocumentsFromVectorStoreAsync()
- {
- // Arrange
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, fixture.TestIndexName);
- await sut.UpsertAsync(this.CreateTestHotel("RemoveMany-1"));
- await sut.UpsertAsync(this.CreateTestHotel("RemoveMany-2"));
- await sut.UpsertAsync(this.CreateTestHotel("RemoveMany-3"));
-
- // Act
- // Also include a non-existing key to test that the operation does not fail for these.
- await sut.DeleteAsync(["RemoveMany-1", "RemoveMany-2", "RemoveMany-3", "RemoveMany-4"]);
-
- // Assert
- Assert.Null(await sut.GetAsync("RemoveMany-1", new RecordRetrievalOptions { IncludeVectors = true }));
- Assert.Null(await sut.GetAsync("RemoveMany-2", new RecordRetrievalOptions { IncludeVectors = true }));
- Assert.Null(await sut.GetAsync("RemoveMany-3", new RecordRetrievalOptions { IncludeVectors = true }));
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItReturnsNullWhenGettingNonExistentRecordAsync()
- {
- // Arrange
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, fixture.TestIndexName);
-
- // Act & Assert
- Assert.Null(await sut.GetAsync("BaseSet-5", new RecordRetrievalOptions { IncludeVectors = true }));
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItThrowsOperationExceptionForFailedConnectionAsync()
- {
- // Arrange
- var searchIndexClient = new SearchIndexClient(new Uri("https://localhost:12345"), new AzureKeyCredential("12345"));
- using var sut = new AzureAISearchCollection(searchIndexClient, fixture.TestIndexName);
-
- // Act & Assert
- await Assert.ThrowsAsync(async () => await sut.GetAsync("BaseSet-1", new RecordRetrievalOptions { IncludeVectors = true }));
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItThrowsOperationExceptionForFailedAuthenticationAsync()
- {
- // Arrange
- var searchIndexClient = new SearchIndexClient(new Uri(fixture.Config.ServiceUrl), new AzureKeyCredential("12345"));
- using var sut = new AzureAISearchCollection(searchIndexClient, fixture.TestIndexName);
-
- // Act & Assert
- await Assert.ThrowsAsync(async () => await sut.GetAsync("BaseSet-1", new RecordRetrievalOptions { IncludeVectors = true }));
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData("equality", true)]
- [InlineData("tagContains", false)]
- public async Task ItCanSearchWithVectorAndFiltersAsync(string option, bool includeVectors)
- {
- // Arrange.
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, fixture.TestIndexName);
-
- // Act.
- var filter = option == "equality" ? new VectorSearchFilter().EqualTo("HotelName", "Hotel 3") : new VectorSearchFilter().AnyTagEqualTo("Tags", "bar");
- var searchResults = await sut.SearchAsync(
- fixture.Embedding,
- top: 3,
- new()
- {
- IncludeVectors = includeVectors,
- VectorProperty = r => r.DescriptionEmbedding,
- OldFilter = filter,
- }).ToListAsync();
-
- // Assert.
- Assert.Single(searchResults);
- var searchResult = searchResults.First();
- Assert.Equal("BaseSet-3", searchResult.Record.HotelId);
- Assert.Equal("Hotel 3", searchResult.Record.HotelName);
- Assert.Equal("This is a great hotel", searchResult.Record.Description);
- Assert.Equal(new[] { "air conditioning", "bar", "continental breakfast" }, searchResult.Record.Tags);
- Assert.True(searchResult.Record.ParkingIncluded);
- Assert.Equal(new DateTimeOffset(2015, 9, 20, 0, 0, 0, TimeSpan.Zero), searchResult.Record.LastRenovationDate);
- Assert.Equal(4.8, searchResult.Record.Rating);
- if (includeVectors)
- {
- Assert.NotNull(searchResult.Record.DescriptionEmbedding);
- var embedding = fixture.Embedding;
- Assert.Equal(embedding, searchResult.Record.DescriptionEmbedding!.Value.ToArray());
- }
- else
- {
- Assert.Null(searchResult.Record.DescriptionEmbedding);
- }
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanSearchWithTextAndFiltersAsync()
- {
- // Arrange.
- using var sut = new AzureAISearchCollection(fixture.SearchIndexClient, fixture.TestIndexName);
-
- // Act.
- var filter = new VectorSearchFilter().EqualTo("HotelName", "Hotel 3");
- var searchResults = await sut.SearchAsync(
- "A hotel with great views.",
- top: 3,
- new()
- {
- VectorProperty = r => r.DescriptionEmbedding,
- OldFilter = filter,
- }).ToListAsync();
-
- // Assert.
- Assert.Single(searchResults);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
- {
- // Arrange
- var options = new AzureAISearchCollectionOptions
- {
- Definition = fixture.VectorStoreRecordDefinition
- };
- using var sut = new AzureAISearchDynamicCollection(fixture.SearchIndexClient, fixture.TestIndexName, options);
-
- // Act
- var baseSetGetResult = await sut.GetAsync("BaseSet-1", new RecordRetrievalOptions { IncludeVectors = true });
- var baseSetEmbedding = fixture.Embedding;
- var dynamicMapperEmbedding = fixture.Embedding;
- await sut.UpsertAsync(new Dictionary
- {
- ["HotelId"] = "DynamicMapper-1",
-
- ["HotelName"] = "Dynamic Mapper Hotel",
- ["Description"] = "This is a dynamic mapper hotel",
- ["Tags"] = new string[] { "dynamic" },
- ["ParkingIncluded"] = false,
- ["LastRenovationDate"] = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
- ["Rating"] = 3.6d,
-
- ["DescriptionEmbedding"] = dynamicMapperEmbedding
- });
- var localGetResult = await sut.GetAsync("DynamicMapper-1", new RecordRetrievalOptions { IncludeVectors = true });
-
- // Assert
- Assert.NotNull(baseSetGetResult);
- Assert.Equal("Hotel 1", baseSetGetResult["HotelName"]);
- Assert.Equal("This is a great hotel", baseSetGetResult["Description"]);
- Assert.Equal(new[] { "pool", "air conditioning", "concierge" }, baseSetGetResult["Tags"]);
- Assert.False((bool?)baseSetGetResult["ParkingIncluded"]);
- Assert.Equal(new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero), baseSetGetResult["LastRenovationDate"]);
- Assert.Equal(3.6d, baseSetGetResult["Rating"]);
- Assert.Equal(baseSetEmbedding, (ReadOnlyMemory)baseSetGetResult["DescriptionEmbedding"]!);
-
- Assert.NotNull(localGetResult);
- Assert.Equal("Dynamic Mapper Hotel", localGetResult["HotelName"]);
- Assert.Equal("This is a dynamic mapper hotel", localGetResult["Description"]);
- Assert.Equal(new[] { "dynamic" }, localGetResult["Tags"]);
- Assert.False((bool?)localGetResult["ParkingIncluded"]);
- Assert.Equal(new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero), localGetResult["LastRenovationDate"]);
- Assert.Equal(3.6d, localGetResult["Rating"]);
- Assert.Equal(dynamicMapperEmbedding, (ReadOnlyMemory)localGetResult["DescriptionEmbedding"]!);
- }
-
- private AzureAISearchHotel CreateTestHotel(string hotelId) => new()
- {
- HotelId = hotelId,
- HotelName = $"MyHotel {hotelId}",
- Description = "My Hotel is great.",
- DescriptionEmbedding = fixture.Embedding,
- Tags = ["pool", "air conditioning", "concierge"],
- ParkingIncluded = true,
- LastRenovationDate = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
- Rating = 3.6
- };
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreTests.cs
deleted file mode 100644
index a7b5781b74c0..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreTests.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Microsoft.SemanticKernel.Connectors.AzureAISearch;
-using SemanticKernel.IntegrationTests.Connectors.Memory.Xunit;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.AzureAISearch;
-
-///
-/// Contains integration tests for the class.
-/// Tests work with an Azure AI Search Instance.
-///
-[Collection("AzureAISearchVectorStoreCollection")]
-[DisableVectorStoreTests(Skip = "Requires Azure AI Search Service instance up and running")]
-public class AzureAISearchVectorStoreTests(AzureAISearchVectorStoreFixture fixture)
-#pragma warning disable CA2000 // Dispose objects before losing scope
- : BaseVectorStoreTests(new AzureAISearchVectorStore(fixture.SearchIndexClient))
-#pragma warning restore CA2000 // Dispose objects before losing scope
-{
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/BaseVectorStoreRecordCollectionTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/BaseVectorStoreRecordCollectionTests.cs
deleted file mode 100644
index b65cd105be10..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/BaseVectorStoreRecordCollectionTests.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.Extensions.VectorData;
-using SemanticKernel.IntegrationTests.Connectors.Memory.Xunit;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory;
-
-///
-/// Base class for common integration tests that should pass for any .
-///
-/// The type of key to use with the record collection.
-public abstract class BaseVectorStoreRecordCollectionTests
- where TKey : notnull
-{
- protected abstract TKey Key1 { get; }
- protected abstract TKey Key2 { get; }
- protected abstract TKey Key3 { get; }
- protected abstract TKey Key4 { get; }
-
- protected abstract HashSet GetSupportedDistanceFunctions();
-
- protected abstract VectorStoreCollection GetTargetRecordCollection(string recordCollectionName, VectorStoreCollectionDefinition? definition) where TRecord : class;
-
- protected virtual int DelayAfterIndexCreateInMilliseconds { get; } = 0;
-
- protected virtual int DelayAfterUploadInMilliseconds { get; } = 0;
-
- [VectorStoreTheory]
- [InlineData(DistanceFunction.CosineDistance, 0, 2, 1, new int[] { 0, 2, 1 })]
- [InlineData(DistanceFunction.CosineSimilarity, 1, -1, 0, new int[] { 0, 2, 1 })]
- [InlineData(DistanceFunction.DotProductSimilarity, 1, -1, 0, new int[] { 0, 2, 1 })]
- [InlineData(DistanceFunction.EuclideanDistance, 0, 2, 1.73, new int[] { 0, 2, 1 })]
- [InlineData(DistanceFunction.EuclideanSquaredDistance, 0, 4, 3, new int[] { 0, 2, 1 })]
- [InlineData(DistanceFunction.HammingDistance, 0, 1, 3, new int[] { 0, 1, 2 })]
- [InlineData(DistanceFunction.ManhattanDistance, 0, 2, 3, new int[] { 0, 1, 2 })]
- public async Task VectorSearchShouldReturnExpectedScoresAsync(string distanceFunction, double expectedExactMatchScore, double expectedOppositeScore, double expectedOrthogonalScore, int[] resultOrder)
- {
- var keyDictionary = new Dictionary
- {
- { 0, this.Key1 },
- { 1, this.Key2 },
- { 2, this.Key3 },
- };
- var scoreDictionary = new Dictionary
- {
- { 0, expectedExactMatchScore },
- { 1, expectedOppositeScore },
- { 2, expectedOrthogonalScore },
- };
-
- // Don't test unsupported distance functions.
- var supportedDistanceFunctions = this.GetSupportedDistanceFunctions();
- if (!supportedDistanceFunctions.Contains(distanceFunction))
- {
- return;
- }
-
- // Arrange
- var definition = CreateKeyWithVectorRecordDefinition(4, distanceFunction);
- var sut = this.GetTargetRecordCollection>(
- $"scorebydf{distanceFunction}",
- definition);
-
- await sut.EnsureCollectionExistsAsync();
- await Task.Delay(this.DelayAfterIndexCreateInMilliseconds);
-
- // Create two vectors that are opposite to each other and records that use these
- // plus a further vector that is orthogonal to the base vector.
- var baseVector = new ReadOnlyMemory([1, 0, 0, 0]);
- var oppositeVector = new ReadOnlyMemory([-1, 0, 0, 0]);
- var orthogonalVector = new ReadOnlyMemory([0f, -1f, -1f, 0f]);
-
- var baseRecord = new KeyWithVectorRecord
- {
- Key = this.Key1,
- Vector = baseVector,
- };
-
- var oppositeRecord = new KeyWithVectorRecord
- {
- Key = this.Key2,
- Vector = oppositeVector,
- };
-
- var orthogonalRecord = new KeyWithVectorRecord
- {
- Key = this.Key3,
- Vector = orthogonalVector,
- };
-
- await sut.UpsertAsync([baseRecord, oppositeRecord, orthogonalRecord]);
- await Task.Delay(this.DelayAfterUploadInMilliseconds);
-
- // Act
- var results = await sut.SearchAsync(baseVector, top: 3).ToListAsync();
-
- // Assert
- Assert.Equal(3, results.Count);
-
- Assert.Equal(keyDictionary[resultOrder[0]], results[0].Record.Key);
- Assert.Equal(Math.Round(scoreDictionary[resultOrder[0]], 2), Math.Round(results[0].Score!.Value, 2));
-
- Assert.Equal(keyDictionary[resultOrder[1]], results[1].Record.Key);
- Assert.Equal(Math.Round(scoreDictionary[resultOrder[1]], 2), Math.Round(results[1].Score!.Value, 2));
-
- Assert.Equal(keyDictionary[resultOrder[2]], results[2].Record.Key);
- Assert.Equal(Math.Round(scoreDictionary[resultOrder[2]], 2), Math.Round(results[2].Score!.Value, 2));
-
- // Cleanup
- await sut.EnsureCollectionDeletedAsync();
- }
-
- private static VectorStoreCollectionDefinition CreateKeyWithVectorRecordDefinition(int vectorDimensions, string distanceFunction)
- {
- var definition = new VectorStoreCollectionDefinition
- {
- Properties =
- [
- new VectorStoreKeyProperty("Key", typeof(TKey)),
- new VectorStoreVectorProperty("Vector", typeof(ReadOnlyMemory), vectorDimensions) { DistanceFunction = distanceFunction },
- ],
- };
-
- return definition;
- }
-
- private sealed class KeyWithVectorRecord
- {
- public required TRecordKey Key { get; set; }
-
- public ReadOnlyMemory Vector { get; set; }
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/BaseVectorStoreTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/BaseVectorStoreTests.cs
deleted file mode 100644
index e81987050487..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/BaseVectorStoreTests.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.Extensions.VectorData;
-using SemanticKernel.IntegrationTests.Connectors.Memory.Xunit;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory;
-
-///
-/// Base class for integration tests.
-///
-public abstract class BaseVectorStoreTests(VectorStore vectorStore)
- where TKey : notnull
- where TRecord : class
-{
- protected virtual IEnumerable CollectionNames => ["listcollectionnames1", "listcollectionnames2", "listcollectionnames3"];
-
- [VectorStoreFact]
- public virtual async Task ItCanGetAListOfExistingCollectionNamesAsync()
- {
- // Arrange
- var expectedCollectionNames = this.CollectionNames;
-
- foreach (var collectionName in expectedCollectionNames)
- {
- var collection = vectorStore.GetCollection(collectionName);
-
- await collection.EnsureCollectionExistsAsync();
- }
-
- // Act
- var actualCollectionNames = await vectorStore.ListCollectionNamesAsync().ToListAsync();
-
- // Assert
- var expected = expectedCollectionNames.Select(l => l.ToUpperInvariant()).ToList();
- var actual = actualCollectionNames.Select(l => l.ToUpperInvariant()).ToList();
-
- expected.ForEach(item => Assert.Contains(item, actual));
-
- // Cleanup
- foreach (var collectionName in expectedCollectionNames)
- {
- var collection = vectorStore.GetCollection(collectionName);
-
- await collection.EnsureCollectionDeletedAsync();
- }
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/Chroma/ChromaMemoryStoreTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/Chroma/ChromaMemoryStoreTests.cs
deleted file mode 100644
index 770400778817..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/Chroma/ChromaMemoryStoreTests.cs
+++ /dev/null
@@ -1,472 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Net.Http;
-using System.Threading.Tasks;
-using Microsoft.SemanticKernel;
-using Microsoft.SemanticKernel.Connectors.Chroma;
-using Microsoft.SemanticKernel.Memory;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Chroma;
-
-///
-/// Integration tests for class.
-/// Tests work with local Chroma server. To setup the server, see dotnet/src/Connectors/Connectors.Memory.Chroma/README.md.
-///
-[Experimental("SKEXP0020")]
-public sealed class ChromaMemoryStoreTests : IDisposable
-{
- // If null, all tests will be enabled
- private const string SkipReason = "Requires Chroma server up and running";
-
- private const string BaseAddress = "http://localhost:8000";
-
- public ChromaMemoryStoreTests()
- {
- this._httpClient = new()
- {
- BaseAddress = new Uri(BaseAddress)
- };
-
- this._chromaMemoryStore = new(this._httpClient);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanCreateCollectionsAsync()
- {
- // Arrange
- var collectionName1 = this.GetRandomCollectionName();
- var collectionName2 = this.GetRandomCollectionName();
- var collectionName3 = this.GetRandomCollectionName();
-
- // Act
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName1);
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName2);
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName3);
-
- // Assert
- var collections = await this._chromaMemoryStore.GetCollectionsAsync().ToListAsync();
-
- Assert.Contains(collectionName1, collections);
- Assert.Contains(collectionName2, collections);
- Assert.Contains(collectionName3, collections);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanHandleDuplicateNameDuringCollectionCreationAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
-
- // Act
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
-
- // Assert
- var collections = await this._chromaMemoryStore.GetCollectionsAsync().ToListAsync();
- var filteredCollections = collections.Where(collection => collection.Equals(collectionName, StringComparison.Ordinal)).ToList();
-
- Assert.Single(filteredCollections);
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task ItCanCheckIfCollectionExistsAsync(bool createCollection)
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
-
- if (createCollection)
- {
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
- }
-
- // Act
- bool doesCollectionExist = await this._chromaMemoryStore.DoesCollectionExistAsync(collectionName);
-
- // Assert
- Assert.Equal(createCollection, doesCollectionExist);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanDeleteExistingCollectionAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
-
- var collectionsBeforeDeletion = await this._chromaMemoryStore.GetCollectionsAsync().ToListAsync();
- Assert.Contains(collectionName, collectionsBeforeDeletion);
-
- // Act
- await this._chromaMemoryStore.DeleteCollectionAsync(collectionName);
-
- // Assert
- var collectionsAfterDeletion = await this._chromaMemoryStore.GetCollectionsAsync().ToListAsync();
- Assert.DoesNotContain(collectionName, collectionsAfterDeletion);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItThrowsExceptionOnNonExistentCollectionDeletionAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
-
- // Act
- var exception = await Record.ExceptionAsync(() => this._chromaMemoryStore.DeleteCollectionAsync(collectionName));
-
- // Assert
- Assert.IsType(exception);
- Assert.Contains(
- $"Cannot delete non-existent collection {collectionName}",
- exception.Message,
- StringComparison.InvariantCulture);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItReturnsNullOnNonExistentRecordRetrievalAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
- var key = Guid.NewGuid().ToString();
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
-
- // Act
- var record = await this._chromaMemoryStore.GetAsync(collectionName, key, true);
-
- // Assert
- Assert.Null(record);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanUpsertMemoryRecordAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
- var expectedRecord = this.GetRandomMemoryRecord();
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
-
- // Act
- var createdRecordKey = await this._chromaMemoryStore.UpsertAsync(collectionName, expectedRecord);
-
- // Assert
- Assert.Equal(expectedRecord.Key, createdRecordKey);
-
- var actualRecord = await this._chromaMemoryStore.GetAsync(collectionName, expectedRecord.Key, true);
-
- Assert.NotNull(actualRecord);
-
- this.AssertMemoryRecordEqual(expectedRecord, actualRecord);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanUpsertMemoryRecordBatchAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
-
- var expectedRecord1 = this.GetRandomMemoryRecord();
- var expectedRecord2 = this.GetRandomMemoryRecord();
- var expectedRecord3 = this.GetRandomMemoryRecord();
-
- var batch = new List { expectedRecord1, expectedRecord2, expectedRecord3 };
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
-
- // Act
- var createdRecordKeys = await this._chromaMemoryStore.UpsertBatchAsync(collectionName, batch).ToListAsync();
-
- // Assert
- Assert.Equal(expectedRecord1.Key, createdRecordKeys[0]);
- Assert.Equal(expectedRecord2.Key, createdRecordKeys[1]);
- Assert.Equal(expectedRecord3.Key, createdRecordKeys[2]);
-
- var actualRecords = await this._chromaMemoryStore.GetBatchAsync(collectionName, batch.Select(l => l.Key), true).ToListAsync();
-
- actualRecords.ForEach(Assert.NotNull);
-
- this.AssertMemoryRecordEqual(expectedRecord1, actualRecords[0]);
- this.AssertMemoryRecordEqual(expectedRecord2, actualRecords[1]);
- this.AssertMemoryRecordEqual(expectedRecord3, actualRecords[2]);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanRemoveMemoryRecordAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
- var expectedRecord = this.GetRandomMemoryRecord();
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
- await this._chromaMemoryStore.UpsertAsync(collectionName, expectedRecord);
-
- var recordBeforeDeletion = await this._chromaMemoryStore.GetAsync(collectionName, expectedRecord.Key);
- Assert.NotNull(recordBeforeDeletion);
-
- // Act
- await this._chromaMemoryStore.RemoveAsync(collectionName, expectedRecord.Key);
-
- // Assert
- var recordAfterDeletion = await this._chromaMemoryStore.GetAsync(collectionName, expectedRecord.Key);
- Assert.Null(recordAfterDeletion);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanRemoveMemoryRecordBatchAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
-
- var expectedRecord1 = this.GetRandomMemoryRecord();
- var expectedRecord2 = this.GetRandomMemoryRecord();
- var expectedRecord3 = this.GetRandomMemoryRecord();
-
- var batch = new List { expectedRecord1, expectedRecord2, expectedRecord3 };
- var keys = batch.Select(l => l.Key);
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
- await this._chromaMemoryStore.UpsertBatchAsync(collectionName, batch).ToListAsync();
-
- var recordsBeforeDeletion = await this._chromaMemoryStore.GetBatchAsync(collectionName, keys).ToListAsync();
-
- Assert.Equal(batch.Count, recordsBeforeDeletion.Count);
- recordsBeforeDeletion.ForEach(Assert.NotNull);
-
- // Act
- await this._chromaMemoryStore.RemoveBatchAsync(collectionName, keys);
-
- // Assert
- var recordsAfterDeletion = await this._chromaMemoryStore.GetBatchAsync(collectionName, keys).ToListAsync();
- Assert.Empty(recordsAfterDeletion);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanGetNearestMatchAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
-
- var expectedRecord1 = this.GetRandomMemoryRecord(embedding: new[] { 10f, 10f, 10f });
- var expectedRecord2 = this.GetRandomMemoryRecord(embedding: new[] { 5f, 5f, 5f });
- var expectedRecord3 = this.GetRandomMemoryRecord(embedding: new[] { 1f, 1f, 1f });
-
- float[] searchEmbedding = [2f, 2f, 2f];
-
- var batch = new List { expectedRecord1, expectedRecord2, expectedRecord3 };
- var keys = batch.Select(l => l.Key);
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
- await this._chromaMemoryStore.UpsertBatchAsync(collectionName, batch).ToListAsync();
-
- // Act
- var nearestMatch = await this._chromaMemoryStore.GetNearestMatchAsync(collectionName, searchEmbedding, withEmbedding: true);
-
- // Assert
- Assert.True(nearestMatch.HasValue);
-
- var actualRecord = nearestMatch.Value.Item1;
-
- Assert.NotNull(actualRecord);
-
- this.AssertMemoryRecordEqual(expectedRecord3, actualRecord);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanGetNearestMatchesAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
-
- var expectedRecord1 = this.GetRandomMemoryRecord(embedding: new[] { 10f, 10f, 10f });
- var expectedRecord2 = this.GetRandomMemoryRecord(embedding: new[] { 5f, 5f, 5f });
- var expectedRecord3 = this.GetRandomMemoryRecord(embedding: new[] { 1f, 1f, 1f });
-
- float[] searchEmbedding = [2f, 2f, 2f];
-
- var batch = new List { expectedRecord1, expectedRecord2, expectedRecord3 };
- var keys = batch.Select(l => l.Key);
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
- await this._chromaMemoryStore.UpsertBatchAsync(collectionName, batch).ToListAsync();
-
- // Act
- var nearestMatches = await this._chromaMemoryStore
- .GetNearestMatchesAsync(collectionName, searchEmbedding, batch.Count, withEmbeddings: true)
- .ToListAsync();
-
- // Assert
- Assert.NotNull(nearestMatches);
- Assert.Equal(batch.Count, nearestMatches.Count);
-
- nearestMatches.ForEach(match => Assert.NotNull(match.Item1));
-
- var actualRecord1 = nearestMatches[0].Item1;
- var actualRecord2 = nearestMatches[1].Item1;
- var actualRecord3 = nearestMatches[2].Item1;
-
- this.AssertMemoryRecordEqual(expectedRecord3, actualRecord1);
- this.AssertMemoryRecordEqual(expectedRecord2, actualRecord2);
- this.AssertMemoryRecordEqual(expectedRecord1, actualRecord3);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItReturnsNoMatchesFromEmptyCollectionAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
- float[] searchEmbedding = [2f, 2f, 2f];
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
-
- // Act
- var nearestMatch = await this._chromaMemoryStore.GetNearestMatchAsync(collectionName, searchEmbedding, withEmbedding: true);
-
- // Assert
- Assert.Null(nearestMatch?.Item1);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanUpsertSameMemoryRecordMultipleTimesAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
- var expectedRecord = this.GetRandomMemoryRecord();
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
-
- // Act
- await this._chromaMemoryStore.UpsertAsync(collectionName, expectedRecord);
- await this._chromaMemoryStore.UpsertAsync(collectionName, expectedRecord);
- await this._chromaMemoryStore.UpsertAsync(collectionName, expectedRecord);
-
- // Assert
- var actualRecord = await this._chromaMemoryStore.GetAsync(collectionName, expectedRecord.Key, true);
-
- Assert.NotNull(actualRecord);
-
- this.AssertMemoryRecordEqual(expectedRecord, actualRecord);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanUpsertDifferentMemoryRecordsWithSameKeyMultipleTimesAsync()
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
- var expectedRecord1 = this.GetRandomMemoryRecord();
- var key = expectedRecord1.Key;
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
- await this._chromaMemoryStore.UpsertAsync(collectionName, expectedRecord1);
-
- var actualRecord1 = await this._chromaMemoryStore.GetAsync(collectionName, key, withEmbedding: true);
-
- Assert.NotNull(actualRecord1);
- this.AssertMemoryRecordEqual(expectedRecord1, actualRecord1);
-
- // Act
- var expectedRecord2 = this.GetRandomMemoryRecord(key: key);
- await this._chromaMemoryStore.UpsertAsync(collectionName, expectedRecord2);
-
- // Assert
- var actualRecord2 = await this._chromaMemoryStore.GetAsync(collectionName, key, withEmbedding: true);
-
- Assert.NotNull(actualRecord2);
- this.AssertMemoryRecordEqual(expectedRecord2, actualRecord2);
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task ItProcessesBooleanValuesCorrectlyAsync(bool isReference)
- {
- // Arrange
- var collectionName = this.GetRandomCollectionName();
- var metadata = this.GetRandomMemoryRecordMetadata(isReference: isReference);
- var expectedRecord = this.GetRandomMemoryRecord(metadata: metadata);
-
- await this._chromaMemoryStore.CreateCollectionAsync(collectionName);
-
- // Act
- var createdRecordKey = await this._chromaMemoryStore.UpsertAsync(collectionName, expectedRecord);
- var actualRecord = await this._chromaMemoryStore.GetAsync(collectionName, createdRecordKey, true);
-
- // Assert
- Assert.NotNull(actualRecord);
-
- Assert.Equal(expectedRecord.Metadata.IsReference, actualRecord.Metadata.IsReference);
- }
-
- public void Dispose()
- {
- this._httpClient.Dispose();
- }
-
- #region private ================================================================================
-
- private readonly HttpClient _httpClient;
- private readonly ChromaMemoryStore _chromaMemoryStore;
-
- private void AssertMemoryRecordEqual(MemoryRecord expectedRecord, MemoryRecord actualRecord)
- {
- Assert.Equal(expectedRecord.Key, actualRecord.Key);
- Assert.True(expectedRecord.Embedding.Span.SequenceEqual(actualRecord.Embedding.Span));
- Assert.Equal(expectedRecord.Metadata.Id, actualRecord.Metadata.Id);
- Assert.Equal(expectedRecord.Metadata.Text, actualRecord.Metadata.Text);
- Assert.Equal(expectedRecord.Metadata.Description, actualRecord.Metadata.Description);
- Assert.Equal(expectedRecord.Metadata.AdditionalMetadata, actualRecord.Metadata.AdditionalMetadata);
- Assert.Equal(expectedRecord.Metadata.IsReference, actualRecord.Metadata.IsReference);
- Assert.Equal(expectedRecord.Metadata.ExternalSourceName, actualRecord.Metadata.ExternalSourceName);
- }
-
- private string GetRandomCollectionName()
- {
- return "sk-test-" + Guid.NewGuid();
- }
-
- private MemoryRecord GetRandomMemoryRecord(string? key = null, ReadOnlyMemory? embedding = null)
- {
- var recordKey = key ?? Guid.NewGuid().ToString();
- var recordEmbedding = embedding ?? new[] { 1f, 3f, 5f };
-
- return MemoryRecord.LocalRecord(
- id: recordKey,
- text: "text-" + Guid.NewGuid().ToString(),
- description: "description-" + Guid.NewGuid().ToString(),
- embedding: recordEmbedding,
- additionalMetadata: "metadata-" + Guid.NewGuid().ToString(),
- key: recordKey);
- }
-
- private MemoryRecord GetRandomMemoryRecord(MemoryRecordMetadata metadata, ReadOnlyMemory? embedding = null)
- {
- var recordEmbedding = embedding ?? new[] { 1f, 3f, 5f };
-
- return MemoryRecord.FromMetadata(
- metadata: metadata,
- embedding: recordEmbedding,
- key: metadata.Id);
- }
-
- private MemoryRecordMetadata GetRandomMemoryRecordMetadata(bool isReference = false, string? key = null)
- {
- var recordKey = key ?? Guid.NewGuid().ToString();
-
- return new MemoryRecordMetadata(
- isReference: isReference,
- id: recordKey,
- text: "text-" + Guid.NewGuid().ToString(),
- description: "description-" + Guid.NewGuid().ToString(),
- externalSourceName: "source-name-" + Guid.NewGuid().ToString(),
- additionalMetadata: "metadata-" + Guid.NewGuid().ToString());
- }
-
- #endregion
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoCollectionFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoCollectionFixture.cs
deleted file mode 100644
index 46fba5703c2f..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoCollectionFixture.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.CosmosMongoDB;
-
-[CollectionDefinition("CosmosMongoCollection")]
-public class CosmosMongoCollectionFixture : ICollectionFixture
-{ }
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoCollectionTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoCollectionTests.cs
deleted file mode 100644
index fff6a76d6c4f..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoCollectionTests.cs
+++ /dev/null
@@ -1,520 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.Extensions.VectorData;
-using Microsoft.SemanticKernel.Connectors.CosmosMongoDB;
-using MongoDB.Bson;
-using MongoDB.Bson.Serialization.Attributes;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.CosmosMongoDB;
-
-#pragma warning disable CS0618 // VectorSearchFilter is obsolete
-
-[Collection("CosmosMongoCollection")]
-public class CosmosMongoCollectionTests(CosmosMongoVectorStoreFixture fixture)
-{
- private const string? SkipReason = "Azure CosmosDB MongoDB cluster is required";
-
- [Theory(Skip = SkipReason)]
- [InlineData("sk-test-hotels", true)]
- [InlineData("nonexistentcollection", false)]
- public async Task CollectionExistsReturnsCollectionStateAsync(string collectionName, bool expectedExists)
- {
- // Arrange
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, collectionName);
-
- // Act
- var actual = await sut.CollectionExistsAsync();
-
- // Assert
- Assert.Equal(expectedExists, actual);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanEnsureCollectionExistsAsync()
- {
- // Arrange
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, "sk-test-create-collection");
-
- try
- {
- // Act
- await sut.EnsureCollectionExistsAsync();
-
- // Assert
- Assert.True(await sut.CollectionExistsAsync());
- }
- finally
- {
- // Clean up
- await sut.EnsureCollectionDeletedAsync();
- }
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true, true)]
- [InlineData(true, false)]
- [InlineData(false, true)]
- [InlineData(false, false)]
- public async Task ItCanCreateCollectionUpsertAndGetAsync(bool includeVectors, bool useRecordDefinition)
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
-
- var collectionNamePostfix = useRecordDefinition ? "with-definition" : "with-type";
- var collectionName = $"collection-{collectionNamePostfix}";
-
- var options = new CosmosMongoCollectionOptions
- {
- Definition = useRecordDefinition ? fixture.HotelVectorStoreRecordDefinition : null
- };
-
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, collectionName);
-
- var record = this.CreateTestHotel(HotelId);
-
- // Act
- await sut.EnsureCollectionExistsAsync();
- await sut.UpsertAsync(record);
- var getResult = await sut.GetAsync(HotelId, new() { IncludeVectors = includeVectors });
-
- // Assert
- Assert.True(await sut.CollectionExistsAsync());
- await sut.EnsureCollectionDeletedAsync();
-
- Assert.NotNull(getResult);
-
- Assert.Equal(record.HotelId, getResult.HotelId);
- Assert.Equal(record.HotelName, getResult.HotelName);
- Assert.Equal(record.HotelCode, getResult.HotelCode);
- Assert.Equal(record.HotelRating, getResult.HotelRating);
- Assert.Equal(record.ParkingIncluded, getResult.ParkingIncluded);
- Assert.Equal(record.Tags.ToArray(), getResult.Tags.ToArray());
- Assert.Equal(record.Description, getResult.Description);
- Assert.Equal(record.Timestamp.ToUniversalTime(), getResult.Timestamp.ToUniversalTime());
-
- if (includeVectors)
- {
- Assert.NotNull(getResult.DescriptionEmbedding);
- Assert.Equal(record.DescriptionEmbedding!.Value.ToArray(), getResult.DescriptionEmbedding.Value.ToArray());
- }
- else
- {
- Assert.Null(getResult.DescriptionEmbedding);
- }
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanDeleteCollectionAsync()
- {
- // Arrange
- const string TempCollectionName = "temp-test";
- await fixture.MongoDatabase.CreateCollectionAsync(TempCollectionName);
-
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, TempCollectionName);
-
- Assert.True(await sut.CollectionExistsAsync());
-
- // Act
- await sut.EnsureCollectionDeletedAsync();
-
- // Assert
- Assert.False(await sut.CollectionExistsAsync());
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanGetAndDeleteRecordAsync()
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- var record = this.CreateTestHotel(HotelId);
-
- await sut.UpsertAsync(record);
- var getResult = await sut.GetAsync(HotelId);
-
- Assert.NotNull(getResult);
-
- // Act
- await sut.DeleteAsync(HotelId);
-
- getResult = await sut.GetAsync(HotelId);
-
- // Assert
- Assert.Null(getResult);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanGetAndDeleteBatchAsync()
- {
- // Arrange
- const string HotelId1 = "11111111-1111-1111-1111-111111111111";
- const string HotelId2 = "22222222-2222-2222-2222-222222222222";
- const string HotelId3 = "33333333-3333-3333-3333-333333333333";
-
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- var record1 = this.CreateTestHotel(HotelId1);
- var record2 = this.CreateTestHotel(HotelId2);
- var record3 = this.CreateTestHotel(HotelId3);
-
- await sut.UpsertAsync([record1, record2, record3]);
- var getResults = await sut.GetAsync([HotelId1, HotelId2, HotelId3]).ToListAsync();
-
- Assert.NotNull(getResults.First(l => l.HotelId == HotelId1));
- Assert.NotNull(getResults.First(l => l.HotelId == HotelId2));
- Assert.NotNull(getResults.First(l => l.HotelId == HotelId3));
-
- // Act
- await sut.DeleteAsync([HotelId1, HotelId2, HotelId3]);
-
- getResults = await sut.GetAsync([HotelId1, HotelId2, HotelId3]).ToListAsync();
-
- // Assert
- Assert.Empty(getResults);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanUpsertRecordAsync()
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- var record = this.CreateTestHotel(HotelId);
-
- await sut.UpsertAsync(record);
- var getResult = await sut.GetAsync(HotelId);
-
- Assert.NotNull(getResult);
-
- // Act
- record.HotelName = "Updated name";
- record.HotelRating = 10;
-
- await sut.UpsertAsync(record);
- getResult = await sut.GetAsync(HotelId);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("Updated name", getResult.HotelName);
- Assert.Equal(10, getResult.HotelRating);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task UpsertWithModelWorksCorrectlyAsync()
- {
- // Arrange
- var definition = new VectorStoreCollectionDefinition
- {
- Properties =
- [
- new VectorStoreKeyProperty("Id", typeof(string)),
- new VectorStoreDataProperty("HotelName", typeof(string))
- ]
- };
-
- var model = new TestModel { Id = "key", HotelName = "Test Name" };
-
- using var sut = new CosmosMongoCollection(
- fixture.MongoDatabase,
- fixture.TestCollection,
- new() { Definition = definition });
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.Id);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.Id);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task UpsertWithVectorStoreModelWorksCorrectlyAsync()
- {
- // Arrange
- var model = new VectorStoreTestModel { HotelId = "key", HotelName = "Test Name" };
-
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.HotelId);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.HotelId);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task UpsertWithBsonModelWorksCorrectlyAsync()
- {
- // Arrange
- var definition = new VectorStoreCollectionDefinition
- {
- Properties =
- [
- new VectorStoreKeyProperty("Id", typeof(string)),
- new VectorStoreDataProperty("HotelName", typeof(string))
- ]
- };
-
- var model = new BsonTestModel { Id = "key", HotelName = "Test Name" };
-
- using var sut = new CosmosMongoCollection(
- fixture.MongoDatabase,
- fixture.TestCollection,
- new() { Definition = definition });
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.Id);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.Id);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task UpsertWithBsonVectorStoreModelWorksCorrectlyAsync()
- {
- // Arrange
- var model = new BsonVectorStoreTestModel { HotelId = "key", HotelName = "Test Name" };
-
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.HotelId);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.HotelId);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task UpsertWithBsonVectorStoreWithNameModelWorksCorrectlyAsync()
- {
- // Arrange
- var model = new BsonVectorStoreWithNameTestModel { Id = "key", HotelName = "Test Name" };
-
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.Id);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.Id);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task SearchReturnsValidResultsByDefaultAsync()
- {
- // Arrange
- var hotel1 = this.CreateTestHotel(hotelId: "key1", embedding: new[] { 30f, 31f, 32f, 33f });
- var hotel2 = this.CreateTestHotel(hotelId: "key2", embedding: new[] { 31f, 32f, 33f, 34f });
- var hotel3 = this.CreateTestHotel(hotelId: "key3", embedding: new[] { 20f, 20f, 20f, 20f });
- var hotel4 = this.CreateTestHotel(hotelId: "key4", embedding: new[] { -1000f, -1000f, -1000f, -1000f });
-
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, "TestVectorizedSearch");
-
- await sut.EnsureCollectionExistsAsync();
-
- await sut.UpsertAsync([hotel4, hotel2, hotel3, hotel1]);
-
- // Act
- var searchResults = await sut.SearchAsync(new ReadOnlyMemory([30f, 31f, 32f, 33f]), top: 3).ToListAsync();
-
- // Assert
- var ids = searchResults.Select(l => l.Record.HotelId).ToList();
-
- Assert.Equal("key1", ids[0]);
- Assert.Equal("key2", ids[1]);
- Assert.Equal("key3", ids[2]);
-
- Assert.DoesNotContain("key4", ids);
-
- Assert.Equal(1, searchResults.First(l => l.Record.HotelId == "key1").Score);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task SearchReturnsValidResultsWithOffsetAsync()
- {
- // Arrange
- var hotel1 = this.CreateTestHotel(hotelId: "key1", embedding: new[] { 30f, 31f, 32f, 33f });
- var hotel2 = this.CreateTestHotel(hotelId: "key2", embedding: new[] { 31f, 32f, 33f, 34f });
- var hotel3 = this.CreateTestHotel(hotelId: "key3", embedding: new[] { 20f, 20f, 20f, 20f });
- var hotel4 = this.CreateTestHotel(hotelId: "key4", embedding: new[] { -1000f, -1000f, -1000f, -1000f });
-
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, "TestVectorizedSearchWithOffset");
-
- await sut.EnsureCollectionExistsAsync();
-
- await sut.UpsertAsync([hotel4, hotel2, hotel3, hotel1]);
-
- // Act
- var searchResults = await sut.SearchAsync(new ReadOnlyMemory([30f, 31f, 32f, 33f]), top: 2, new()
- {
- Skip = 2
- }).ToListAsync();
-
- // Assert
- var ids = searchResults.Select(l => l.Record.HotelId).ToList();
-
- Assert.Equal("key3", ids[0]);
- Assert.Equal("key4", ids[1]);
-
- Assert.DoesNotContain("key1", ids);
- Assert.DoesNotContain("key2", ids);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task SearchReturnsValidResultsWithFilterAsync()
- {
- // Arrange
- var hotel1 = this.CreateTestHotel(hotelId: "key1", embedding: new[] { 30f, 31f, 32f, 33f });
- var hotel2 = this.CreateTestHotel(hotelId: "key2", embedding: new[] { 31f, 32f, 33f, 34f });
- var hotel3 = this.CreateTestHotel(hotelId: "key3", embedding: new[] { 20f, 20f, 20f, 20f });
- var hotel4 = this.CreateTestHotel(hotelId: "key4", embedding: new[] { -1000f, -1000f, -1000f, -1000f });
-
- using var sut = new CosmosMongoCollection(fixture.MongoDatabase, "TestVectorizedSearchWithFilter");
-
- await sut.EnsureCollectionExistsAsync();
-
- await sut.UpsertAsync([hotel4, hotel2, hotel3, hotel1]);
-
- // Act
- var searchResults = await sut.SearchAsync(new ReadOnlyMemory([30f, 31f, 32f, 33f]), top: 3, new()
- {
- OldFilter = new VectorSearchFilter().EqualTo(nameof(CosmosMongoHotel.HotelName), "My Hotel key2")
- }).ToListAsync();
-
- // Assert
- var ids = searchResults.Select(l => l.Record.HotelId).ToList();
-
- Assert.Equal("key2", ids[0]);
-
- Assert.DoesNotContain("key1", ids);
- Assert.DoesNotContain("key3", ids);
- Assert.DoesNotContain("key4", ids);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
- {
- // Arrange
- var options = new CosmosMongoCollectionOptions
- {
- Definition = fixture.HotelVectorStoreRecordDefinition
- };
-
- using var sut = new CosmosMongoDynamicCollection(fixture.MongoDatabase, fixture.TestCollection, options);
-
- // Act
- await sut.UpsertAsync(new Dictionary
- {
- ["HotelId"] = "DynamicMapper-1",
-
- ["HotelName"] = "Dynamic Mapper Hotel",
- ["Description"] = "This is a dynamic mapper hotel",
- ["Tags"] = new string[] { "dynamic" },
- ["ParkingIncluded"] = false,
- ["Timestamp"] = new DateTime(1970, 1, 18, 0, 0, 0).ToUniversalTime(),
- ["HotelRating"] = 3.6f,
-
- ["DescriptionEmbedding"] = new ReadOnlyMemory([30f, 31f, 32f, 33f])
- });
-
- var localGetResult = await sut.GetAsync("DynamicMapper-1", new RecordRetrievalOptions { IncludeVectors = true });
-
- // Assert
- Assert.NotNull(localGetResult);
- Assert.Equal("Dynamic Mapper Hotel", localGetResult["HotelName"]);
- Assert.Equal("This is a dynamic mapper hotel", localGetResult["Description"]);
- Assert.Equal(new[] { "dynamic" }, localGetResult["Tags"]);
- Assert.False((bool?)localGetResult["ParkingIncluded"]);
- Assert.Equal(new DateTime(1970, 1, 18, 0, 0, 0).ToUniversalTime(), localGetResult["Timestamp"]);
- Assert.Equal(3.6f, localGetResult["HotelRating"]);
- Assert.Equal(new[] { 30f, 31f, 32f, 33f }, ((ReadOnlyMemory)localGetResult["DescriptionEmbedding"]!).ToArray());
- }
-
- #region private
-
- private CosmosMongoHotel CreateTestHotel(string hotelId, ReadOnlyMemory? embedding = null)
- {
- return new CosmosMongoHotel
- {
- HotelId = hotelId,
- HotelName = $"My Hotel {hotelId}",
- HotelCode = 42,
- HotelRating = 4.5f,
- ParkingIncluded = true,
- Tags = { "t1", "t2" },
- Description = "This is a great hotel.",
- Timestamp = new DateTime(2024, 09, 23, 15, 32, 33),
- DescriptionEmbedding = embedding ?? new[] { 30f, 31f, 32f, 33f },
- };
- }
-
- private sealed class TestModel
- {
- public string? Id { get; set; }
-
- public string? HotelName { get; set; }
- }
-
- private sealed class VectorStoreTestModel
- {
- [VectorStoreKey]
- public string? HotelId { get; set; }
-
- [VectorStoreData(StorageName = "hotel_name")]
- public string? HotelName { get; set; }
- }
-
- private sealed class BsonTestModel
- {
- [BsonId]
- public string? Id { get; set; }
-
- [BsonElement("hotel_name")]
- public string? HotelName { get; set; }
- }
-
- private sealed class BsonVectorStoreTestModel
- {
- [BsonId]
- [VectorStoreKey]
- public string? HotelId { get; set; }
-
- [BsonElement("hotel_name")]
- [VectorStoreData]
- public string? HotelName { get; set; }
- }
-
- private sealed class BsonVectorStoreWithNameTestModel
- {
- [BsonId]
- [VectorStoreKey]
- public string? Id { get; set; }
-
- [BsonElement("bson_hotel_name")]
- [VectorStoreData(StorageName = "storage_hotel_name")]
- public string? HotelName { get; set; }
- }
-
- #endregion
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoHotel.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoHotel.cs
deleted file mode 100644
index 90b34c7afd91..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoHotel.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.VectorData;
-
-namespace SemanticKernel.IntegrationTests.Connectors.CosmosMongoDB;
-
-#pragma warning disable CS8618
-
-public class CosmosMongoHotel
-{
- /// The key of the record.
- [VectorStoreKey]
- public string HotelId { get; init; }
-
- /// A string metadata field.
- [VectorStoreData(IsIndexed = true)]
- public string? HotelName { get; set; }
-
- /// An int metadata field.
- [VectorStoreData]
- public int HotelCode { get; set; }
-
- /// A float metadata field.
- [VectorStoreData]
- public float? HotelRating { get; set; }
-
- /// A bool metadata field.
- [VectorStoreData(StorageName = "parking_is_included")]
- public bool ParkingIncluded { get; set; }
-
- /// An array metadata field.
- [VectorStoreData]
- public List Tags { get; set; } = [];
-
- /// A data field.
- [VectorStoreData]
- public string Description { get; set; }
-
- /// A datetime metadata field.
- [VectorStoreData]
- public DateTime Timestamp { get; set; }
-
- /// A vector field.
- [VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineDistance, IndexKind = IndexKind.IvfFlat)]
- public ReadOnlyMemory? DescriptionEmbedding { get; set; }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoVectorStoreFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoVectorStoreFixture.cs
deleted file mode 100644
index f4427b6d5bef..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoVectorStoreFixture.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.VectorData;
-using MongoDB.Driver;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.CosmosMongoDB;
-
-public class CosmosMongoVectorStoreFixture : IAsyncLifetime
-{
- private readonly List _testCollections = ["sk-test-hotels", "sk-test-contacts", "sk-test-addresses"];
-
- /// Main test collection for tests.
- public string TestCollection => this._testCollections[0];
-
- /// that can be used to manage the collections in Azure CosmosDB MongoDB.
- public IMongoDatabase MongoDatabase { get; }
-
- /// Gets the manually created vector store record definition for Azure CosmosDB MongoDB test model.
- public VectorStoreCollectionDefinition HotelVectorStoreRecordDefinition { get; private set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public CosmosMongoVectorStoreFixture()
- {
- var configuration = new ConfigurationBuilder()
- .AddJsonFile(path: "testsettings.json", optional: false, reloadOnChange: true)
- .AddJsonFile(
- path: "testsettings.development.json",
- optional: true,
- reloadOnChange: true
- )
- .AddEnvironmentVariables()
- .AddUserSecrets()
- .Build();
-
- var connectionString = GetConnectionString(configuration);
-#pragma warning disable CA2000 // Dispose objects before losing scope
- var client = new MongoClient(connectionString);
-#pragma warning restore CA2000
-
- this.MongoDatabase = client.GetDatabase("test");
-
- this.HotelVectorStoreRecordDefinition = new()
- {
- Properties =
- [
- new VectorStoreKeyProperty("HotelId", typeof(string)),
- new VectorStoreDataProperty("HotelName", typeof(string)),
- new VectorStoreDataProperty("HotelCode", typeof(int)),
- new VectorStoreDataProperty("ParkingIncluded", typeof(bool)) { StorageName = "parking_is_included" },
- new VectorStoreDataProperty("HotelRating", typeof(float)),
- new VectorStoreDataProperty("Tags", typeof(List)),
- new VectorStoreDataProperty("Timestamp", typeof(DateTime)),
- new VectorStoreDataProperty("Description", typeof(string)),
- new VectorStoreVectorProperty("DescriptionEmbedding", typeof(ReadOnlyMemory?), 4) { IndexKind = IndexKind.IvfFlat, DistanceFunction = DistanceFunction.CosineDistance }
- ]
- };
- }
-
- public async Task InitializeAsync()
- {
- foreach (var collection in this._testCollections)
- {
- await this.MongoDatabase.CreateCollectionAsync(collection);
- }
- }
-
- public async Task DisposeAsync()
- {
- var cursor = await this.MongoDatabase.ListCollectionNamesAsync();
-
- while (await cursor.MoveNextAsync().ConfigureAwait(false))
- {
- foreach (var collection in cursor.Current)
- {
- await this.MongoDatabase.DropCollectionAsync(collection);
- }
- }
- }
-
- #region private
-
- private static string GetConnectionString(IConfigurationRoot configuration)
- {
- var settingValue = configuration["CosmosMongo:ConnectionString"];
- if (string.IsNullOrWhiteSpace(settingValue))
- {
- throw new ArgumentNullException($"{settingValue} string is not configured");
- }
-
- return settingValue;
- }
-
- #endregion
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoVectorStoreTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoVectorStoreTests.cs
deleted file mode 100644
index b1720dee0234..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/CosmosMongoVectorStoreTests.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Microsoft.SemanticKernel.Connectors.CosmosMongoDB;
-using SemanticKernel.IntegrationTests.Connectors.Memory;
-using SemanticKernel.IntegrationTests.Connectors.Memory.Xunit;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.CosmosMongoDB;
-
-[Collection("CosmosMongoCollection")]
-[DisableVectorStoreTests(Skip = "Azure CosmosDB MongoDB cluster is required")]
-public class CosmosMongoVectorStoreTests(CosmosMongoVectorStoreFixture fixture)
-#pragma warning disable CA2000 // Dispose objects before losing scope
- : BaseVectorStoreTests(new CosmosMongoVectorStore(fixture.MongoDatabase))
-#pragma warning restore CA2000 // Dispose objects before losing scope
-{
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/DataHelper.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/DataHelper.cs
deleted file mode 100644
index 2b5e07969aab..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosMongoDB/DataHelper.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Linq;
-using System.Numerics.Tensors;
-using Microsoft.SemanticKernel.Memory;
-
-namespace SemanticKernel.IntegrationTests.Connectors.CosmosMongo;
-
-internal static class DataHelper
-{
- public static MemoryRecord[] VectorSearchExpectedResults { get; }
- public static MemoryRecord[] VectorSearchTestRecords { get; }
- public static float[] VectorSearchTestEmbedding { get; }
-
- static DataHelper()
- {
- VectorSearchTestRecords = CreateBatchRecords(8);
- VectorSearchTestEmbedding = [1, 0.699f, 0.701f];
- VectorSearchExpectedResults = VectorSearchTestRecords
- .OrderByDescending(r => TensorPrimitives.CosineSimilarity(r.Embedding.Span, VectorSearchTestEmbedding))
- .ToArray();
- }
-
- public static MemoryRecord CreateRecord(string id) =>
- MemoryRecord.LocalRecord(
- id: id,
- text: $"text_{id}",
- description: $"description_{id}",
- embedding: new[] { 1.1f, 2.2f, 3.3f },
- timestamp: GetDateTime());
-
- public static MemoryRecord[] CreateBatchRecords(int count) =>
- Enumerable
- .Range(0, count)
- .Select(i => MemoryRecord.LocalRecord(
- id: $"test_{i}",
- text: $"text_{i}",
- description: $"description_{i}",
- embedding: new[] { 1, (float)Math.Cos(Math.PI * i / count), (float)Math.Sin(Math.PI * i / count) },
- timestamp: GetDateTime()))
- .ToArray();
-
- private static DateTime GetDateTime() =>
- new(TimeSpan.TicksPerMillisecond * (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond), DateTimeKind.Local);
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlCollectionFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlCollectionFixture.cs
deleted file mode 100644
index d2357df505b1..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlCollectionFixture.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.CosmosNoSql;
-
-[CollectionDefinition("CosmosNoSqlCollection")]
-public class CosmosNoSqlCollectionFixture : ICollectionFixture
-{ }
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlCollectionTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlCollectionTests.cs
deleted file mode 100644
index 47cb5d26bb97..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlCollectionTests.cs
+++ /dev/null
@@ -1,455 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.Azure.Cosmos;
-using Microsoft.Extensions.VectorData;
-using Microsoft.SemanticKernel.Connectors.CosmosNoSql;
-using SemanticKernel.IntegrationTests.Connectors.Memory.Xunit;
-using Xunit;
-using DistanceFunction = Microsoft.Extensions.VectorData.DistanceFunction;
-using IndexKind = Microsoft.Extensions.VectorData.IndexKind;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.CosmosNoSql;
-
-#pragma warning disable CA1859 // Use concrete types when possible for improved performance
-#pragma warning disable CS0618 // VectorSearchFilter is obsolete
-
-///
-/// Integration tests for class.
-///
-[Collection("CosmosNoSqlCollection")]
-[CosmosNoSqlConnectionStringSetCondition]
-public sealed class CosmosNoSqlCollectionTests(CosmosNoSqlVectorStoreFixture fixture)
-{
- [VectorStoreFact]
- public async Task ItCanEnsureCollectionExistsAsync()
- {
- // Arrange
- using var sut = new CosmosNoSqlCollection(fixture.Database!, "test-create-collection");
-
- // Act
- await sut.EnsureCollectionExistsAsync();
-
- // Assert
- Assert.True(await sut.CollectionExistsAsync());
- }
-
- [VectorStoreTheory]
- [InlineData("sk-test-hotels", true)]
- [InlineData("nonexistentcollection", false)]
- public async Task CollectionExistsReturnsCollectionStateAsync(string collectionName, bool expectedExists)
- {
- // Arrange
- using var sut = new CosmosNoSqlCollection(fixture.Database!, collectionName);
-
- if (expectedExists)
- {
- await fixture.Database!.CreateContainerIfNotExistsAsync(new ContainerProperties(collectionName, "/id"));
- }
-
- // Act
- var actual = await sut.CollectionExistsAsync();
-
- // Assert
- Assert.Equal(expectedExists, actual);
- }
-
- [VectorStoreTheory]
- [InlineData(true, true)]
- [InlineData(true, false)]
- [InlineData(false, true)]
- [InlineData(false, false)]
- public async Task ItCanCreateCollectionUpsertAndGetAsync(bool includeVectors, bool useRecordDefinition)
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
-
- var collectionNamePostfix = useRecordDefinition ? "with-definition" : "with-type";
- collectionNamePostfix = includeVectors ? $"{collectionNamePostfix}-with-vectors" : $"{collectionNamePostfix}-without-vectors";
- var collectionName = $"collection-{collectionNamePostfix}";
-
- var options = new CosmosNoSqlCollectionOptions
- {
- Definition = useRecordDefinition ? this.GetTestHotelRecordDefinition() : null
- };
-
- using var sut = new CosmosNoSqlCollection(fixture.Database!, collectionName);
-
- var record = this.CreateTestHotel(HotelId);
-
- // Act
- await sut.EnsureCollectionExistsAsync();
- await sut.UpsertAsync(record);
- var getResult = await sut.GetAsync(HotelId, new() { IncludeVectors = includeVectors });
-
- // Assert
- Assert.True(await sut.CollectionExistsAsync());
- await sut.EnsureCollectionDeletedAsync();
-
- Assert.NotNull(getResult);
-
- Assert.Equal(record.HotelId, getResult.HotelId);
- Assert.Equal(record.HotelName, getResult.HotelName);
- Assert.Equal(record.HotelCode, getResult.HotelCode);
- Assert.Equal(record.HotelRating, getResult.HotelRating);
- Assert.Equal(record.ParkingIncluded, getResult.ParkingIncluded);
- Assert.Equal(record.Tags.ToArray(), getResult.Tags.ToArray());
- Assert.Equal(record.Description, getResult.Description);
- Assert.Equal(record.Timestamp, getResult.Timestamp);
-
- if (includeVectors)
- {
- Assert.NotNull(getResult.DescriptionEmbedding);
- Assert.Equal(record.DescriptionEmbedding!.Value.ToArray(), getResult.DescriptionEmbedding.Value.ToArray());
- }
- else
- {
- Assert.Null(getResult.DescriptionEmbedding);
- }
- }
-
- [VectorStoreFact]
- public async Task ItCanDeleteCollectionAsync()
- {
- // Arrange
- const string TempCollectionName = "test-delete-collection";
- await fixture.Database!.CreateContainerAsync(new ContainerProperties(TempCollectionName, "/id"));
-
- using var sut = new CosmosNoSqlCollection(fixture.Database!, TempCollectionName);
-
- Assert.True(await sut.CollectionExistsAsync());
-
- // Act
- await sut.EnsureCollectionDeletedAsync();
-
- // Assert
- Assert.False(await sut.CollectionExistsAsync());
- }
-
- [VectorStoreTheory]
- [InlineData("consistent-mode-collection", IndexingMode.Consistent)]
- [InlineData("lazy-mode-collection", IndexingMode.Lazy)]
- [InlineData("none-mode-collection", IndexingMode.None)]
- public async Task ItCanGetAndDeleteRecordAsync(string collectionName, IndexingMode indexingMode)
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
- using var sut = new CosmosNoSqlCollection(
- fixture.Database!,
- collectionName,
- new() { IndexingMode = indexingMode, Automatic = indexingMode != IndexingMode.None });
-
- await sut.EnsureCollectionExistsAsync();
-
- var record = this.CreateTestHotel(HotelId);
-
- await sut.UpsertAsync(record);
- var getResult = await sut.GetAsync(HotelId);
-
- Assert.NotNull(getResult);
-
- // Act
- await sut.DeleteAsync(HotelId);
-
- getResult = await sut.GetAsync(HotelId);
-
- // Assert
- Assert.Null(getResult);
- }
-
- [VectorStoreFact]
- public async Task ItCanGetAndDeleteRecordWithPartitionKeyAsync()
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
- const string HotelName = "Test Hotel Name";
-
- using VectorStoreCollection sut =
- new CosmosNoSqlCollection(
- fixture.Database!,
- "delete-with-partition-key",
- new() { PartitionKeyPropertyName = "HotelName" });
-
- await sut.EnsureCollectionExistsAsync();
-
- var record = this.CreateTestHotel(HotelId, HotelName);
-
- await sut.UpsertAsync(record);
-
- var key = new CosmosNoSqlCompositeKey(record.HotelId, record.HotelName!);
- var getResult = await sut.GetAsync(key);
-
- Assert.NotNull(getResult);
-
- // Act
- await sut.DeleteAsync(key);
-
- getResult = await sut.GetAsync(key);
-
- // Assert
- Assert.Null(getResult);
- }
-
- [VectorStoreFact]
- public async Task ItCanGetAndDeleteBatchAsync()
- {
- // Arrange
- const string HotelId1 = "11111111-1111-1111-1111-111111111111";
- const string HotelId2 = "22222222-2222-2222-2222-222222222222";
- const string HotelId3 = "33333333-3333-3333-3333-333333333333";
-
- using var sut = new CosmosNoSqlCollection(fixture.Database!, "get-and-delete-batch");
-
- await sut.EnsureCollectionExistsAsync();
-
- var record1 = this.CreateTestHotel(HotelId1);
- var record2 = this.CreateTestHotel(HotelId2);
- var record3 = this.CreateTestHotel(HotelId3);
-
- await sut.UpsertAsync([record1, record2, record3]);
- var getResults = await sut.GetAsync([HotelId1, HotelId2, HotelId3]).ToListAsync();
-
- Assert.NotNull(getResults.First(l => l.HotelId == HotelId1));
- Assert.NotNull(getResults.First(l => l.HotelId == HotelId2));
- Assert.NotNull(getResults.First(l => l.HotelId == HotelId3));
-
- // Act
- await sut.DeleteAsync([HotelId1, HotelId2, HotelId3]);
-
- getResults = await sut.GetAsync([HotelId1, HotelId2, HotelId3]).ToListAsync();
-
- // Assert
- Assert.Empty(getResults);
- }
-
- [VectorStoreFact]
- public async Task ItCanUpsertRecordAsync()
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
- using var sut = new CosmosNoSqlCollection(fixture.Database!, "upsert-record");
-
- await sut.EnsureCollectionExistsAsync();
-
- var record = this.CreateTestHotel(HotelId);
-
- await sut.UpsertAsync(record);
- var getResult = await sut.GetAsync(HotelId);
-
- Assert.NotNull(getResult);
-
- // Act
- record.HotelName = "Updated name";
- record.HotelRating = 10;
- await sut.UpsertAsync(record);
-
- getResult = await sut.GetAsync(HotelId);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("Updated name", getResult.HotelName);
- Assert.Equal(10, getResult.HotelRating);
- }
-
- [VectorStoreFact]
- public async Task SearchReturnsValidResultsByDefaultAsync()
- {
- // Arrange
- var hotel1 = this.CreateTestHotel(hotelId: "key1", embedding: new[] { 30f, 31f, 32f, 33f });
- var hotel2 = this.CreateTestHotel(hotelId: "key2", embedding: new[] { 31f, 32f, 33f, 34f });
- var hotel3 = this.CreateTestHotel(hotelId: "key3", embedding: new[] { 20f, 20f, 20f, 20f });
- var hotel4 = this.CreateTestHotel(hotelId: "key4", embedding: new[] { -1000f, -1000f, -1000f, -1000f });
-
- using var sut = new CosmosNoSqlCollection(fixture.Database!, "vector-search-default");
-
- await sut.EnsureCollectionExistsAsync();
-
- await sut.UpsertAsync([hotel4, hotel2, hotel3, hotel1]);
-
- // Act
- var searchResults = await sut.SearchAsync(new ReadOnlyMemory([30f, 31f, 32f, 33f]), top: 3).ToListAsync();
-
- // Assert
- var ids = searchResults.Select(l => l.Record.HotelId).ToList();
-
- Assert.Equal("key1", ids[0]);
- Assert.Equal("key2", ids[1]);
- Assert.Equal("key3", ids[2]);
-
- Assert.DoesNotContain("key4", ids);
-
- Assert.Equal(1, searchResults.First(l => l.Record.HotelId == "key1").Score);
- }
-
- [VectorStoreFact]
- public async Task SearchReturnsValidResultsWithOffsetAsync()
- {
- // Arrange
- var hotel1 = this.CreateTestHotel(hotelId: "key1", embedding: new[] { 30f, 31f, 32f, 33f });
- var hotel2 = this.CreateTestHotel(hotelId: "key2", embedding: new[] { 31f, 32f, 33f, 34f });
- var hotel3 = this.CreateTestHotel(hotelId: "key3", embedding: new[] { 20f, 20f, 20f, 20f });
- var hotel4 = this.CreateTestHotel(hotelId: "key4", embedding: new[] { -1000f, -1000f, -1000f, -1000f });
-
- using var sut = new CosmosNoSqlCollection(fixture.Database!, "vector-search-with-offset");
-
- await sut.EnsureCollectionExistsAsync();
-
- await sut.UpsertAsync([hotel4, hotel2, hotel3, hotel1]);
-
- // Act
- var searchResults = await sut.SearchAsync(new ReadOnlyMemory([30f, 31f, 32f, 33f]), top: 2, new()
- {
- Skip = 2
- }).ToListAsync();
-
- // Assert
- var ids = searchResults.Select(l => l.Record.HotelId).ToList();
-
- Assert.Equal("key3", ids[0]);
- Assert.Equal("key4", ids[1]);
-
- Assert.DoesNotContain("key1", ids);
- Assert.DoesNotContain("key2", ids);
- }
-
- [VectorStoreTheory]
- [MemberData(nameof(SearchWithFilterData))]
- public async Task SearchReturnsValidResultsWithFilterAsync(VectorSearchFilter filter, List expectedIds)
- {
- // Arrange
- var hotel1 = this.CreateTestHotel(hotelId: "key1", embedding: new[] { 30f, 31f, 32f, 33f });
- var hotel2 = this.CreateTestHotel(hotelId: "key2", embedding: new[] { 31f, 32f, 33f, 34f });
- var hotel3 = this.CreateTestHotel(hotelId: "key3", embedding: new[] { 20f, 20f, 20f, 20f });
- var hotel4 = this.CreateTestHotel(hotelId: "key4", embedding: new[] { -1000f, -1000f, -1000f, -1000f });
-
- using var sut = new CosmosNoSqlCollection(fixture.Database!, "vector-search-with-filter");
-
- await sut.EnsureCollectionExistsAsync();
-
- await sut.UpsertAsync([hotel4, hotel2, hotel3, hotel1]);
-
- // Act
- var searchResults = await sut.SearchAsync(new ReadOnlyMemory([30f, 31f, 32f, 33f]), top: 4, new()
- {
- OldFilter = filter,
- }).ToListAsync();
-
- // Assert
- var actualIds = searchResults.Select(l => l.Record.HotelId).ToList();
-
- Assert.Equal(expectedIds, actualIds);
- }
-
- [VectorStoreFact]
- public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
- var options = new CosmosNoSqlCollectionOptions
- {
- Definition = this.GetTestHotelRecordDefinition()
- };
-
- using var sut = new CosmosNoSqlDynamicCollection(fixture.Database!, "dynamic-mapper", options);
-
- await sut.EnsureCollectionExistsAsync();
-
- // Act
- await sut.UpsertAsync(new Dictionary
- {
- ["HotelId"] = HotelId,
-
- ["HotelName"] = "Dynamic Mapper Hotel",
- ["Description"] = "This is a dynamic mapper hotel",
- ["Tags"] = new List { "dynamic" },
- ["parking_is_included"] = false,
- ["Timestamp"] = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
- ["HotelRating"] = 3.6f,
-
- ["DescriptionEmbedding"] = new ReadOnlyMemory([30f, 31f, 32f, 33f])
- });
-
- var localGetResult = await sut.GetAsync(HotelId, new RecordRetrievalOptions { IncludeVectors = true });
-
- // Assert
- Assert.NotNull(localGetResult);
- Assert.Equal("Dynamic Mapper Hotel", localGetResult["HotelName"]);
- Assert.Equal("This is a dynamic mapper hotel", localGetResult["Description"]);
- Assert.Equal(new List { "dynamic" }, localGetResult["Tags"]);
- Assert.False((bool?)localGetResult["parking_is_included"]);
- Assert.Equal(new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero), localGetResult["Timestamp"]);
- Assert.Equal(3.6f, localGetResult["HotelRating"]);
- Assert.Equal(new[] { 30f, 31f, 32f, 33f }, ((ReadOnlyMemory)localGetResult["DescriptionEmbedding"]!).ToArray());
- }
-
- public static TheoryData> SearchWithFilterData => new()
- {
- {
- new VectorSearchFilter()
- .EqualTo(nameof(CosmosNoSqlHotel.HotelName), "My Hotel key2"),
- ["key2"]
- },
- {
- new VectorSearchFilter()
- .AnyTagEqualTo(nameof(CosmosNoSqlHotel.Tags), "t2"),
- ["key1", "key2", "key3", "key4"]
- },
- {
- new VectorSearchFilter()
- .EqualTo(nameof(CosmosNoSqlHotel.HotelName), "My Hotel key2")
- .AnyTagEqualTo(nameof(CosmosNoSqlHotel.Tags), "t2"),
- ["key2"]
- },
- {
- new VectorSearchFilter()
- .EqualTo(nameof(CosmosNoSqlHotel.HotelName), "non-existent-hotel")
- .AnyTagEqualTo(nameof(CosmosNoSqlHotel.Tags), "non-existent-tag"),
- []
- },
- };
-
- #region private
-
- private CosmosNoSqlHotel CreateTestHotel(
- string hotelId,
- string? hotelName = null,
- ReadOnlyMemory? embedding = null)
- {
- return new CosmosNoSqlHotel
- {
- HotelId = hotelId,
- HotelName = hotelName ?? $"My Hotel {hotelId}",
- HotelCode = 42,
- HotelRating = 4.5f,
- ParkingIncluded = true,
- Tags = { "t1", "t2" },
- Description = "This is a great hotel.",
- DescriptionEmbedding = embedding ?? new[] { 30f, 31f, 32f, 33f },
- Timestamp = new DateTimeOffset(2024, 9, 24, 17, 28, 32, TimeSpan.Zero),
- };
- }
-
- private VectorStoreCollectionDefinition GetTestHotelRecordDefinition()
- {
- return new()
- {
- Properties =
- [
- new VectorStoreKeyProperty("HotelId", typeof(string)),
- new VectorStoreDataProperty("HotelName", typeof(string)),
- new VectorStoreDataProperty("HotelCode", typeof(int)),
- new VectorStoreDataProperty("parking_is_included", typeof(bool)),
- new VectorStoreDataProperty("HotelRating", typeof(float)),
- new VectorStoreDataProperty("Tags", typeof(List)),
- new VectorStoreDataProperty("Description", typeof(string)),
- new VectorStoreDataProperty("Timestamp", typeof(DateTimeOffset)),
- new VectorStoreVectorProperty("DescriptionEmbedding", typeof(ReadOnlyMemory?), 4) { IndexKind = IndexKind.Flat, DistanceFunction = DistanceFunction.CosineSimilarity }
- ]
- };
- }
-
- #endregion
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlConnectionStringSetConditionAttribute.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlConnectionStringSetConditionAttribute.cs
deleted file mode 100644
index ceeb9fae5c1d..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlConnectionStringSetConditionAttribute.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Threading.Tasks;
-using SemanticKernel.IntegrationTests.Connectors.Memory.Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.CosmosNoSql;
-
-///
-/// Attribute to use to skip tests if the connection string for CosmosDB NoSQL is not set.
-///
-[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
-public sealed class CosmosNoSqlConnectionStringSetConditionAttribute : Attribute, ITestCondition
-{
- public ValueTask IsMetAsync()
- {
- var isMet = !string.IsNullOrEmpty(CosmosNoSqlVectorStoreFixture.GetConnectionString());
-
- return ValueTask.FromResult(isMet);
- }
-
- public string SkipReason
- => $"CosmosDB NoSQL connection string was not specified in user secrets. Use the following command to set it: dotnet user-secrets set \"{CosmosNoSqlVectorStoreFixture.ConnectionStringKey}\" \"your_connection_string\"";
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlHotel.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlHotel.cs
deleted file mode 100644
index 74bdfe40e79e..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlHotel.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Text.Json.Serialization;
-using Microsoft.Extensions.VectorData;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.CosmosNoSql;
-
-#pragma warning disable CS8618
-
-public record CosmosNoSqlHotel()
-{
- /// The key of the record.
- [VectorStoreKey]
- public string HotelId { get; init; }
-
- /// A string metadata field.
- [VectorStoreData(IsIndexed = true)]
- public string? HotelName { get; set; }
-
- /// An int metadata field.
- [VectorStoreData(IsFullTextIndexed = true)]
- public int HotelCode { get; set; }
-
- /// A float metadata field.
- [VectorStoreData]
- public float? HotelRating { get; set; }
-
- /// A bool metadata field.
- [JsonPropertyName("parking_is_included")]
- [VectorStoreData]
- public bool ParkingIncluded { get; set; }
-
- /// An array metadata field.
- [VectorStoreData]
- public List Tags { get; set; } = [];
-
- /// A data field.
- [VectorStoreData]
- public string Description { get; set; }
-
- /// A datetime field.
- [VectorStoreData]
- public DateTimeOffset Timestamp { get; set; }
-
- /// A vector field.
- [VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Flat)]
- public ReadOnlyMemory? DescriptionEmbedding { get; set; }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlVectorStoreFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlVectorStoreFixture.cs
deleted file mode 100644
index fa16e85167dd..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlVectorStoreFixture.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Net.Http;
-using System.Text.Json;
-using System.Threading.Tasks;
-using Microsoft.Azure.Cosmos;
-using Microsoft.Extensions.Configuration;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.CosmosNoSql;
-
-public class CosmosNoSqlVectorStoreFixture : IAsyncLifetime, IDisposable
-{
- public const string ConnectionStringKey = "CosmosNoSql:ConnectionString";
- private const string DatabaseName = "testdb";
-
- private readonly CosmosClient _cosmosClient;
-
- /// that can be used to manage the collections in Azure CosmosDB NoSQL.
- public Database? Database { get; private set; }
-
- public CosmosNoSqlVectorStoreFixture()
- {
- var connectionString = GetConnectionString();
- if (string.IsNullOrWhiteSpace(connectionString))
- {
- throw new ArgumentNullException($"{connectionString} string is not configured");
- }
-
- var options = new CosmosClientOptions
- {
- UseSystemTextJsonSerializerWithOptions = JsonSerializerOptions.Default,
- ConnectionMode = ConnectionMode.Gateway,
-#pragma warning disable CA5400 // HttpClient may be created without enabling CheckCertificateRevocationList
- HttpClientFactory = () => new HttpClient(new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator })
-#pragma warning restore CA5400 // HttpClient may be created without enabling CheckCertificateRevocationList
- };
-
- this._cosmosClient = new CosmosClient(connectionString, options);
- }
-
- public static string? GetConnectionString()
- {
- var configuration = new ConfigurationBuilder()
- .AddJsonFile(path: "testsettings.json", optional: false, reloadOnChange: true)
- .AddJsonFile(
- path: "testsettings.development.json",
- optional: true,
- reloadOnChange: true
- )
- .AddEnvironmentVariables()
- .AddUserSecrets()
- .Build();
-
- return configuration[ConnectionStringKey];
- }
-
- public async Task InitializeAsync()
- {
- await this._cosmosClient.CreateDatabaseIfNotExistsAsync(DatabaseName);
-
- this.Database = this._cosmosClient.GetDatabase(DatabaseName);
- }
-
- public async Task DisposeAsync()
- {
- await this.Database!.DeleteAsync();
- }
-
- public void Dispose()
- {
- this.Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- this._cosmosClient.Dispose();
- }
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlVectorStoreTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlVectorStoreTests.cs
deleted file mode 100644
index 472f9a9551cf..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/CosmosNoSqlVectorStoreTests.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Microsoft.SemanticKernel.Connectors.CosmosNoSql;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.CosmosNoSql;
-
-///
-/// Integration tests for .
-///
-[Collection("CosmosNoSqlCollection")]
-[CosmosNoSqlConnectionStringSetCondition]
-public sealed class CosmosNoSqlVectorStoreTests(CosmosNoSqlVectorStoreFixture fixture)
-#pragma warning disable CA2000 // Dispose objects before losing scope
- : BaseVectorStoreTests(new CosmosNoSqlVectorStore(fixture.Database!))
-#pragma warning restore CA2000 // Dispose objects before losing scope
-{
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/DataHelper.cs b/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/DataHelper.cs
deleted file mode 100644
index 651e67de4523..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/CosmosNoSql/DataHelper.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Linq;
-using System.Numerics.Tensors;
-using Microsoft.SemanticKernel.Memory;
-
-namespace SemanticKernel.IntegrationTests.Connectors.CosmosNoSql;
-
-internal static class DataHelper
-{
- public static MemoryRecord[] VectorSearchExpectedResults { get; }
- public static MemoryRecord[] VectorSearchTestRecords { get; }
- public static float[] VectorSearchTestEmbedding { get; }
-
- static DataHelper()
- {
- VectorSearchTestRecords = CreateBatchRecords(8);
- VectorSearchTestEmbedding = new[] { 1, 0.699f, 0.701f };
- VectorSearchExpectedResults = VectorSearchTestRecords
- .OrderByDescending(r => TensorPrimitives.CosineSimilarity(r.Embedding.Span, VectorSearchTestEmbedding))
- .ToArray();
- }
-
- public static MemoryRecord[] CreateBatchRecords(int count) =>
- Enumerable
- .Range(0, count)
- .Select(i => MemoryRecord.LocalRecord(
- id: $"test_{i}",
- text: $"text_{i}",
- description: $"description_{i}",
- embedding: new[] { 1, (float)Math.Cos(Math.PI * i / count), (float)Math.Sin(Math.PI * i / count) },
- key: $"test_{i}",
- timestamp: DateTimeOffset.Now))
- .ToArray();
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/InMemory/CommonInMemoryVectorStoreRecordCollectionTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/InMemory/CommonInMemoryVectorStoreRecordCollectionTests.cs
deleted file mode 100644
index 61df5cb49429..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/InMemory/CommonInMemoryVectorStoreRecordCollectionTests.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System.Collections.Generic;
-using Microsoft.Extensions.VectorData;
-using Microsoft.SemanticKernel.Connectors.InMemory;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.InMemory;
-
-///
-/// Inherits common integration tests that should pass for any .
-///
-public class CommonInMemoryVectorStoreRecordCollectionTests() : BaseVectorStoreRecordCollectionTests
-{
- protected override string Key1 => "1";
- protected override string Key2 => "2";
- protected override string Key3 => "3";
- protected override string Key4 => "4";
-
- protected override VectorStoreCollection GetTargetRecordCollection(string recordCollectionName, VectorStoreCollectionDefinition? definition)
- {
- return new InMemoryCollection(recordCollectionName, new()
- {
- Definition = definition
- });
- }
-
- protected override HashSet GetSupportedDistanceFunctions()
- {
- return [DistanceFunction.CosineDistance, DistanceFunction.CosineSimilarity, DistanceFunction.DotProductSimilarity, DistanceFunction.EuclideanDistance];
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/InMemory/InMemoryVectorStoreTextSearchTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/InMemory/InMemoryVectorStoreTextSearchTests.cs
deleted file mode 100644
index bd9658cfb6da..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/InMemory/InMemoryVectorStoreTextSearchTests.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Threading.Tasks;
-using Microsoft.Extensions.AI;
-using Microsoft.Extensions.Configuration;
-using Microsoft.SemanticKernel.Connectors.InMemory;
-using Microsoft.SemanticKernel.Data;
-using OpenAI;
-using SemanticKernel.IntegrationTests.Data;
-using SemanticKernel.IntegrationTests.TestSettings;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.InMemory;
-
-///
-/// Integration tests for using with .
-///
-public class InMemoryVectorStoreTextSearchTests : BaseVectorStoreTextSearchTests
-{
- ///
- public override async Task CreateTextSearchAsync()
- {
- if (this.VectorStore is null)
- {
- OpenAIConfiguration? openAIConfiguration = this.Configuration.GetSection("OpenAIEmbeddings").Get();
- Assert.NotNull(openAIConfiguration);
- Assert.NotNull(openAIConfiguration.ModelId);
- Assert.NotNull(openAIConfiguration.ApiKey);
-
- this.EmbeddingGenerator = new OpenAIClient(openAIConfiguration.ApiKey)
- .GetEmbeddingClient(openAIConfiguration.ModelId)
- .AsIEmbeddingGenerator();
-
- // Delegate which will create a record.
- static DataModel CreateRecord(int index, string text, ReadOnlyMemory embedding)
- {
- var guid = Guid.NewGuid();
- return new()
- {
- Key = guid,
- Text = text,
- Link = $"noop://{guid}",
- Tag = index % 2 == 0 ? "Even" : "Odd",
- Embedding = embedding
- };
- }
-
- this.VectorStore = new InMemoryVectorStore();
- await AddRecordsAsync(this.VectorStore, "records", this.EmbeddingGenerator, CreateRecord);
- }
-
- var vectorSearch = this.VectorStore.GetCollection("records");
- var stringMapper = new DataModelTextSearchStringMapper();
- var resultMapper = new DataModelTextSearchResultMapper();
-
- // TODO: Once OpenAITextEmbeddingGenerationService implements MEAI's IEmbeddingGenerator (#10811), configure it with the InMemoryVectorStore above instead of passing it here.
- return new VectorStoreTextSearch(vectorSearch, this.EmbeddingGenerator!, stringMapper, resultMapper);
- }
-
- ///
- public override string GetQuery() => "What is the Semantic Kernel?";
-
- ///
- public override TextSearchFilter GetTextSearchFilter() => new TextSearchFilter().Equality("Tag", "Even");
-
- ///
- public override bool VerifySearchResults(object[] results, string query, TextSearchFilter? filter = null)
- {
- Assert.NotNull(results);
- Assert.NotEmpty(results);
- Assert.Equal(4, results.Length);
- foreach (var result in results)
- {
- Assert.NotNull(result);
- Assert.IsType(result);
- }
-
- return true;
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/Milvus/MilvusFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/Milvus/MilvusFixture.cs
deleted file mode 100644
index c944cc86fd36..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/Milvus/MilvusFixture.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System.Threading.Tasks;
-using Milvus.Client;
-using Testcontainers.Milvus;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Milvus;
-
-public sealed class MilvusFixture : IAsyncLifetime
-{
- private readonly MilvusContainer _container = new MilvusBuilder().Build();
-
- public string Host => this._container.Hostname;
- public int Port => this._container.GetMappedPublicPort(MilvusBuilder.MilvusGrpcPort);
-
- public MilvusClient CreateClient()
- => new(this.Host, "root", "milvus", this.Port);
-
- public Task InitializeAsync()
- {
- return Task.CompletedTask;
- //=> this._container.StartAsync();
- }
-
- public Task DisposeAsync()
- {
- return Task.CompletedTask;
- //=> this._container.DisposeAsync().AsTask();
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/Milvus/MilvusMemoryStoreTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/Milvus/MilvusMemoryStoreTests.cs
deleted file mode 100644
index 5ca5e8a26c17..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/Milvus/MilvusMemoryStoreTests.cs
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.SemanticKernel.Connectors.Milvus;
-using Microsoft.SemanticKernel.Memory;
-using Milvus.Client;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Milvus;
-
-[Experimental("SKEXP0020")]
-public class MilvusMemoryStoreTests(MilvusFixture milvusFixture) : IClassFixture, IAsyncLifetime
-{
- private const string CollectionName = "test";
- private const string? SkipReason = "Fail starting Milvus container on GitHub intermittently.";
-
- private readonly MilvusFixture _milvusFixture = milvusFixture;
- private MilvusMemoryStore Store { get; set; } = null!;
-
- [Fact(Skip = SkipReason)]
- public async Task CreateCollectionAsync()
- {
- Assert.False(await this.Store.DoesCollectionExistAsync(CollectionName));
-
- await this.Store.CreateCollectionAsync(CollectionName);
- Assert.True(await this.Store.DoesCollectionExistAsync(CollectionName));
- }
-
- [Fact(Skip = SkipReason)]
- public async Task DropCollectionAsync()
- {
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.Store.DeleteCollectionAsync(CollectionName);
- Assert.False(await this.Store.DoesCollectionExistAsync(CollectionName));
- }
-
- [Fact(Skip = SkipReason)]
- public async Task GetCollectionsAsync()
- {
- await this.Store.CreateCollectionAsync("collection1");
- await this.Store.CreateCollectionAsync("collection2");
-
- List collections = await this.Store.GetCollectionsAsync().ToListAsync();
- Assert.Contains("collection1", collections);
- Assert.Contains("collection2", collections);
- }
-
- [Fact(Skip = SkipReason)]
- public async Task UpsertAsync()
- {
- await this.Store.CreateCollectionAsync(CollectionName);
-
- string id = await this.Store.UpsertAsync(CollectionName, new MemoryRecord(
- new MemoryRecordMetadata(
- isReference: true,
- id: "Some id",
- description: "Some description",
- text: "Some text",
- externalSourceName: "Some external resource name",
- additionalMetadata: "Some additional metadata"),
- new[] { 10f, 11f, 12f, 13f, 14f },
- key: "Some key",
- timestamp: new DateTimeOffset(2023, 1, 1, 12, 0, 0, TimeSpan.Zero)));
-
- Assert.Equal("Some id", id);
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task GetAsync(bool withEmbeddings)
- {
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.InsertSampleDataAsync();
-
- MemoryRecord? record = await this.Store.GetAsync(CollectionName, "Some id", withEmbedding: withEmbeddings);
- Assert.NotNull(record);
-
- Assert.True(record.Metadata.IsReference);
- Assert.Equal("Some id", record.Metadata.Id);
- Assert.Equal("Some description", record.Metadata.Description);
- Assert.Equal("Some text", record.Metadata.Text);
- Assert.Equal("Some external resource name", record.Metadata.ExternalSourceName);
- Assert.Equal("Some additional metadata", record.Metadata.AdditionalMetadata);
- Assert.Equal("Some key", record.Key);
- Assert.Equal(new DateTimeOffset(2023, 1, 1, 12, 0, 0, TimeSpan.Zero), record.Timestamp);
-
- Assert.Equal(
- withEmbeddings ? [10f, 11f, 12f, 13f, 14f] : [],
- record.Embedding.ToArray());
- }
-
- [Fact(Skip = SkipReason)]
- public async Task UpsertBatchAsync()
- {
- await this.Store.CreateCollectionAsync(CollectionName);
- List ids = await this.InsertSampleDataAsync();
-
- Assert.Collection(ids,
- id => Assert.Equal("Some id", id),
- id => Assert.Equal("Some other id", id));
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task GetBatchAsync(bool withEmbeddings)
- {
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.InsertSampleDataAsync();
-
- List records = await this.Store.GetBatchAsync(CollectionName, ["Some id", "Some other id"], withEmbeddings: withEmbeddings).ToListAsync();
-
- Assert.Collection(records.OrderBy(r => r.Metadata.Id),
- r =>
- {
- Assert.True(r.Metadata.IsReference);
- Assert.Equal("Some id", r.Metadata.Id);
- Assert.Equal("Some description", r.Metadata.Description);
- Assert.Equal("Some text", r.Metadata.Text);
- Assert.Equal("Some external resource name", r.Metadata.ExternalSourceName);
- Assert.Equal("Some additional metadata", r.Metadata.AdditionalMetadata);
- Assert.Equal("Some key", r.Key);
- Assert.Equal(new DateTimeOffset(2023, 1, 1, 12, 0, 0, TimeSpan.Zero), r.Timestamp);
-
- Assert.Equal(
- withEmbeddings ? [10f, 11f, 12f, 13f, 14f] : [],
- r.Embedding.ToArray());
- },
- r =>
- {
- Assert.False(r.Metadata.IsReference);
- Assert.Equal("Some other id", r.Metadata.Id);
- Assert.Empty(r.Metadata.Description);
- Assert.Empty(r.Metadata.Text);
- Assert.Empty(r.Metadata.ExternalSourceName);
- Assert.Empty(r.Metadata.AdditionalMetadata);
- Assert.Empty(r.Key);
- Assert.Null(r.Timestamp);
-
- Assert.Equal(
- withEmbeddings ? [20f, 21f, 22f, 23f, 24f] : [],
- r.Embedding.ToArray());
- });
- }
-
- [Fact(Skip = SkipReason)]
- public async Task RemoveAsync()
- {
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.InsertSampleDataAsync();
-
- using var milvusClient = this._milvusFixture.CreateClient();
-
- Assert.NotNull(await this.Store.GetAsync(CollectionName, "Some id"));
- await this.Store.RemoveAsync(CollectionName, "Some id");
- Assert.Null(await this.Store.GetAsync(CollectionName, "Some id"));
- }
-
- [Fact(Skip = SkipReason)]
- public async Task RemoveBatchAsync()
- {
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.InsertSampleDataAsync();
-
- Assert.NotNull(await this.Store.GetAsync(CollectionName, "Some id"));
- Assert.NotNull(await this.Store.GetAsync(CollectionName, "Some other id"));
- await this.Store.RemoveBatchAsync(CollectionName, ["Some id", "Some other id"]);
- Assert.Null(await this.Store.GetAsync(CollectionName, "Some id"));
- Assert.Null(await this.Store.GetAsync(CollectionName, "Some other id"));
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task GetNearestMatchesAsync(bool withEmbeddings)
- {
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.InsertSampleDataAsync();
-
- // There seems to be some race condition where the upserted data above isn't taken into account in the search below and zero results are returned...
- await Task.Delay(1000);
-
- List<(MemoryRecord Record, double SimilarityScore)> results =
- await this.Store.GetNearestMatchesAsync(CollectionName, new[] { 5f, 6f, 7f, 8f, 9f }, limit: 2, withEmbeddings: withEmbeddings).ToListAsync();
-
- Assert.All(results, t => Assert.True(t.SimilarityScore > 0));
-
- Assert.Collection(results.OrderBy(r => r.SimilarityScore).Select(r => r.Record),
- r =>
- {
- Assert.True(r.Metadata.IsReference);
- Assert.Equal("Some id", r.Metadata.Id);
- Assert.Equal("Some description", r.Metadata.Description);
- Assert.Equal("Some text", r.Metadata.Text);
- Assert.Equal("Some external resource name", r.Metadata.ExternalSourceName);
- Assert.Equal("Some additional metadata", r.Metadata.AdditionalMetadata);
- Assert.Equal("Some key", r.Key);
- Assert.Equal(new DateTimeOffset(2023, 1, 1, 12, 0, 0, TimeSpan.Zero), r.Timestamp);
-
- Assert.Equal(
- withEmbeddings ? [10f, 11f, 12f, 13f, 14f] : [],
- r.Embedding.ToArray());
- },
- r =>
- {
- Assert.False(r.Metadata.IsReference);
- Assert.Equal("Some other id", r.Metadata.Id);
- Assert.Empty(r.Metadata.Description);
- Assert.Empty(r.Metadata.Text);
- Assert.Empty(r.Metadata.ExternalSourceName);
- Assert.Empty(r.Metadata.AdditionalMetadata);
- Assert.Empty(r.Key);
- Assert.Null(r.Timestamp);
-
- Assert.Equal(
- withEmbeddings ? [20f, 21f, 22f, 23f, 24f] : [],
- r.Embedding.ToArray());
- });
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task GetNearestMatchesWithMetricTypeAsync(bool withEmbeddings)
- {
- //Create collection with default, Ip metric
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.InsertSampleDataAsync();
- await this.Store.Client.FlushAsync([CollectionName]);
-
- //Search with Ip metric, run correctly
- List<(MemoryRecord Record, double SimilarityScore)> ipResults =
- await this.Store.GetNearestMatchesAsync(CollectionName, new[] { 5f, 6f, 7f, 8f, 9f }, limit: 2, withEmbeddings: withEmbeddings).ToListAsync();
-
- Assert.All(ipResults, t => Assert.True(t.SimilarityScore > 0));
-
- //Set the store to Cosine metric, without recreate collection
- this.Store = new(this._milvusFixture.Host, vectorSize: 5, port: this._milvusFixture.Port, metricType: SimilarityMetricType.Cosine, consistencyLevel: ConsistencyLevel.Strong);
-
- //An exception will be thrown here, the exception message includes "metric type not match"
- MilvusException milvusException = await Assert.ThrowsAsync(async () => await this.Store.GetNearestMatchesAsync(CollectionName, new[] { 5f, 6f, 7f, 8f, 9f }, limit: 2, withEmbeddings: withEmbeddings).ToListAsync());
-
- Assert.NotNull(milvusException);
-
- Assert.Contains("metric type not match", milvusException.Message);
-
- //Recreate collection with Cosine metric
- await this.Store.DeleteCollectionAsync(CollectionName);
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.InsertSampleDataAsync();
- await this.Store.Client.FlushAsync([CollectionName]);
-
- //Search with Ip metric, run correctly
- List<(MemoryRecord Record, double SimilarityScore)> cosineResults =
- await this.Store.GetNearestMatchesAsync(CollectionName, new[] { 5f, 6f, 7f, 8f, 9f }, limit: 2, withEmbeddings: withEmbeddings).ToListAsync();
-
- Assert.All(cosineResults, t => Assert.True(t.SimilarityScore > 0));
- }
-
- [Fact(Skip = SkipReason)]
- public async Task GetNearestMatchesWithMinRelevanceScoreAsync()
- {
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.InsertSampleDataAsync();
-
- List<(MemoryRecord Record, double SimilarityScore)> results =
- await this.Store.GetNearestMatchesAsync(CollectionName, new[] { 5f, 6f, 7f, 8f, 9f }, limit: 2).ToListAsync();
-
- string firstId = results[0].Record.Metadata.Id;
- double firstSimilarityScore = results[0].SimilarityScore;
-
- results = await this.Store.GetNearestMatchesAsync(CollectionName, new[] { 5f, 6f, 7f, 8f, 9f }, limit: 2, minRelevanceScore: firstSimilarityScore + 0.0001).ToListAsync();
-
- Assert.DoesNotContain(firstId, results.Select(r => r.Record.Metadata.Id));
- }
-
- [Theory(Skip = SkipReason)]
- [InlineData(true)]
- [InlineData(false)]
- public async Task GetNearestMatchAsync(bool withEmbeddings)
- {
- await this.Store.CreateCollectionAsync(CollectionName);
- await this.InsertSampleDataAsync();
-
- (MemoryRecord Record, double SimilarityScore)? result =
- await this.Store.GetNearestMatchAsync(CollectionName, new[] { 20f, 21f, 22f, 23f, 24f }, withEmbedding: withEmbeddings);
-
- Assert.NotNull(result);
- Assert.True(result.Value.SimilarityScore > 0);
- MemoryRecord record = result.Value.Record;
-
- Assert.Equal("Some other id", record.Metadata.Id);
- Assert.Equal(
- withEmbeddings ? [20f, 21f, 22f, 23f, 24f] : [],
- record.Embedding.ToArray());
- }
-
- private async Task> InsertSampleDataAsync()
- {
- IAsyncEnumerable ids = this.Store.UpsertBatchAsync(CollectionName,
- [
- new MemoryRecord(
- new MemoryRecordMetadata(
- isReference: true,
- id: "Some id",
- description: "Some description",
- text: "Some text",
- externalSourceName: "Some external resource name",
- additionalMetadata: "Some additional metadata"),
- new[] { 10f, 11f, 12f, 13f, 14f },
- key: "Some key",
- timestamp: new DateTimeOffset(2023, 1, 1, 12, 0, 0, TimeSpan.Zero)),
- new MemoryRecord(
- new MemoryRecordMetadata(
- isReference: false,
- id: "Some other id",
- description: "",
- text: "",
- externalSourceName: "",
- additionalMetadata: ""),
- new[] { 20f, 21f, 22f, 23f, 24f },
- key: null,
- timestamp: null),
- ]);
-
- List idList = [];
-
- await foreach (string id in ids)
- {
- idList.Add(id);
- }
-
- return idList;
- }
-
- public async Task InitializeAsync()
- {
- this.Store = new(this._milvusFixture.Host, vectorSize: 5, port: this._milvusFixture.Port, consistencyLevel: ConsistencyLevel.Strong);
- await this.Store.DeleteCollectionAsync(CollectionName);
- }
-
- public Task DisposeAsync()
- {
- this.Store.Dispose();
- return Task.CompletedTask;
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/DataHelper.cs b/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/DataHelper.cs
deleted file mode 100644
index fd0a634b47be..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/DataHelper.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Linq;
-using System.Numerics.Tensors;
-using Microsoft.SemanticKernel.Memory;
-
-namespace SemanticKernel.IntegrationTests.Connectors.MongoDB;
-
-internal static class DataHelper
-{
- public static MemoryRecord[] VectorSearchExpectedResults { get; }
- public static MemoryRecord[] VectorSearchTestRecords { get; }
- public static float[] VectorSearchTestEmbedding { get; }
-
- static DataHelper()
- {
- VectorSearchTestRecords = CreateBatchRecords(8);
- VectorSearchTestEmbedding = [1, 0.699f, 0.701f];
- VectorSearchExpectedResults = [.. VectorSearchTestRecords.OrderByDescending(r => TensorPrimitives.CosineSimilarity(r.Embedding.Span, VectorSearchTestEmbedding))];
- }
-
- public static MemoryRecord CreateRecord(string id) =>
- MemoryRecord.LocalRecord(
- id: id,
- text: $"text_{id}",
- description: $"description_{id}",
- embedding: new[] { 1.1f, 2.2f, 3.3f },
- timestamp: GetDateTime());
-
- public static MemoryRecord[] CreateBatchRecords(int count) =>
- Enumerable
- .Range(0, count)
- .Select(i => MemoryRecord.LocalRecord(
- id: $"test_{i}",
- text: $"text_{i}",
- description: $"description_{i}",
- embedding: new[] { 1, (float)Math.Cos(Math.PI * i / count), (float)Math.Sin(Math.PI * i / count) },
- timestamp: GetDateTime()))
- .ToArray();
-
- private static DateTime GetDateTime() =>
- new(TimeSpan.TicksPerMillisecond * (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond), DateTimeKind.Local);
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBHotel.cs b/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBHotel.cs
deleted file mode 100644
index acf48766c4c9..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBHotel.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.VectorData;
-
-namespace SemanticKernel.IntegrationTests.Connectors.MongoDB;
-
-#pragma warning disable CS8618
-
-public class MongoDBHotel
-{
- /// The key of the record.
- [VectorStoreKey]
- public string HotelId { get; init; }
-
- /// A string metadata field.
- [VectorStoreData(IsIndexed = true)]
- public string? HotelName { get; set; }
-
- /// An int metadata field.
- [VectorStoreData]
- public int HotelCode { get; set; }
-
- /// A float metadata field.
- [VectorStoreData]
- public float? HotelRating { get; set; }
-
- /// A bool metadata field.
- [VectorStoreData(StorageName = "parking_is_included")]
- public bool ParkingIncluded { get; set; }
-
- /// An array metadata field.
- [VectorStoreData]
- public List Tags { get; set; } = [];
-
- /// A data field.
- [VectorStoreData]
- public string Description { get; set; }
-
- /// A datetime metadata field.
- [VectorStoreData]
- public DateTime Timestamp { get; set; }
-
- /// A vector field.
- [VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.IvfFlat)]
- public ReadOnlyMemory? DescriptionEmbedding { get; set; }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreCollectionFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreCollectionFixture.cs
deleted file mode 100644
index 7defbeec1f5c..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreCollectionFixture.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.MongoDB;
-
-[CollectionDefinition("MongoDBVectorStoreCollection")]
-public class MongoDBVectorStoreCollectionFixture : ICollectionFixture
-{ }
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreFixture.cs
deleted file mode 100644
index 5a17920cff6f..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreFixture.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using DotNet.Testcontainers.Containers;
-using Microsoft.Extensions.VectorData;
-using MongoDB.Driver;
-using Testcontainers.MongoDb;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.MongoDB;
-
-#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
-
-public class MongoDBVectorStoreFixture : IAsyncLifetime
-{
- private readonly MongoDbContainer _container = new MongoDbBuilder()
- .WithImage("mongodb/mongodb-atlas-local:7.0.6")
- .Build();
-
- private readonly List _testCollections = ["sk-test-hotels", "sk-test-contacts", "sk-test-addresses"];
-
- /// Main test collection for tests.
- public string TestCollection => this._testCollections[0];
-
- /// that can be used to manage the collections in MongoDB.
- public IMongoDatabase MongoDatabase { get; private set; }
-
- /// Gets the manually created vector store record definition for MongoDB test model.
- public VectorStoreCollectionDefinition HotelVectorStoreRecordDefinition { get; private set; }
-
- public async Task InitializeAsync()
- {
- using CancellationTokenSource cts = new();
- cts.CancelAfter(TimeSpan.FromSeconds(60));
- await this._container.StartAsync(cts.Token);
-
-#pragma warning disable CA2000 // Dispose objects before losing scope
- var mongoClient = new MongoClient(new MongoClientSettings
- {
- Server = new MongoServerAddress(this._container.Hostname, this._container.GetMappedPublicPort(MongoDbBuilder.MongoDbPort)),
- DirectConnection = true,
- });
-#pragma warning restore CA2000
-
- this.MongoDatabase = mongoClient.GetDatabase("test");
-
- this.HotelVectorStoreRecordDefinition = new()
- {
- Properties =
- [
- new VectorStoreKeyProperty("HotelId", typeof(string)),
- new VectorStoreDataProperty("HotelName", typeof(string)),
- new VectorStoreDataProperty("HotelCode", typeof(int)),
- new VectorStoreDataProperty("ParkingIncluded", typeof(bool)) { StorageName = "parking_is_included" },
- new VectorStoreDataProperty("HotelRating", typeof(float)),
- new VectorStoreDataProperty("Tags", typeof(List)),
- new VectorStoreDataProperty("Timestamp", typeof(DateTime)),
- new VectorStoreDataProperty("Description", typeof(string)),
- new VectorStoreVectorProperty("DescriptionEmbedding", typeof(ReadOnlyMemory?), 4) { IndexKind = IndexKind.IvfFlat, DistanceFunction = DistanceFunction.CosineSimilarity }
- ]
- };
-
- foreach (var collection in this._testCollections)
- {
- await this.MongoDatabase.CreateCollectionAsync(collection);
- }
- }
-
- public async Task DisposeAsync()
- {
- if (this.MongoDatabase is not null)
- {
- var cursor = await this.MongoDatabase.ListCollectionNamesAsync();
-
- while (await cursor.MoveNextAsync().ConfigureAwait(false))
- {
- foreach (var collection in cursor.Current)
- {
- await this.MongoDatabase.DropCollectionAsync(collection);
- }
- }
- }
-
- if (this._container is not null && this._container.State == TestcontainersStates.Running)
- {
- await this._container.StopAsync();
- }
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreRecordCollectionTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreRecordCollectionTests.cs
deleted file mode 100644
index 019776c3b9e5..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreRecordCollectionTests.cs
+++ /dev/null
@@ -1,519 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.Extensions.VectorData;
-using Microsoft.SemanticKernel.Connectors.MongoDB;
-using MongoDB.Bson;
-using MongoDB.Bson.Serialization.Attributes;
-using MongoDB.Driver;
-using xRetry;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.MongoDB;
-
-#pragma warning disable CS0618 // VectorSearchFilter is obsolete
-
-[Collection("MongoDBVectorStoreCollection")]
-public class MongoDBVectorStoreRecordCollectionTests(MongoDBVectorStoreFixture fixture)
-{
- // If null, all tests will be enabled
- private const string? SkipReason = "The MongoDB container is intermittently timing out at startup time blocking prs, so these test should be run manually.";
-
- [RetryTheory(typeof(MongoCommandException), Skip = SkipReason)]
- [InlineData("sk-test-hotels", true)]
- [InlineData("nonexistentcollection", false)]
- public async Task CollectionExistsReturnsCollectionStateAsync(string collectionName, bool expectedExists)
- {
- // Arrange
- using var sut = new MongoCollection(fixture.MongoDatabase, collectionName);
-
- // Act
- var actual = await sut.CollectionExistsAsync();
-
- // Assert
- Assert.Equal(expectedExists, actual);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task ItCanEnsureCollectionExistsAsync()
- {
- // Arrange
- var newCollection = Guid.NewGuid().ToString();
- using var sut = new MongoCollection(fixture.MongoDatabase, newCollection);
-
- // Act
- await sut.EnsureCollectionExistsAsync();
-
- // Assert
- Assert.True(await sut.CollectionExistsAsync());
- await sut.EnsureCollectionDeletedAsync();
- }
-
- [RetryTheory(typeof(MongoCommandException), Skip = SkipReason)]
- [InlineData(true, true)]
- [InlineData(true, false)]
- [InlineData(false, true)]
- [InlineData(false, false)]
- public async Task ItCanCreateCollectionUpsertAndGetAsync(bool includeVectors, bool useRecordDefinition)
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
-
- var collectionNamePostfix = useRecordDefinition ? "with-definition" : "with-type";
- collectionNamePostfix += includeVectors ? "-with-vectors" : "-without-vectors";
- var collectionName = $"collection-{collectionNamePostfix}";
-
- var options = new MongoCollectionOptions
- {
- Definition = useRecordDefinition ? fixture.HotelVectorStoreRecordDefinition : null
- };
-
- using var sut = new MongoCollection(fixture.MongoDatabase, collectionName, options);
-
- var record = this.CreateTestHotel(HotelId);
-
- // Act
- await sut.EnsureCollectionExistsAsync();
- await sut.UpsertAsync(record);
- var getResult = await sut.GetAsync(HotelId, new() { IncludeVectors = includeVectors });
-
- // Assert
- Assert.True(await sut.CollectionExistsAsync());
- await sut.EnsureCollectionDeletedAsync();
-
- Assert.NotNull(getResult);
-
- Assert.Equal(record.HotelId, getResult.HotelId);
- Assert.Equal(record.HotelName, getResult.HotelName);
- Assert.Equal(record.HotelCode, getResult.HotelCode);
- Assert.Equal(record.HotelRating, getResult.HotelRating);
- Assert.Equal(record.ParkingIncluded, getResult.ParkingIncluded);
- Assert.Equal(record.Tags.ToArray(), getResult.Tags.ToArray());
- Assert.Equal(record.Description, getResult.Description);
- Assert.Equal(record.Timestamp.ToUniversalTime(), getResult.Timestamp.ToUniversalTime());
-
- if (includeVectors)
- {
- Assert.NotNull(getResult.DescriptionEmbedding);
- Assert.Equal(record.DescriptionEmbedding!.Value.ToArray(), getResult.DescriptionEmbedding.Value.ToArray());
- }
- else
- {
- Assert.Null(getResult.DescriptionEmbedding);
- }
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task ItCanDeleteCollectionAsync()
- {
- // Arrange
- const string TempCollectionName = "temp-test";
- await fixture.MongoDatabase.CreateCollectionAsync(TempCollectionName);
-
- using var sut = new MongoCollection(fixture.MongoDatabase, TempCollectionName);
-
- Assert.True(await sut.CollectionExistsAsync());
-
- // Act
- await sut.EnsureCollectionDeletedAsync();
-
- // Assert
- Assert.False(await sut.CollectionExistsAsync());
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task ItCanGetAndDeleteRecordAsync()
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
- using var sut = new MongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- var record = this.CreateTestHotel(HotelId);
-
- await sut.UpsertAsync(record);
- var getResult = await sut.GetAsync(HotelId);
-
- Assert.NotNull(getResult);
-
- // Act
- await sut.DeleteAsync(HotelId);
-
- getResult = await sut.GetAsync(HotelId);
-
- // Assert
- Assert.Null(getResult);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task ItCanGetAndDeleteBatchAsync()
- {
- // Arrange
- const string HotelId1 = "11111111-1111-1111-1111-111111111111";
- const string HotelId2 = "22222222-2222-2222-2222-222222222222";
- const string HotelId3 = "33333333-3333-3333-3333-333333333333";
-
- using var sut = new MongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- var record1 = this.CreateTestHotel(HotelId1);
- var record2 = this.CreateTestHotel(HotelId2);
- var record3 = this.CreateTestHotel(HotelId3);
-
- await sut.UpsertAsync([record1, record2, record3]);
-
- var getResults = await sut.GetAsync([HotelId1, HotelId2, HotelId3]).ToListAsync();
-
- Assert.NotNull(getResults.First(l => l.HotelId == HotelId1));
- Assert.NotNull(getResults.First(l => l.HotelId == HotelId2));
- Assert.NotNull(getResults.First(l => l.HotelId == HotelId3));
-
- // Act
- await sut.DeleteAsync([HotelId1, HotelId2, HotelId3]);
-
- getResults = await sut.GetAsync([HotelId1, HotelId2, HotelId3]).ToListAsync();
-
- // Assert
- Assert.Empty(getResults);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task ItCanUpsertRecordAsync()
- {
- // Arrange
- const string HotelId = "55555555-5555-5555-5555-555555555555";
- using var sut = new MongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- var record = this.CreateTestHotel(HotelId);
-
- await sut.UpsertAsync(record);
- var getResult = await sut.GetAsync(HotelId);
-
- Assert.NotNull(getResult);
-
- // Act
- record.HotelName = "Updated name";
- record.HotelRating = 10;
-
- await sut.UpsertAsync(record);
- getResult = await sut.GetAsync(HotelId);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("Updated name", getResult.HotelName);
- Assert.Equal(10, getResult.HotelRating);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task UpsertWithModelWorksCorrectlyAsync()
- {
- // Arrange
- var definition = new VectorStoreCollectionDefinition
- {
- Properties =
- [
- new VectorStoreKeyProperty("Id", typeof(string)),
- new VectorStoreDataProperty("HotelName", typeof(string))
- ]
- };
-
- var model = new TestModel { Id = "key", HotelName = "Test Name" };
-
- using var sut = new MongoCollection(
- fixture.MongoDatabase,
- fixture.TestCollection,
- new() { Definition = definition });
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.Id);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.Id);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task UpsertWithVectorStoreModelWorksCorrectlyAsync()
- {
- // Arrange
- var model = new VectorStoreTestModel { HotelId = "key", HotelName = "Test Name" };
-
- using var sut = new MongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.HotelId);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.HotelId);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task UpsertWithBsonModelWorksCorrectlyAsync()
- {
- // Arrange
- var definition = new VectorStoreCollectionDefinition
- {
- Properties =
- [
- new VectorStoreKeyProperty("Id", typeof(string)),
- new VectorStoreDataProperty("HotelName", typeof(string))
- ]
- };
-
- var model = new BsonTestModel { Id = "key", HotelName = "Test Name" };
-
- using var sut = new MongoCollection(
- fixture.MongoDatabase,
- fixture.TestCollection,
- new() { Definition = definition });
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.Id);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.Id);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task UpsertWithBsonVectorStoreModelWorksCorrectlyAsync()
- {
- // Arrange
- var model = new BsonVectorStoreTestModel { HotelId = "key", HotelName = "Test Name" };
-
- using var sut = new MongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.HotelId);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.HotelId);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task UpsertWithBsonVectorStoreWithNameModelWorksCorrectlyAsync()
- {
- // Arrange
- var model = new BsonVectorStoreWithNameTestModel { Id = "key", HotelName = "Test Name" };
-
- using var sut = new MongoCollection(fixture.MongoDatabase, fixture.TestCollection);
-
- // Act
- await sut.UpsertAsync(model);
- var getResult = await sut.GetAsync(model.Id);
-
- // Assert
- Assert.NotNull(getResult);
- Assert.Equal("key", getResult.Id);
- Assert.Equal("Test Name", getResult.HotelName);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task SearchReturnsValidResultsByDefaultAsync()
- {
- // Arrange
- var hotel1 = this.CreateTestHotel(hotelId: "key1", embedding: new[] { 30f, 31f, 32f, 33f });
- var hotel2 = this.CreateTestHotel(hotelId: "key2", embedding: new[] { 31f, 32f, 33f, 34f });
- var hotel3 = this.CreateTestHotel(hotelId: "key3", embedding: new[] { 20f, 20f, 20f, 20f });
- var hotel4 = this.CreateTestHotel(hotelId: "key4", embedding: new[] { -1000f, -1000f, -1000f, -1000f });
-
- using var sut = new MongoCollection(fixture.MongoDatabase, "TestVectorizedSearch");
-
- await sut.EnsureCollectionExistsAsync();
-
- await sut.UpsertAsync([hotel4, hotel2, hotel3, hotel1]);
-
- // Act
- var searchResults = await sut.SearchAsync(new ReadOnlyMemory([30f, 31f, 32f, 33f]), top: 3).ToListAsync();
-
- // Assert
- var ids = searchResults.Select(l => l.Record.HotelId).ToList();
-
- Assert.Equal("key1", ids[0]);
- Assert.Equal("key2", ids[1]);
- Assert.Equal("key3", ids[2]);
-
- Assert.DoesNotContain("key4", ids);
-
- Assert.Equal(1, searchResults.First(l => l.Record.HotelId == "key1").Score);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task SearchReturnsValidResultsWithOffsetAsync()
- {
- // Arrange
- var hotel1 = this.CreateTestHotel(hotelId: "key1", embedding: new[] { 30f, 31f, 32f, 33f });
- var hotel2 = this.CreateTestHotel(hotelId: "key2", embedding: new[] { 31f, 32f, 33f, 34f });
- var hotel3 = this.CreateTestHotel(hotelId: "key3", embedding: new[] { 20f, 20f, 20f, 20f });
- var hotel4 = this.CreateTestHotel(hotelId: "key4", embedding: new[] { -1000f, -1000f, -1000f, -1000f });
-
- using var sut = new MongoCollection(fixture.MongoDatabase, "TestVectorizedSearchWithOffset");
-
- await sut.EnsureCollectionExistsAsync();
-
- await sut.UpsertAsync([hotel4, hotel2, hotel3, hotel1]);
-
- // Act
- var searchResults = await sut.SearchAsync(new ReadOnlyMemory([30f, 31f, 32f, 33f]), top: 2, new()
- {
- Skip = 2
- }).ToListAsync();
-
- // Assert
- var ids = searchResults.Select(l => l.Record.HotelId).ToList();
-
- Assert.Equal("key3", ids[0]);
- Assert.Equal("key4", ids[1]);
-
- Assert.DoesNotContain("key1", ids);
- Assert.DoesNotContain("key2", ids);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task SearchReturnsValidResultsWithFilterAsync()
- {
- // Arrange
- var hotel1 = this.CreateTestHotel(hotelId: "key1", embedding: new[] { 30f, 31f, 32f, 33f });
- var hotel2 = this.CreateTestHotel(hotelId: "key2", embedding: new[] { 31f, 32f, 33f, 34f });
- var hotel3 = this.CreateTestHotel(hotelId: "key3", embedding: new[] { 20f, 20f, 20f, 20f });
- var hotel4 = this.CreateTestHotel(hotelId: "key4", embedding: new[] { -1000f, -1000f, -1000f, -1000f });
-
- using var sut = new MongoCollection(fixture.MongoDatabase, "TestVectorizedSearchWithFilter");
-
- await sut.EnsureCollectionExistsAsync();
-
- await sut.UpsertAsync([hotel4, hotel2, hotel3, hotel1]);
-
- // Act
- var searchResults = await sut.SearchAsync(new ReadOnlyMemory([30f, 31f, 32f, 33f]), top: 3, new()
- {
- OldFilter = new VectorSearchFilter().EqualTo(nameof(MongoDBHotel.HotelName), "My Hotel key2")
- }).ToListAsync();
-
- // Assert
- var ids = searchResults.Select(l => l.Record.HotelId).ToList();
-
- Assert.Equal("key2", ids[0]);
-
- Assert.DoesNotContain("key1", ids);
- Assert.DoesNotContain("key3", ids);
- Assert.DoesNotContain("key4", ids);
- }
-
- [RetryFact(typeof(MongoCommandException), Skip = SkipReason)]
- public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
- {
- // Arrange
- var options = new MongoCollectionOptions
- {
- Definition = fixture.HotelVectorStoreRecordDefinition
- };
-
- using var sut = new MongoDynamicCollection(fixture.MongoDatabase, fixture.TestCollection, options);
-
- // Act
- await sut.UpsertAsync(new Dictionary
- {
- ["HotelId"] = "DynamicMapper-1",
-
- ["HotelName"] = "Dynamic Mapper Hotel",
- ["Description"] = "This is a dynamic mapper hotel",
- ["Tags"] = new string[] { "dynamic" },
- ["ParkingIncluded"] = false,
- ["Timestamp"] = new DateTime(1970, 1, 18, 0, 0, 0).ToUniversalTime(),
- ["HotelRating"] = 3.6f,
-
- ["DescriptionEmbedding"] = new ReadOnlyMemory([30f, 31f, 32f, 33f])
- });
-
- var localGetResult = await sut.GetAsync("DynamicMapper-1", new RecordRetrievalOptions { IncludeVectors = true });
-
- // Assert
- Assert.NotNull(localGetResult);
- Assert.Equal("Dynamic Mapper Hotel", localGetResult["HotelName"]);
- Assert.Equal("This is a dynamic mapper hotel", localGetResult["Description"]);
- Assert.Equal(new[] { "dynamic" }, localGetResult["Tags"]);
- Assert.False((bool?)localGetResult["ParkingIncluded"]);
- Assert.Equal(new DateTime(1970, 1, 18, 0, 0, 0).ToUniversalTime(), localGetResult["Timestamp"]);
- Assert.Equal(3.6f, localGetResult["HotelRating"]);
- Assert.Equal(new[] { 30f, 31f, 32f, 33f }, ((ReadOnlyMemory)localGetResult["DescriptionEmbedding"]!).ToArray());
- }
-
- #region private
-
- private MongoDBHotel CreateTestHotel(string hotelId, ReadOnlyMemory? embedding = null)
- {
- return new MongoDBHotel
- {
- HotelId = hotelId,
- HotelName = $"My Hotel {hotelId}",
- HotelCode = 42,
- HotelRating = 4.5f,
- ParkingIncluded = true,
- Tags = { "t1", "t2" },
- Description = "This is a great hotel.",
- Timestamp = new DateTime(2024, 09, 23, 15, 32, 33),
- DescriptionEmbedding = embedding ?? new[] { 30f, 31f, 32f, 33f },
- };
- }
-
- private sealed class TestModel
- {
- public string? Id { get; set; }
-
- public string? HotelName { get; set; }
- }
-
- private sealed class VectorStoreTestModel
- {
- [VectorStoreKey]
- public string? HotelId { get; set; }
-
- [VectorStoreData(StorageName = "hotel_name")]
- public string? HotelName { get; set; }
- }
-
- private sealed class BsonTestModel
- {
- [BsonId]
- public string? Id { get; set; }
-
- [BsonElement("hotel_name")]
- public string? HotelName { get; set; }
- }
-
- private sealed class BsonVectorStoreTestModel
- {
- [BsonId]
- [VectorStoreKey]
- public string? HotelId { get; set; }
-
- [BsonElement("hotel_name")]
- [VectorStoreData]
- public string? HotelName { get; set; }
- }
-
- private sealed class BsonVectorStoreWithNameTestModel
- {
- [BsonId]
- [VectorStoreKey]
- public string? Id { get; set; }
-
- [BsonElement("bson_hotel_name")]
- [VectorStoreData(StorageName = "storage_hotel_name")]
- public string? HotelName { get; set; }
- }
-
- #endregion
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreTests.cs
deleted file mode 100644
index 03af0b5c4c3f..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/MongoDB/MongoDBVectorStoreTests.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Microsoft.SemanticKernel.Connectors.MongoDB;
-using SemanticKernel.IntegrationTests.Connectors.Memory;
-using SemanticKernel.IntegrationTests.Connectors.Memory.Xunit;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.MongoDB;
-
-[Collection("MongoDBVectorStoreCollection")]
-[DisableVectorStoreTests(Skip = "The MongoDB container is intermittently timing out at startup time blocking prs, so these test should be run manually.")]
-public class MongoDBVectorStoreTests(MongoDBVectorStoreFixture fixture)
-#pragma warning disable CA2000 // Dispose objects before losing scope
- : BaseVectorStoreTests(new MongoVectorStore(fixture.MongoDatabase))
-#pragma warning restore CA2000 // Dispose objects before losing scope
-{
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/CommonPostgresVectorStoreRecordCollectionTests.cs b/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/CommonPostgresVectorStoreRecordCollectionTests.cs
deleted file mode 100644
index 225f81926a9c..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/CommonPostgresVectorStoreRecordCollectionTests.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System.Collections.Generic;
-using Microsoft.Extensions.VectorData;
-using Microsoft.SemanticKernel.Connectors.PgVector;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.PgVector;
-
-///
-/// Inherits common integration tests that should pass for any .
-///
-/// Postres setup and teardown.
-[Collection("PostgresVectorStoreCollection")]
-public class CommonPostgresVectorStoreRecordCollectionTests(PostgresVectorStoreFixture fixture) : BaseVectorStoreRecordCollectionTests
-{
- protected override string Key1 => "1";
- protected override string Key2 => "2";
- protected override string Key3 => "3";
- protected override string Key4 => "4";
-
- protected override VectorStoreCollection GetTargetRecordCollection(string recordCollectionName, VectorStoreCollectionDefinition? definition)
- {
- return new PostgresCollection(fixture.DataSource!, recordCollectionName, ownsDataSource: false, new()
- {
- Definition = definition
- });
- }
-
- protected override HashSet GetSupportedDistanceFunctions()
- {
- return [DistanceFunction.CosineDistance, DistanceFunction.CosineSimilarity, DistanceFunction.DotProductSimilarity, DistanceFunction.EuclideanDistance, DistanceFunction.ManhattanDistance];
- }
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/PostgresHotel.cs b/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/PostgresHotel.cs
deleted file mode 100644
index d25a38935925..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/PostgresHotel.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.VectorData;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.PgVector;
-
-#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
-
-///
-/// A test model for the postgres vector store.
-///
-public record PostgresHotel()
-{
- /// The key of the record.
- [VectorStoreKey]
- public T HotelId { get; init; }
-
- /// A string metadata field.
- [VectorStoreData()]
- public string? HotelName { get; set; }
-
- /// An int metadata field.
- [VectorStoreData()]
- public int HotelCode { get; set; }
-
- /// A float metadata field.
- [VectorStoreData()]
- public float? HotelRating { get; set; }
-
- /// A bool metadata field.
- [VectorStoreData(StorageName = "parking_is_included")]
- public bool ParkingIncluded { get; set; }
-
- [VectorStoreData]
- public List Tags { get; set; } = [];
-
- [VectorStoreData]
- public List? ListInts { get; set; } = null;
-
- /// A data field.
- [VectorStoreData]
- public string Description { get; set; }
-
- /// A vector field.
- [VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.EuclideanDistance, IndexKind = IndexKind.Hnsw)]
- public ReadOnlyMemory? DescriptionEmbedding { get; set; }
-
- public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
-
- public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
-
- public PostgresHotel(T key) : this()
- {
- this.HotelId = key;
- }
-}
-
-#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/PostgresVectorStoreCollectionFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/PostgresVectorStoreCollectionFixture.cs
deleted file mode 100644
index 066752a822cc..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/PostgresVectorStoreCollectionFixture.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.PgVector;
-
-[CollectionDefinition("PostgresVectorStoreCollection")]
-public class PostgresVectorStoreCollectionFixture : ICollectionFixture
-{
-}
diff --git a/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/PostgresVectorStoreFixture.cs b/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/PostgresVectorStoreFixture.cs
deleted file mode 100644
index b9f71202810d..000000000000
--- a/dotnet/src/IntegrationTests/Connectors/Memory/PgVector/PostgresVectorStoreFixture.cs
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Docker.DotNet;
-using Docker.DotNet.Models;
-using Microsoft.Extensions.VectorData;
-using Microsoft.SemanticKernel.Connectors.PgVector;
-using Npgsql;
-using Xunit;
-
-namespace SemanticKernel.IntegrationTests.Connectors.Memory.PgVector;
-
-public class PostgresVectorStoreFixture : IAsyncLifetime
-{
- /// The docker client we are using to create a postgres container with.
- private readonly DockerClient _client;
-
- /// The id of the postgres container that we are testing with.
- private string? _containerId = null;
-
-#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
-
- ///
- /// Initializes a new instance of the class.
- ///
- public PostgresVectorStoreFixture()
- {
- using var dockerClientConfiguration = new DockerClientConfiguration();
- this._client = dockerClientConfiguration.CreateClient();
- }
-
- ///
- /// Holds the Npgsql data source to use for tests.
- ///
- public NpgsqlDataSource? DataSource { get; private set; }
-
- private string _connectionString = null!;
- private string _databaseName = null!;
-
- ///
- /// Gets a vector store to use for tests.
- ///
- public VectorStore VectorStore => new PostgresVectorStore(this.DataSource!, ownsDataSource: false);
-
- ///
- /// Get a database connection
- ///
- public NpgsqlConnection GetConnection()
- {
- return this.DataSource!.OpenConnection();
- }
-
- public VectorStoreCollection GetCollection(
- string collectionName,
- VectorStoreCollectionDefinition? definition = default)
- where TKey : notnull
- where TRecord : class
- {
- var vectorStore = this.VectorStore;
- return vectorStore.GetCollection(collectionName, definition);
- }
-
- public VectorStoreCollection