diff --git a/dotnet/samples/KernelSyntaxExamples/Example12_SequentialPlanner.cs b/dotnet/samples/KernelSyntaxExamples/Example12_SequentialPlanner.cs index 361450671438..d74748c38b5b 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example12_SequentialPlanner.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example12_SequentialPlanner.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Threading.Tasks; using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Connectors.AI.OpenAI.TextEmbedding; using Microsoft.SemanticKernel.Diagnostics; using Microsoft.SemanticKernel.Memory; using Microsoft.SemanticKernel.Planners; @@ -149,7 +150,7 @@ private static async Task EmailSamplesWithRecallAsync() Console.WriteLine("======== Sequential Planner - Find and Execute Saved Plan ========"); // Save the plan for future use - var semanticMemory = GetMemory(); + var semanticMemory = InitializeMemory(); await semanticMemory.SaveInformationAsync( "plans", id: Guid.NewGuid().ToString(), @@ -228,7 +229,8 @@ private static async Task MemorySampleAsync() { Console.WriteLine("======== Sequential Planner - Create and Execute Plan using Memory ========"); - var kernel = InitializeKernelWithMemory(); + var kernel = InitializeKernel(); + var memory = InitializeMemory(); string folder = RepoFiles.SamplePluginsPath(); kernel.ImportSemanticFunctionsFromDirectory(folder, @@ -251,7 +253,7 @@ private static async Task MemorySampleAsync() var goal = "Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.'"; // IMPORTANT: To use memory and embeddings to find relevant plugins in the planner, set the 'Memory' property on the planner config. - var planner = new SequentialPlanner(kernel, new SequentialPlannerConfig { SemanticMemoryConfig = new() { RelevancyThreshold = 0.5, Memory = kernel.Memory } }); + var planner = new SequentialPlanner(kernel, new SequentialPlannerConfig { SemanticMemoryConfig = new() { RelevancyThreshold = 0.5, Memory = memory } }); var plan = await planner.CreatePlanAsync(goal); @@ -274,7 +276,7 @@ private static IKernel InitializeKernelAndPlanner(out SequentialPlanner planner, return kernel; } - private static IKernel InitializeKernelWithMemory() + private static IKernel InitializeKernel() { // IMPORTANT: Register an embedding generation service and a memory store. The Planner will // use these to generate and store embeddings for the function descriptions. @@ -288,24 +290,22 @@ private static IKernel InitializeKernelWithMemory() TestConfiguration.AzureOpenAIEmbeddings.DeploymentName, TestConfiguration.AzureOpenAIEmbeddings.Endpoint, TestConfiguration.AzureOpenAIEmbeddings.ApiKey) - .WithMemoryStorage(new VolatileMemoryStore()) .Build(); return kernel; } - private static ISemanticTextMemory GetMemory(IKernel? kernel = null) + private static SemanticTextMemory InitializeMemory() { - if (kernel is not null) - { - return kernel.Memory; - } var memoryStorage = new VolatileMemoryStore(); - var textEmbeddingGenerator = new Microsoft.SemanticKernel.Connectors.AI.OpenAI.TextEmbedding.AzureTextEmbeddingGeneration( + + var textEmbeddingGenerator = new AzureTextEmbeddingGeneration( modelId: TestConfiguration.AzureOpenAIEmbeddings.DeploymentName, endpoint: TestConfiguration.AzureOpenAIEmbeddings.Endpoint, apiKey: TestConfiguration.AzureOpenAIEmbeddings.ApiKey); + var memory = new SemanticTextMemory(memoryStorage, textEmbeddingGenerator); + return memory; } diff --git a/dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs b/dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs index c71bac3910c2..e47ab6e5ce19 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Connectors.AI.OpenAI; using Microsoft.SemanticKernel.Connectors.Memory.AzureCognitiveSearch; using Microsoft.SemanticKernel.Memory; using Microsoft.SemanticKernel.Plugins.Memory; @@ -35,13 +36,13 @@ public static async Task RunAsync() * need to worry about embedding generation. */ - var kernelWithACS = Kernel.Builder + var memoryWithACS = new MemoryBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) .WithOpenAITextEmbeddingGenerationService("text-embedding-ada-002", TestConfiguration.OpenAI.ApiKey) - .WithMemoryStorage(new AzureCognitiveSearchMemoryStore(TestConfiguration.ACS.Endpoint, TestConfiguration.ACS.ApiKey)) + .WithMemoryStore(new AzureCognitiveSearchMemoryStore(TestConfiguration.ACS.Endpoint, TestConfiguration.ACS.ApiKey)) .Build(); - await RunExampleAsync(kernelWithACS); + await RunExampleAsync(memoryWithACS); Console.WriteLine("===================================================="); Console.WriteLine("======== Semantic Memory (volatile, in RAM) ========"); @@ -56,20 +57,20 @@ public static async Task RunAsync() * or implement your connectors for Pinecone, Vespa, Postgres + pgvector, SQLite VSS, etc. */ - var kernelWithCustomDb = Kernel.Builder + var memoryWithCustomDb = new MemoryBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) .WithOpenAITextEmbeddingGenerationService("text-embedding-ada-002", TestConfiguration.OpenAI.ApiKey) - .WithMemoryStorage(new VolatileMemoryStore()) + .WithMemoryStore(new VolatileMemoryStore()) .Build(); - await RunExampleAsync(kernelWithCustomDb); + await RunExampleAsync(memoryWithCustomDb); } - public static async Task RunExampleAsync(IKernel kernel) + public static async Task RunExampleAsync(ISemanticTextMemory memory) { - await StoreMemoryAsync(kernel); + await StoreMemoryAsync(memory); - await SearchMemoryAsync(kernel, "How do I get started?"); + await SearchMemoryAsync(memory, "How do I get started?"); /* Output: @@ -86,7 +87,7 @@ public static async Task RunExampleAsync(IKernel kernel) */ - await SearchMemoryAsync(kernel, "Can I build a chat with SK?"); + await SearchMemoryAsync(memory, "Can I build a chat with SK?"); /* Output: @@ -104,26 +105,26 @@ public static async Task RunExampleAsync(IKernel kernel) */ } - private static async Task SearchMemoryAsync(IKernel kernel, string query) + private static async Task SearchMemoryAsync(ISemanticTextMemory memory, string query) { Console.WriteLine("\nQuery: " + query + "\n"); - var memories = kernel.Memory.SearchAsync(MemoryCollectionName, query, limit: 2, minRelevanceScore: 0.5); + var memoryResults = memory.SearchAsync(MemoryCollectionName, query, limit: 2, minRelevanceScore: 0.5); int i = 0; - await foreach (MemoryQueryResult memory in memories) + await foreach (MemoryQueryResult memoryResult in memoryResults) { Console.WriteLine($"Result {++i}:"); - Console.WriteLine(" URL: : " + memory.Metadata.Id); - Console.WriteLine(" Title : " + memory.Metadata.Description); - Console.WriteLine(" Relevance: " + memory.Relevance); + Console.WriteLine(" URL: : " + memoryResult.Metadata.Id); + Console.WriteLine(" Title : " + memoryResult.Metadata.Description); + Console.WriteLine(" Relevance: " + memoryResult.Relevance); Console.WriteLine(); } Console.WriteLine("----------------------"); } - private static async Task StoreMemoryAsync(IKernel kernel) + private static async Task StoreMemoryAsync(ISemanticTextMemory memory) { /* Store some data in the semantic memory. * @@ -138,7 +139,7 @@ private static async Task StoreMemoryAsync(IKernel kernel) var i = 0; foreach (var entry in githubFiles) { - await kernel.Memory.SaveReferenceAsync( + await memory.SaveReferenceAsync( collection: MemoryCollectionName, externalSourceName: "GitHub", externalId: entry.Key, diff --git a/dotnet/samples/KernelSyntaxExamples/Example15_TextMemoryPlugin.cs b/dotnet/samples/KernelSyntaxExamples/Example15_TextMemoryPlugin.cs index fe1858f13f66..8a635e45a226 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example15_TextMemoryPlugin.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example15_TextMemoryPlugin.cs @@ -152,7 +152,7 @@ private static async Task RunWithStoreAsync(IMemoryStore memoryStore, Cancellati // The combination of the text embedding generator and the memory store makes up the 'SemanticTextMemory' object used to // store and retrieve memories. - using SemanticTextMemory textMemory = new(memoryStore, embeddingGenerator); + SemanticTextMemory textMemory = new(memoryStore, embeddingGenerator); ///////////////////////////////////////////////////////////////////////////////////////////////////// // PART 1: Store and retrieve memories using the ISemanticTextMemory (textMemory) object. diff --git a/dotnet/samples/KernelSyntaxExamples/Example31_CustomPlanner.cs b/dotnet/samples/KernelSyntaxExamples/Example31_CustomPlanner.cs index 9a52f1447681..8dd94d078651 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example31_CustomPlanner.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example31_CustomPlanner.cs @@ -7,6 +7,8 @@ using System.Xml; using System.Xml.XPath; using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Connectors.AI.OpenAI; +using Microsoft.SemanticKernel.Memory; using Microsoft.SemanticKernel.Orchestration; using Microsoft.SemanticKernel.Planning; using Microsoft.SemanticKernel.Plugins.Core; @@ -24,16 +26,17 @@ public static async Task RunAsync() { Console.WriteLine("======== Custom Planner - Create and Execute Markup Plan ========"); IKernel kernel = InitializeKernel(); + ISemanticTextMemory memory = InitializeMemory(); // ContextQuery is part of the QAPlugin IDictionary qaPlugin = LoadQAPlugin(kernel); SKContext context = CreateContextQueryContext(kernel); // Create a memory store using the VolatileMemoryStore and the embedding generator registered in the kernel - kernel.ImportFunctions(new TextMemoryPlugin(kernel.Memory)); + kernel.ImportFunctions(new TextMemoryPlugin(memory)); // Setup defined memories for recall - await RememberFactsAsync(kernel); + await RememberFactsAsync(kernel, memory); // MarkupPlugin named "markup" var markup = kernel.ImportFunctions(new MarkupPlugin(), "markup"); @@ -85,9 +88,9 @@ private static SKContext CreateContextQueryContext(IKernel kernel) return context; } - private static async Task RememberFactsAsync(IKernel kernel) + private static async Task RememberFactsAsync(IKernel kernel, ISemanticTextMemory memory) { - kernel.ImportFunctions(new TextMemoryPlugin(kernel.Memory)); + kernel.ImportFunctions(new TextMemoryPlugin(memory)); List memoriesToSave = new() { @@ -105,7 +108,7 @@ private static async Task RememberFactsAsync(IKernel kernel) foreach (var memoryToSave in memoriesToSave) { - await kernel.Memory.SaveInformationAsync("contextQueryMemories", memoryToSave, Guid.NewGuid().ToString()); + await memory.SaveInformationAsync("contextQueryMemories", memoryToSave, Guid.NewGuid().ToString()); } } @@ -136,7 +139,18 @@ private static IKernel InitializeKernel() TestConfiguration.AzureOpenAIEmbeddings.DeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) - .WithMemoryStorage(new VolatileMemoryStore()) + .Build(); + } + + private static ISemanticTextMemory InitializeMemory() + { + return new MemoryBuilder() + .WithLoggerFactory(ConsoleLogger.LoggerFactory) + .WithAzureTextEmbeddingGenerationService( + TestConfiguration.AzureOpenAIEmbeddings.DeploymentName, + TestConfiguration.AzureOpenAI.Endpoint, + TestConfiguration.AzureOpenAI.ApiKey) + .WithMemoryStore(new VolatileMemoryStore()) .Build(); } } diff --git a/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs b/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs index bd6ff0dd5952..f90c1ad6d9e7 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs @@ -78,7 +78,8 @@ public static Task RunAsync() endpoint: azureOpenAIEndpoint, apiKey: azureOpenAIKey, loggerFactory: loggerFactory); - using var memory = new SemanticTextMemory(memoryStorage, textEmbeddingGenerator); + + var memory = new SemanticTextMemory(memoryStorage, textEmbeddingGenerator); var plugins = new FunctionCollection(); var templateEngine = new BasicPromptTemplateEngine(loggerFactory); @@ -104,30 +105,6 @@ public static Task RunAsync() // The kernel builder purpose is to simplify this process, automating how dependencies // are connected, still allowing to customize parts of the composition. - // Example: how to use a custom memory and configure Azure OpenAI - var kernel4 = Kernel.Builder - .WithLoggerFactory(NullLoggerFactory.Instance) - .WithMemory(memory) - .WithAzureChatCompletionService( - deploymentName: azureOpenAIChatCompletionDeployment, - endpoint: azureOpenAIEndpoint, - apiKey: azureOpenAIKey) - .Build(); - - // Example: how to use a custom memory storage - var kernel6 = Kernel.Builder - .WithLoggerFactory(NullLoggerFactory.Instance) - .WithMemoryStorage(memoryStorage) // Custom memory storage - .WithAzureChatCompletionService( - deploymentName: azureOpenAIChatCompletionDeployment, - endpoint: azureOpenAIEndpoint, - apiKey: azureOpenAIKey) // This will be used when using AI completions - .WithAzureTextEmbeddingGenerationService( - deploymentName: azureOpenAIEmbeddingDeployment, - endpoint: azureOpenAIEndpoint, - apiKey: azureOpenAIKey) // This will be used when indexing memory records - .Build(); - // ========================================================================================================== // The AI services are defined with the builder diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/Connectors.AI.OpenAI.csproj b/dotnet/src/Connectors/Connectors.AI.OpenAI/Connectors.AI.OpenAI.csproj index c3d6d7c82ff1..bbf1fd8fc532 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/Connectors.AI.OpenAI.csproj +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/Connectors.AI.OpenAI.csproj @@ -20,6 +20,7 @@ + diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIMemoryBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIMemoryBuilderExtensions.cs new file mode 100644 index 000000000000..4d351c5d774a --- /dev/null +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIMemoryBuilderExtensions.cs @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Net.Http; +using Azure.Core; +using Microsoft.SemanticKernel.Connectors.AI.OpenAI.TextEmbedding; +using Microsoft.SemanticKernel.Plugins.Memory; + +namespace Microsoft.SemanticKernel.Connectors.AI.OpenAI; + +/// +/// Provides extension methods for the class to configure OpenAI and AzureOpenAI connectors. +/// +public static class OpenAIMemoryBuilderExtensions +{ + /// + /// Adds an Azure OpenAI text embeddings service. + /// See https://learn.microsoft.com/azure/cognitive-services/openai for service details. + /// + /// The instance + /// Azure OpenAI deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource + /// Azure OpenAI deployment URL, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart + /// Azure OpenAI API key, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart + /// A local identifier for the given AI service + /// Whether the service should be the default for its type. + /// Custom for HTTP requests. + /// Self instance + public static MemoryBuilder WithAzureTextEmbeddingGenerationService( + this MemoryBuilder builder, + string deploymentName, + string endpoint, + string apiKey, + string? serviceId = null, + bool setAsDefault = false, + HttpClient? httpClient = null) + { + builder.WithTextEmbeddingGeneration((loggerFactory, httpHandlerFactory) => + new AzureTextEmbeddingGeneration( + deploymentName, + endpoint, + apiKey, + HttpClientProvider.GetHttpClient(httpHandlerFactory, httpClient, loggerFactory), + loggerFactory)); + + return builder; + } + + /// + /// Adds an Azure OpenAI text embeddings service. + /// See https://learn.microsoft.com/azure/cognitive-services/openai for service details. + /// + /// The instance + /// Azure OpenAI deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource + /// Azure OpenAI deployment URL, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart + /// Token credentials, e.g. DefaultAzureCredential, ManagedIdentityCredential, EnvironmentCredential, etc. + /// A local identifier for the given AI service + /// Whether the service should be the default for its type. + /// Custom for HTTP requests. + /// Self instance + public static MemoryBuilder WithAzureTextEmbeddingGenerationService( + this MemoryBuilder builder, + string deploymentName, + string endpoint, + TokenCredential credential, + string? serviceId = null, + bool setAsDefault = false, + HttpClient? httpClient = null) + { + builder.WithTextEmbeddingGeneration((loggerFactory, httpHandlerFactory) => + new AzureTextEmbeddingGeneration( + deploymentName, + endpoint, + credential, + HttpClientProvider.GetHttpClient(httpHandlerFactory, httpClient, loggerFactory), + loggerFactory)); + + return builder; + } + + /// + /// Adds the OpenAI text embeddings service. + /// See https://platform.openai.com/docs for service details. + /// + /// The instance + /// OpenAI model name, see https://platform.openai.com/docs/models + /// OpenAI API key, see https://platform.openai.com/account/api-keys + /// OpenAI organization id. This is usually optional unless your account belongs to multiple organizations. + /// A local identifier for the given AI service + /// Whether the service should be the default for its type. + /// Custom for HTTP requests. + /// Self instance + public static MemoryBuilder WithOpenAITextEmbeddingGenerationService( + this MemoryBuilder builder, + string modelId, + string apiKey, + string? orgId = null, + string? serviceId = null, + bool setAsDefault = false, + HttpClient? httpClient = null) + { + builder.WithTextEmbeddingGeneration((loggerFactory, httpHandlerFactory) => + new OpenAITextEmbeddingGeneration( + modelId, + apiKey, + orgId, + HttpClientProvider.GetHttpClient(httpHandlerFactory, httpClient, loggerFactory), + loggerFactory)); + + return builder; + } +} diff --git a/dotnet/src/Connectors/Connectors.Memory.Chroma/ChromaKernelBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Chroma/ChromaKernelBuilderExtensions.cs index 723613d39543..8366997c1ca0 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Chroma/ChromaKernelBuilderExtensions.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Chroma/ChromaKernelBuilderExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.ComponentModel; using System.Net.Http; using Microsoft.SemanticKernel.Connectors.Memory.Chroma; @@ -10,6 +12,8 @@ namespace Microsoft.SemanticKernel; /// /// Provides extension methods for the class to configure Chroma memory connector. /// +[Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use ChromaMemoryBuilderExtensions instead.")] +[EditorBrowsable(EditorBrowsableState.Never)] public static class ChromaKernelBuilderExtensions { /// @@ -18,6 +22,8 @@ public static class ChromaKernelBuilderExtensions /// The instance. /// Chroma server endpoint URL. /// Self instance. + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use ChromaMemoryBuilderExtensions.WithChromaMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithChromaMemoryStore(this KernelBuilder builder, string endpoint) { builder.WithMemoryStorage((loggerFactory, httpHandlerFactory) => @@ -38,6 +44,8 @@ public static KernelBuilder WithChromaMemoryStore(this KernelBuilder builder, st /// The instance used for making HTTP requests. /// Chroma server endpoint URL. If not specified, the base address of the HTTP client is used. /// Self instance. + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use ChromaMemoryBuilderExtensions.WithChromaMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithChromaMemoryStore(this KernelBuilder builder, HttpClient httpClient, string? endpoint = null) diff --git a/dotnet/src/Connectors/Connectors.Memory.Chroma/ChromaMemoryBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Chroma/ChromaMemoryBuilderExtensions.cs new file mode 100644 index 000000000000..cbe98e0a6748 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.Chroma/ChromaMemoryBuilderExtensions.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Net.Http; +using Microsoft.SemanticKernel.Plugins.Memory; + +namespace Microsoft.SemanticKernel.Connectors.Memory.Chroma; + +/// +/// Provides extension methods for the class to configure Chroma memory connector. +/// +public static class ChromaMemoryBuilderExtensions +{ + /// + /// Registers Chroma memory connector. + /// + /// The instance. + /// Chroma server endpoint URL. + /// Updated Memory builder including Chroma memory connector. + public static MemoryBuilder WithChromaMemoryStore(this MemoryBuilder builder, string endpoint) + { + builder.WithMemoryStore((loggerFactory, httpHandlerFactory) => + { + return new ChromaMemoryStore( + HttpClientProvider.GetHttpClient(httpHandlerFactory, null, loggerFactory), + endpoint, + loggerFactory); + }); + + return builder; + } + + /// + /// Registers Chroma memory connector. + /// + /// The instance. + /// The instance used for making HTTP requests. + /// Chroma server endpoint URL. If not specified, the base address of the HTTP client is used. + /// Updated Memory builder including Chroma memory connector. + public static MemoryBuilder WithChromaMemoryStore( + this MemoryBuilder builder, + HttpClient httpClient, + string? endpoint = null) + { + builder.WithMemoryStore((loggerFactory, httpHandlerFactory) => + { + return new ChromaMemoryStore( + HttpClientProvider.GetHttpClient(httpHandlerFactory, httpClient, loggerFactory), + endpoint, + loggerFactory); + }); + + return builder; + } +} diff --git a/dotnet/src/Connectors/Connectors.Memory.Chroma/Connectors.Memory.Chroma.csproj b/dotnet/src/Connectors/Connectors.Memory.Chroma/Connectors.Memory.Chroma.csproj index 5b1f72a6b197..4af82ec792a7 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Chroma/Connectors.Memory.Chroma.csproj +++ b/dotnet/src/Connectors/Connectors.Memory.Chroma/Connectors.Memory.Chroma.csproj @@ -22,6 +22,7 @@ + diff --git a/dotnet/src/Connectors/Connectors.Memory.Pinecone/Connectors.Memory.Pinecone.csproj b/dotnet/src/Connectors/Connectors.Memory.Pinecone/Connectors.Memory.Pinecone.csproj index e2bfc591f91f..da502d5cae4f 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Pinecone/Connectors.Memory.Pinecone.csproj +++ b/dotnet/src/Connectors/Connectors.Memory.Pinecone/Connectors.Memory.Pinecone.csproj @@ -22,6 +22,7 @@ + diff --git a/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeKernelBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeKernelBuilderExtensions.cs index 55adfdd197f0..2db0698f73d4 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeKernelBuilderExtensions.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeKernelBuilderExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.ComponentModel; using System.Net.Http; using Microsoft.SemanticKernel.Connectors.Memory.Pinecone; @@ -10,6 +12,8 @@ namespace Microsoft.SemanticKernel; /// /// Provides extension methods for the class to configure Pinecone connectors. /// +[Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use PineconeMemoryBuilderExtensions instead.")] +[EditorBrowsable(EditorBrowsableState.Never)] public static class PineconeKernelBuilderExtensions { /// @@ -20,6 +24,8 @@ public static class PineconeKernelBuilderExtensions /// The API key for accessing Pinecone services. /// An optional HttpClient instance for making HTTP requests. /// Self instance + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use PineconeMemoryBuilderExtensions.WithPineconeMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithPineconeMemoryStore(this KernelBuilder builder, string environment, string apiKey, diff --git a/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeMemoryBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeMemoryBuilderExtensions.cs new file mode 100644 index 000000000000..984fd97e42db --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.Pinecone/PineconeMemoryBuilderExtensions.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Net.Http; +using Microsoft.SemanticKernel.Plugins.Memory; + +namespace Microsoft.SemanticKernel.Connectors.Memory.Pinecone; + +/// +/// Provides extension methods for the class to configure Pinecone connector. +/// +public static class PineconeMemoryBuilderExtensions +{ + /// + /// Registers Pinecone memory connector. + /// + /// The instance. + /// The environment for Pinecone. + /// The API key for accessing Pinecone services. + /// An optional HttpClient instance for making HTTP requests. + /// Updated Memory builder including Pinecone memory connector. + public static MemoryBuilder WithPineconeMemoryStore( + this MemoryBuilder builder, + string environment, + string apiKey, + HttpClient? httpClient = null) + { + builder.WithMemoryStore((loggerFactory, httpHandlerFactory) => + { + var client = new PineconeClient( + environment, + apiKey, + loggerFactory, + HttpClientProvider.GetHttpClient(httpHandlerFactory, httpClient, loggerFactory)); + + return new PineconeMemoryStore(client, loggerFactory); + }); + + return builder; + } +} diff --git a/dotnet/src/Connectors/Connectors.Memory.Postgres/Connectors.Memory.Postgres.csproj b/dotnet/src/Connectors/Connectors.Memory.Postgres/Connectors.Memory.Postgres.csproj index 77b9b68e0982..b8ce22772d9c 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Postgres/Connectors.Memory.Postgres.csproj +++ b/dotnet/src/Connectors/Connectors.Memory.Postgres/Connectors.Memory.Postgres.csproj @@ -26,6 +26,7 @@ + diff --git a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresKernelBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresKernelBuilderExtensions.cs index d059448cf6ac..5bbe95e28189 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresKernelBuilderExtensions.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresKernelBuilderExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.ComponentModel; using Microsoft.SemanticKernel.Connectors.Memory.Postgres; using Npgsql; @@ -10,6 +12,8 @@ namespace Microsoft.SemanticKernel; /// /// Provides extension methods for the class to configure Postgres connectors. /// +[Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use PostgresMemoryBuilderExtensions instead.")] +[EditorBrowsable(EditorBrowsableState.Never)] public static class PostgresKernelBuilderExtensions { /// @@ -20,6 +24,8 @@ public static class PostgresKernelBuilderExtensions /// Embedding vector size. /// Schema of collection tables. /// Self instance + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use PostgresMemoryBuilderExtensions.WithPostgresMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithPostgresMemoryStore(this KernelBuilder builder, string connectionString, int vectorSize, @@ -41,6 +47,8 @@ public static KernelBuilder WithPostgresMemoryStore(this KernelBuilder builder, /// Embedding vector size. /// Schema of collection tables. /// Self instance + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use PostgresMemoryBuilderExtensions.WithPostgresMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithPostgresMemoryStore(this KernelBuilder builder, NpgsqlDataSource dataSource, int vectorSize, @@ -60,6 +68,8 @@ public static KernelBuilder WithPostgresMemoryStore(this KernelBuilder builder, /// The instance /// Postgres database client. /// Self instance + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use PostgresMemoryBuilderExtensions.WithPostgresMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithPostgresMemoryStore(this KernelBuilder builder, IPostgresDbClient postgresDbClient) { builder.WithMemoryStorage((loggerFactory) => diff --git a/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresMemoryBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresMemoryBuilderExtensions.cs new file mode 100644 index 000000000000..7037c3c74d6b --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresMemoryBuilderExtensions.cs @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel.Plugins.Memory; +using Npgsql; + +namespace Microsoft.SemanticKernel.Connectors.Memory.Postgres; + +/// +/// Provides extension methods for the class to configure Postgres connector. +/// +public static class PostgresMemoryBuilderExtensions +{ + /// + /// Registers Postgres memory connector. + /// + /// The instance. + /// Postgres database connection string. + /// Embedding vector size. + /// Schema of collection tables. + /// Updated Memory builder including Postgres memory connector. + public static MemoryBuilder WithPostgresMemoryStore( + this MemoryBuilder builder, + string connectionString, + int vectorSize, + string schema = PostgresMemoryStore.DefaultSchema) + { + builder.WithMemoryStore((_) => + { + return new PostgresMemoryStore(connectionString, vectorSize, schema); + }); + + return builder; + } + + /// + /// Registers Postgres memory connector. + /// + /// The instance. + /// Postgres data source. + /// Embedding vector size. + /// Schema of collection tables. + /// Updated Memory builder including Postgres memory connector. + public static MemoryBuilder WithPostgresMemoryStore( + this MemoryBuilder builder, + NpgsqlDataSource dataSource, + int vectorSize, + string schema = PostgresMemoryStore.DefaultSchema) + { + builder.WithMemoryStore((_) => + { + return new PostgresMemoryStore(dataSource, vectorSize, schema); + }); + + return builder; + } + + /// + /// Registers Postgres memory connector. + /// + /// The instance. + /// Postgres database client. + /// Updated Memory builder including Postgres memory connector. + public static MemoryBuilder WithPostgresMemoryStore( + this MemoryBuilder builder, + IPostgresDbClient postgresDbClient) + { + builder.WithMemoryStore((_) => + { + return new PostgresMemoryStore(postgresDbClient); + }); + + return builder; + } +} diff --git a/dotnet/src/Connectors/Connectors.Memory.Qdrant/Connectors.Memory.Qdrant.csproj b/dotnet/src/Connectors/Connectors.Memory.Qdrant/Connectors.Memory.Qdrant.csproj index 3ff3581c25ce..361115c0f621 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Qdrant/Connectors.Memory.Qdrant.csproj +++ b/dotnet/src/Connectors/Connectors.Memory.Qdrant/Connectors.Memory.Qdrant.csproj @@ -22,6 +22,7 @@ + diff --git a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantKernelBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantKernelBuilderExtensions.cs index 32205c050374..0ed45e671fbb 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantKernelBuilderExtensions.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantKernelBuilderExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.ComponentModel; using System.Net.Http; using Microsoft.SemanticKernel.Connectors.Memory.Qdrant; @@ -10,6 +12,8 @@ namespace Microsoft.SemanticKernel; /// /// Provides extension methods for the class to configure Qdrant memory connector. /// +[Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use QdrantMemoryBuilderExtensions instead.")] +[EditorBrowsable(EditorBrowsableState.Never)] public static class QdrantKernelBuilderExtensions { /// @@ -19,6 +23,8 @@ public static class QdrantKernelBuilderExtensions /// The Qdrant Vector Database endpoint. /// The size of the vectors. /// Self instance + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use QdrantMemoryBuilderExtensions.WithQdrantMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithQdrantMemoryStore(this KernelBuilder builder, string endpoint, int vectorSize) @@ -45,6 +51,8 @@ public static KernelBuilder WithQdrantMemoryStore(this KernelBuilder builder, /// The size of the vectors. /// The Qdrant Vector Database endpoint. If not specified, the base address of the HTTP client is used. /// Self instance + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use QdrantMemoryBuilderExtensions.WithQdrantMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithQdrantMemoryStore(this KernelBuilder builder, HttpClient httpClient, int vectorSize, diff --git a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantMemoryBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantMemoryBuilderExtensions.cs new file mode 100644 index 000000000000..8f18fbe4f850 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantMemoryBuilderExtensions.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Net.Http; +using Microsoft.SemanticKernel.Plugins.Memory; + +namespace Microsoft.SemanticKernel.Connectors.Memory.Qdrant; + +/// +/// Provides extension methods for the class to configure Qdrant connector. +/// +public static class QdrantMemoryBuilderExtensions +{ + /// + /// Registers Qdrant memory connector. + /// + /// The instance. + /// The Qdrant Vector Database endpoint. + /// The size of the vectors. + /// Updated Memory builder including Qdrant memory connector. + public static MemoryBuilder WithQdrantMemoryStore( + this MemoryBuilder builder, + string endpoint, + int vectorSize) + { + builder.WithMemoryStore((loggerFactory, httpHandlerFactory) => + { + var client = new QdrantVectorDbClient( + HttpClientProvider.GetHttpClient(httpHandlerFactory, null, loggerFactory), + vectorSize, + endpoint, + loggerFactory); + + return new QdrantMemoryStore(client, loggerFactory); + }); + + return builder; + } + + /// + /// Registers Qdrant memory connector. + /// + /// The instance. + /// The optional instance used for making HTTP requests. + /// The size of the vectors. + /// The Qdrant Vector Database endpoint. If not specified, the base address of the HTTP client is used. + /// Updated Memory builder including Qdrant memory connector. + public static MemoryBuilder WithQdrantMemoryStore( + this MemoryBuilder builder, + HttpClient httpClient, + int vectorSize, + string? endpoint = null) + { + builder.WithMemoryStore((loggerFactory, httpHandlerFactory) => + { + var client = new QdrantVectorDbClient( + HttpClientProvider.GetHttpClient(httpHandlerFactory, httpClient, loggerFactory), + vectorSize, + endpoint, + loggerFactory); + + return new QdrantMemoryStore(client, loggerFactory); + }); + + return builder; + } +} diff --git a/dotnet/src/Connectors/Connectors.Memory.Weaviate/Connectors.Memory.Weaviate.csproj b/dotnet/src/Connectors/Connectors.Memory.Weaviate/Connectors.Memory.Weaviate.csproj index 7b69467f4b62..b142a7b5ba2c 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Weaviate/Connectors.Memory.Weaviate.csproj +++ b/dotnet/src/Connectors/Connectors.Memory.Weaviate/Connectors.Memory.Weaviate.csproj @@ -22,6 +22,7 @@ + diff --git a/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateKernelBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateKernelBuilderExtensions.cs index 7f56539fde7c..e11047eb2288 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateKernelBuilderExtensions.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateKernelBuilderExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.ComponentModel; using System.Net.Http; using Microsoft.SemanticKernel.Connectors.Memory.Weaviate; @@ -10,6 +12,8 @@ namespace Microsoft.SemanticKernel; /// /// Provides extension methods for the class to configure Weaviate memory connector. /// +[Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use WeaviateMemoryBuilderExtensions instead.")] +[EditorBrowsable(EditorBrowsableState.Never)] public static class WeaviateKernelBuilderExtensions { /// @@ -20,6 +24,8 @@ public static class WeaviateKernelBuilderExtensions /// The API key for accessing Weaviate server. /// The API version to use. /// Self instance + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use WeaviateMemoryBuilderExtensions.WithWeaviateMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithWeaviateMemoryStore( this KernelBuilder builder, string endpoint, @@ -48,6 +54,8 @@ public static KernelBuilder WithWeaviateMemoryStore( /// The API key for accessing Weaviate server. /// The API version to use. /// Self instance + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. Use WeaviateMemoryBuilderExtensions.WithWeaviateMemoryStore instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static KernelBuilder WithWeaviateMemoryStore(this KernelBuilder builder, HttpClient httpClient, string? endpoint = null, diff --git a/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateMemoryBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateMemoryBuilderExtensions.cs new file mode 100644 index 000000000000..b1dbd2686707 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.Memory.Weaviate/WeaviateMemoryBuilderExtensions.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Net.Http; +using Microsoft.SemanticKernel.Plugins.Memory; + +namespace Microsoft.SemanticKernel.Connectors.Memory.Weaviate; + +/// +/// Provides extension methods for the class to configure Weaviate connector. +/// +public static class WeaviateMemoryBuilderExtensions +{ + /// + /// Registers Weaviate memory connector. + /// + /// The instance. + /// The Weaviate server endpoint URL. + /// The API key for accessing Weaviate server. + /// The API version to use. + /// Updated Memory builder including Weaviate memory connector. + public static MemoryBuilder WithWeaviateMemoryStore( + this MemoryBuilder builder, + string endpoint, + string? apiKey, + string? apiVersion = null) + { + builder.WithMemoryStore((loggerFactory, httpHandlerFactory) => + { + return new WeaviateMemoryStore( + HttpClientProvider.GetHttpClient(httpHandlerFactory, null, loggerFactory), + apiKey, + endpoint, + apiVersion, + loggerFactory); + }); + + return builder; + } + + /// + /// Registers Weaviate memory connector. + /// + /// The instance. + /// The optional instance used for making HTTP requests. + /// The Weaviate server endpoint URL. If not specified, the base address of the HTTP client is used. + /// The API key for accessing Weaviate server. + /// The API version to use. + /// Updated Memory builder including Weaviate memory connector. + public static MemoryBuilder WithWeaviateMemoryStore( + this MemoryBuilder builder, + HttpClient httpClient, + string? endpoint = null, + string? apiKey = null, + string? apiVersion = null) + { + builder.WithMemoryStore((loggerFactory, httpHandlerFactory) => + { + return new WeaviateMemoryStore( + HttpClientProvider.GetHttpClient(httpHandlerFactory, httpClient, loggerFactory), + apiKey, + endpoint, + apiVersion, + loggerFactory); + }); + + return builder; + } +} diff --git a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeKernelBuilderExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeKernelBuilderExtensionsTests.cs index aec5b254225a..4a624fb4ca13 100644 --- a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeKernelBuilderExtensionsTests.cs +++ b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeKernelBuilderExtensionsTests.cs @@ -30,12 +30,16 @@ public async Task PineconeMemoryStoreShouldBeProperlyInitializedAsync() this._messageHandlerStub.ResponseToReturn.Content = new StringContent("[\"fake-index1\"]", Encoding.UTF8, MediaTypeNames.Application.Json); var builder = new KernelBuilder(); +#pragma warning disable CS0618 // This will be removed in a future release. builder.WithPineconeMemoryStore("fake-environment", "fake-api-key", this._httpClient); +#pragma warning restore CS0618 // This will be removed in a future release. builder.WithAzureTextEmbeddingGenerationService("fake-deployment-name", "https://fake-random-test-host/fake-path", "fake -api-key"); var kernel = builder.Build(); //This call triggers the internal factory registered by WithPineconeMemoryStore method to create an instance of the PineconeMemoryStore class. //Act +#pragma warning disable CS0618 // This will be removed in a future release. await kernel.Memory.GetCollectionsAsync(); //This call triggers a subsequent call to Pinecone memory store. +#pragma warning restore CS0618 // This will be removed in a future release. //Assert Assert.Equal("https://controller.fake-environment.pinecone.io/databases", this._messageHandlerStub?.RequestUri?.AbsoluteUri); diff --git a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeMemoryBuilderExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeMemoryBuilderExtensionsTests.cs new file mode 100644 index 000000000000..abfc4e85f6d1 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeMemoryBuilderExtensionsTests.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Linq; +using System.Net.Http; +using System.Net.Mime; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.AI.Embeddings; +using Microsoft.SemanticKernel.Connectors.Memory.Pinecone; +using Microsoft.SemanticKernel.Plugins.Memory; +using Moq; +using Xunit; + +namespace SemanticKernel.Connectors.UnitTests.Memory.Pinecone; + +public sealed class PineconeMemoryBuilderExtensionsTests : IDisposable +{ + private readonly HttpMessageHandlerStub _messageHandlerStub; + private readonly HttpClient _httpClient; + + public PineconeMemoryBuilderExtensionsTests() + { + this._messageHandlerStub = new HttpMessageHandlerStub(); + + this._httpClient = new HttpClient(this._messageHandlerStub, false); + } + + [Fact] + public async Task PineconeMemoryStoreShouldBeProperlyInitializedAsync() + { + // Arrange + var embeddingGenerationMock = Mock.Of(); + this._messageHandlerStub.ResponseToReturn.Content = new StringContent("[\"fake-index1\"]", Encoding.UTF8, MediaTypeNames.Application.Json); + + var builder = new MemoryBuilder(); + builder.WithPineconeMemoryStore("fake-environment", "fake-api-key", this._httpClient); + builder.WithTextEmbeddingGeneration(embeddingGenerationMock); + + var memory = builder.Build(); //This call triggers the internal factory registered by WithPineconeMemoryStore method to create an instance of the PineconeMemoryStore class. + + // Act + await memory.GetCollectionsAsync(); //This call triggers a subsequent call to Pinecone memory store. + + // Assert + Assert.Equal("https://controller.fake-environment.pinecone.io/databases", this._messageHandlerStub?.RequestUri?.AbsoluteUri); + + var headerValues = Enumerable.Empty(); + var headerExists = this._messageHandlerStub?.RequestHeaders?.TryGetValues("Api-Key", out headerValues); + Assert.True(headerExists); + Assert.Contains(headerValues!, (value) => value == "fake-api-key"); + } + + public void Dispose() + { + this._httpClient.Dispose(); + this._messageHandlerStub.Dispose(); + } +} diff --git a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantKernelBuilderExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantKernelBuilderExtensionsTests.cs index 42571d457ead..e7d1052faadb 100644 --- a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantKernelBuilderExtensionsTests.cs +++ b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantKernelBuilderExtensionsTests.cs @@ -30,12 +30,16 @@ public async Task QdrantMemoryStoreShouldBeProperlyInitializedAsync() this._messageHandlerStub.ResponseToReturn.Content = new StringContent("{\"result\":{\"collections\":[]}}", Encoding.UTF8, MediaTypeNames.Application.Json); var builder = new KernelBuilder(); +#pragma warning disable CS0618 // This will be removed in a future release. builder.WithQdrantMemoryStore(this._httpClient, 123); +#pragma warning restore CS0618 // This will be removed in a future release. builder.WithAzureTextEmbeddingGenerationService("fake-deployment-name", "https://fake-random-text-embedding-generation-host/fake-path", "fake-api-key"); var kernel = builder.Build(); //This call triggers the internal factory registered by WithQdrantMemoryStore method to create an instance of the QdrantMemoryStore class. //Act +#pragma warning disable CS0618 // This will be removed in a future release. await kernel.Memory.GetCollectionsAsync(); //This call triggers a subsequent call to Qdrant memory store. +#pragma warning restore CS0618 // This will be removed in a future release. //Assert Assert.Equal("https://fake-random-qdrant-host/collections", this._messageHandlerStub?.RequestUri?.AbsoluteUri); diff --git a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantMemoryBuilderExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantMemoryBuilderExtensionsTests.cs new file mode 100644 index 000000000000..37ed036b54f6 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantMemoryBuilderExtensionsTests.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Net.Http; +using System.Net.Mime; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.AI.Embeddings; +using Microsoft.SemanticKernel.Connectors.Memory.Qdrant; +using Microsoft.SemanticKernel.Plugins.Memory; +using Moq; +using Xunit; + +namespace SemanticKernel.Connectors.UnitTests.Memory.Qdrant; + +public sealed class QdrantMemoryBuilderExtensionsTests : IDisposable +{ + private readonly HttpMessageHandlerStub _messageHandlerStub; + private readonly HttpClient _httpClient; + + public QdrantMemoryBuilderExtensionsTests() + { + this._messageHandlerStub = new HttpMessageHandlerStub(); + + this._httpClient = new HttpClient(this._messageHandlerStub, false); + } + + [Fact] + public async Task QdrantMemoryStoreShouldBeProperlyInitializedAsync() + { + // Arrange + var embeddingGenerationMock = Mock.Of(); + + this._httpClient.BaseAddress = new Uri("https://fake-random-qdrant-host"); + this._messageHandlerStub.ResponseToReturn.Content = new StringContent("{\"result\":{\"collections\":[]}}", Encoding.UTF8, MediaTypeNames.Application.Json); + + var builder = new MemoryBuilder(); + builder.WithQdrantMemoryStore(this._httpClient, 123); + builder.WithTextEmbeddingGeneration(embeddingGenerationMock); + var memory = builder.Build(); //This call triggers the internal factory registered by WithQdrantMemoryStore method to create an instance of the QdrantMemoryStore class. + + // Act + await memory.GetCollectionsAsync(); //This call triggers a subsequent call to Qdrant memory store. + + // Assert + Assert.Equal("https://fake-random-qdrant-host/collections", this._messageHandlerStub?.RequestUri?.AbsoluteUri); + } + + public void Dispose() + { + this._httpClient.Dispose(); + this._messageHandlerStub.Dispose(); + } +} diff --git a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateKernelBuilderExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateKernelBuilderExtensionsTests.cs index b77d66f13ebe..0d771ef95194 100644 --- a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateKernelBuilderExtensionsTests.cs +++ b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateKernelBuilderExtensionsTests.cs @@ -44,12 +44,16 @@ public async Task WeaviateMemoryStoreShouldBeProperlyInitializedAsync(string? ap this._messageHandlerStub.ResponseToReturn.Content = new StringContent(JsonSerializer.Serialize(getResponse, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }), Encoding.UTF8, MediaTypeNames.Application.Json); var builder = new KernelBuilder(); +#pragma warning disable CS0618 // This will be removed in a future release. builder.WithWeaviateMemoryStore(this._httpClient, "https://fake-random-test-weaviate-host", "fake-api-key", apiVersion); +#pragma warning restore CS0618 // This will be removed in a future release. builder.WithAzureTextEmbeddingGenerationService("fake-deployment-name", "https://fake-random-test-host/fake-path", "fake -api-key"); var kernel = builder.Build(); //This call triggers the internal factory registered by WithWeaviateMemoryStore method to create an instance of the WeaviateMemoryStore class. //Act +#pragma warning disable CS0618 // This will be removed in a future release. await kernel.Memory.GetAsync("fake-collection", "fake-key"); //This call triggers a subsequent call to Weaviate memory store. +#pragma warning restore CS0618 // This will be removed in a future release. //Assert Assert.Equal(expectedAddress, this._messageHandlerStub?.RequestUri?.AbsoluteUri); diff --git a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateMemoryBuilderExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateMemoryBuilderExtensionsTests.cs new file mode 100644 index 000000000000..d9e90cbeba42 --- /dev/null +++ b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateMemoryBuilderExtensionsTests.cs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Mime; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.AI.Embeddings; +using Microsoft.SemanticKernel.Connectors.Memory.Weaviate; +using Microsoft.SemanticKernel.Plugins.Memory; +using Moq; +using Xunit; + +namespace SemanticKernel.Connectors.UnitTests.Memory.Weaviate; + +public sealed class WeaviateMemoryBuilderExtensionsTests : IDisposable +{ + private readonly HttpMessageHandlerStub _messageHandlerStub; + private readonly HttpClient _httpClient; + + public WeaviateMemoryBuilderExtensionsTests() + { + this._messageHandlerStub = new HttpMessageHandlerStub(); + + this._httpClient = new HttpClient(this._messageHandlerStub, false); + } + + [Theory] + [InlineData(null, "https://fake-random-test-weaviate-host/v1/objects/fake-key")] + [InlineData("v2", "https://fake-random-test-weaviate-host/v2/objects/fake-key")] + public async Task WeaviateMemoryStoreShouldBeProperlyInitializedAsync(string? apiVersion, string expectedAddress) + { + // Arrange + var embeddingGenerationMock = Mock.Of(); + + var getResponse = new + { + Properties = new Dictionary { + { "sk_id", "fake_id" }, + { "sk_description", "fake_description" }, + { "sk_text", "fake_text" }, + { "sk_additional_metadata", "fake_additional_metadata" } + } + }; + + this._messageHandlerStub.ResponseToReturn.Content = new StringContent(JsonSerializer.Serialize(getResponse, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }), Encoding.UTF8, MediaTypeNames.Application.Json); + + var builder = new MemoryBuilder(); + builder.WithWeaviateMemoryStore(this._httpClient, "https://fake-random-test-weaviate-host", "fake-api-key", apiVersion); + builder.WithTextEmbeddingGeneration(embeddingGenerationMock); + + var memory = builder.Build(); //This call triggers the internal factory registered by WithWeaviateMemoryStore method to create an instance of the WeaviateMemoryStore class. + + // Act + await memory.GetAsync("fake-collection", "fake-key"); //This call triggers a subsequent call to Weaviate memory store. + + // Assert + Assert.Equal(expectedAddress, this._messageHandlerStub?.RequestUri?.AbsoluteUri); + + var headerValues = Enumerable.Empty(); + var headerExists = this._messageHandlerStub?.RequestHeaders?.TryGetValues("Authorization", out headerValues); + Assert.True(headerExists); + Assert.Contains(headerValues!, (value) => value == "fake-api-key"); + } + + public void Dispose() + { + this._httpClient.Dispose(); + this._messageHandlerStub.Dispose(); + } +} diff --git a/dotnet/src/IntegrationTests/Planners/PlanTests.cs b/dotnet/src/IntegrationTests/Planners/PlanTests.cs index 88b868fa257d..8ca1c786c44e 100644 --- a/dotnet/src/IntegrationTests/Planners/PlanTests.cs +++ b/dotnet/src/IntegrationTests/Planners/PlanTests.cs @@ -9,7 +9,6 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Orchestration; using Microsoft.SemanticKernel.Planning; -using Microsoft.SemanticKernel.Plugins.Memory; using SemanticKernel.IntegrationTests.Fakes; using SemanticKernel.IntegrationTests.TestSettings; using Xunit; @@ -531,8 +530,7 @@ private IKernel InitializeKernel(bool useEmbeddings = false, bool useChatModel = .WithAzureTextEmbeddingGenerationService( deploymentName: azureOpenAIEmbeddingsConfiguration.DeploymentName, endpoint: azureOpenAIEmbeddingsConfiguration.Endpoint, - apiKey: azureOpenAIEmbeddingsConfiguration.ApiKey) - .WithMemoryStorage(new VolatileMemoryStore()); + apiKey: azureOpenAIEmbeddingsConfiguration.ApiKey); } var kernel = builder.Build(); diff --git a/dotnet/src/IntegrationTests/Planners/SequentialPlanner/SequentialPlannerTests.cs b/dotnet/src/IntegrationTests/Planners/SequentialPlanner/SequentialPlannerTests.cs index bb1086559cca..a9e4e2ac6516 100644 --- a/dotnet/src/IntegrationTests/Planners/SequentialPlanner/SequentialPlannerTests.cs +++ b/dotnet/src/IntegrationTests/Planners/SequentialPlanner/SequentialPlannerTests.cs @@ -6,6 +6,8 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.AI.Embeddings; +using Microsoft.SemanticKernel.Memory; using Microsoft.SemanticKernel.Planners; using Microsoft.SemanticKernel.Plugins.Memory; using SemanticKernel.IntegrationTests.Fakes; @@ -84,14 +86,17 @@ public async Task CreatePlanGoalRelevantAsync(string prompt, string expectedFunc { // Arrange bool useEmbeddings = true; + IKernel kernel = this.InitializeKernel(useEmbeddings); + ISemanticTextMemory memory = this.InitializeMemory(kernel.GetService()); + kernel.ImportFunctions(new EmailPluginFake()); // Import all sample plugins available for demonstration purposes. TestHelpers.ImportAllSamplePlugins(kernel); var planner = new Microsoft.SemanticKernel.Planners.SequentialPlanner(kernel, - new SequentialPlannerConfig { SemanticMemoryConfig = new() { RelevancyThreshold = 0.65, MaxRelevantFunctions = 30, Memory = kernel.Memory } }); + new SequentialPlannerConfig { SemanticMemoryConfig = new() { RelevancyThreshold = 0.65, MaxRelevantFunctions = 30, Memory = memory } }); // Act var plan = await planner.CreatePlanAsync(prompt); @@ -134,8 +139,7 @@ private IKernel InitializeKernel(bool useEmbeddings = false, bool useChatModel = builder.WithAzureTextEmbeddingGenerationService( deploymentName: azureOpenAIEmbeddingsConfiguration.DeploymentName, endpoint: azureOpenAIEmbeddingsConfiguration.Endpoint, - apiKey: azureOpenAIEmbeddingsConfiguration.ApiKey) - .WithMemoryStorage(new VolatileMemoryStore()); + apiKey: azureOpenAIEmbeddingsConfiguration.ApiKey); } var kernel = builder.Build(); @@ -143,6 +147,17 @@ private IKernel InitializeKernel(bool useEmbeddings = false, bool useChatModel = return kernel; } + private ISemanticTextMemory InitializeMemory(ITextEmbeddingGeneration textEmbeddingGeneration) + { + var builder = new MemoryBuilder(); + + builder.WithLoggerFactory(this._logger); + builder.WithMemoryStore(new VolatileMemoryStore()); + builder.WithTextEmbeddingGeneration(textEmbeddingGeneration); + + return builder.Build(); + } + private readonly ILoggerFactory _logger; private readonly RedirectOutput _testOutputHelper; private readonly IConfigurationRoot _configuration; diff --git a/dotnet/src/IntegrationTests/Planners/StepwisePlanner/StepwisePlannerTests.cs b/dotnet/src/IntegrationTests/Planners/StepwisePlanner/StepwisePlannerTests.cs index fb435bffcf8f..e6869e8d42bf 100644 --- a/dotnet/src/IntegrationTests/Planners/StepwisePlanner/StepwisePlannerTests.cs +++ b/dotnet/src/IntegrationTests/Planners/StepwisePlanner/StepwisePlannerTests.cs @@ -10,7 +10,6 @@ using Microsoft.SemanticKernel.Functions.OpenAPI.Extensions; using Microsoft.SemanticKernel.Planners; using Microsoft.SemanticKernel.Plugins.Core; -using Microsoft.SemanticKernel.Plugins.Memory; using Microsoft.SemanticKernel.Plugins.Web; using Microsoft.SemanticKernel.Plugins.Web.Bing; using SemanticKernel.IntegrationTests.TestSettings; @@ -170,8 +169,7 @@ private IKernel InitializeKernel(bool useEmbeddings = false, bool useChatModel = builder.WithAzureTextEmbeddingGenerationService( deploymentName: azureOpenAIEmbeddingsConfiguration.DeploymentName, endpoint: azureOpenAIEmbeddingsConfiguration.Endpoint, - apiKey: azureOpenAIEmbeddingsConfiguration.ApiKey) - .WithMemoryStorage(new VolatileMemoryStore()); + apiKey: azureOpenAIEmbeddingsConfiguration.ApiKey); } var kernel = builder.Build(); diff --git a/dotnet/src/Plugins/Plugins.Memory/MemoryBuilder.cs b/dotnet/src/Plugins/Plugins.Memory/MemoryBuilder.cs new file mode 100644 index 000000000000..646f4232cacb --- /dev/null +++ b/dotnet/src/Plugins/Plugins.Memory/MemoryBuilder.cs @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.SemanticKernel.AI.Embeddings; +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.Http; +using Microsoft.SemanticKernel.Memory; + +namespace Microsoft.SemanticKernel.Plugins.Memory; + +/// +/// A builder for Memory plugin. +/// +public sealed class MemoryBuilder +{ + private Func? _memoryStoreFactory = null; + private Func? _embeddingGenerationFactory = null; + private IDelegatingHandlerFactory _httpHandlerFactory = NullHttpHandlerFactory.Instance; + private ILoggerFactory _loggerFactory = NullLoggerFactory.Instance; + + /// + /// Build a new instance of using the settings passed so far. + /// + /// Instance of . + public ISemanticTextMemory Build() + { + var memoryStore = this._memoryStoreFactory?.Invoke() ?? + throw new SKException($"{nameof(IMemoryStore)} dependency was not provided. Use {nameof(WithMemoryStore)} method."); + + var embeddingGeneration = this._embeddingGenerationFactory?.Invoke() ?? + throw new SKException($"{nameof(ITextEmbeddingGeneration)} dependency was not provided. Use {nameof(WithTextEmbeddingGeneration)} method."); + + return new SemanticTextMemory(memoryStore, embeddingGeneration); + } + + /// + /// Add a logger factory. + /// + /// The to use for logging. If null, no logging will be performed. + /// Updated Memory builder including the logger factory. + public MemoryBuilder WithLoggerFactory(ILoggerFactory loggerFactory) + { + Verify.NotNull(loggerFactory); + this._loggerFactory = loggerFactory; + return this; + } + + /// + /// Add a http handler factory. + /// + /// Http handler factory to add. + /// Updated Memory builder including the http handler factory. + public MemoryBuilder WithHttpHandlerFactory(IDelegatingHandlerFactory httpHandlerFactory) + { + Verify.NotNull(httpHandlerFactory); + this._httpHandlerFactory = httpHandlerFactory; + return this; + } + + /// + /// Add memory store. + /// + /// Store to add. + /// Updated Memory builder including the memory store. + public MemoryBuilder WithMemoryStore(IMemoryStore store) + { + Verify.NotNull(store); + this._memoryStoreFactory = () => store; + return this; + } + + /// + /// Add memory store factory. + /// + /// The store factory. + /// Updated Memory builder including the memory store. + public MemoryBuilder WithMemoryStore(Func factory) where TStore : IMemoryStore + { + Verify.NotNull(factory); + this._memoryStoreFactory = () => factory(this._loggerFactory); + return this; + } + + /// + /// Add memory store factory. + /// + /// The store factory. + /// Updated Memory builder including the memory store. + public MemoryBuilder WithMemoryStore(Func factory) where TStore : IMemoryStore + { + Verify.NotNull(factory); + this._memoryStoreFactory = () => factory(this._loggerFactory, this._httpHandlerFactory); + return this; + } + + /// + /// Add text embedding generation. + /// + /// The text embedding generation. + /// Updated Memory builder including the text embedding generation. + public MemoryBuilder WithTextEmbeddingGeneration(ITextEmbeddingGeneration textEmbeddingGeneration) + { + Verify.NotNull(textEmbeddingGeneration); + this._embeddingGenerationFactory = () => textEmbeddingGeneration; + return this; + } + + /// + /// Add text embedding generation. + /// + /// The text embedding generation factory. + /// Updated Memory builder including the text embedding generation. + public MemoryBuilder WithTextEmbeddingGeneration( + Func factory) where TEmbeddingGeneration : ITextEmbeddingGeneration + { + Verify.NotNull(factory); + this._embeddingGenerationFactory = () => factory(this._loggerFactory, this._httpHandlerFactory); + return this; + } +} diff --git a/dotnet/src/Plugins/Plugins.UnitTests/Memory/MemoryBuilderTests.cs b/dotnet/src/Plugins/Plugins.UnitTests/Memory/MemoryBuilderTests.cs new file mode 100644 index 000000000000..92aa2ca5dc07 --- /dev/null +++ b/dotnet/src/Plugins/Plugins.UnitTests/Memory/MemoryBuilderTests.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.Extensions.Logging; +using Microsoft.SemanticKernel.AI.Embeddings; +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.Http; +using Microsoft.SemanticKernel.Memory; +using Microsoft.SemanticKernel.Plugins.Memory; +using Moq; +using Xunit; + +namespace SemanticKernel.Plugins.UnitTests.Memory; + +/// +/// Unit tests for class. +/// +public sealed class MemoryBuilderTests +{ + [Fact] + public void ItThrowsExceptionWhenMemoryStoreIsNotProvided() + { + // Arrange + var builder = new MemoryBuilder(); + + // Act + var exception = Assert.Throws(() => builder.Build()); + + // Assert + Assert.Equal("IMemoryStore dependency was not provided. Use WithMemoryStore method.", exception.Message); + } + + [Fact] + public void ItThrowsExceptionWhenEmbeddingGenerationIsNotProvided() + { + // Arrange + var builder = new MemoryBuilder() + .WithMemoryStore(Mock.Of()); + + // Act + var exception = Assert.Throws(() => builder.Build()); + + // Assert + Assert.Equal("ITextEmbeddingGeneration dependency was not provided. Use WithTextEmbeddingGeneration method.", exception.Message); + } + + [Fact] + public void ItInitializesMemoryWhenRequiredDependenciesAreProvided() + { + // Arrange + var builder = new MemoryBuilder() + .WithMemoryStore(Mock.Of()) + .WithTextEmbeddingGeneration(Mock.Of()); + + // Act + var memory = builder.Build(); + + // Assert + Assert.NotNull(memory); + } + + [Fact] + public void ItUsesProvidedLoggerFactory() + { + // Arrange + var loggerFactoryUsed = Mock.Of(); + var loggerFactoryUnused = Mock.Of(); + + // Act & Assert + var builder = new MemoryBuilder() + .WithLoggerFactory(loggerFactoryUsed) + .WithMemoryStore((loggerFactory) => + { + Assert.Same(loggerFactoryUsed, loggerFactory); + Assert.NotSame(loggerFactoryUnused, loggerFactory); + + return Mock.Of(); + }) + .WithTextEmbeddingGeneration((loggerFactory, httpHandlerFactory) => + { + Assert.Same(loggerFactoryUsed, loggerFactory); + Assert.NotSame(loggerFactoryUnused, loggerFactory); + + return Mock.Of(); + }) + .Build(); + } + + [Fact] + public void ItUsesProvidedHttpHandlerFactory() + { + // Arrange + var httpHandlerFactoryUsed = Mock.Of(); + var httpHandlerFactoryUnused = Mock.Of(); + + // Act & Assert + var builder = new MemoryBuilder() + .WithHttpHandlerFactory(httpHandlerFactoryUsed) + .WithMemoryStore((loggerFactory, httpHandlerFactory) => + { + Assert.Same(httpHandlerFactoryUsed, httpHandlerFactory); + Assert.NotSame(httpHandlerFactoryUnused, httpHandlerFactory); + + return Mock.Of(); + }) + .WithTextEmbeddingGeneration((loggerFactory, httpHandlerFactory) => + { + Assert.Same(httpHandlerFactoryUsed, httpHandlerFactory); + Assert.NotSame(httpHandlerFactoryUnused, httpHandlerFactory); + + return Mock.Of(); + }) + .Build(); + } +} diff --git a/dotnet/src/SemanticKernel.Abstractions/IKernel.cs b/dotnet/src/SemanticKernel.Abstractions/IKernel.cs index b7e11420fbbc..78b0324ad581 100644 --- a/dotnet/src/SemanticKernel.Abstractions/IKernel.cs +++ b/dotnet/src/SemanticKernel.Abstractions/IKernel.cs @@ -26,11 +26,6 @@ public interface IKernel /// ILoggerFactory LoggerFactory { get; } - /// - /// Semantic memory instance - /// - ISemanticTextMemory Memory { get; } - /// /// Reference to the engine rendering prompt templates /// @@ -41,12 +36,6 @@ public interface IKernel /// IReadOnlyFunctionCollection Functions { get; } - [Obsolete("Methods, properties and classes which include Skill in the name have been renamed. Use Kernel.Functions instead. This will be removed in a future release.")] - [EditorBrowsable(EditorBrowsableState.Never)] -#pragma warning disable CS1591 - IReadOnlyFunctionCollection Skills { get; } -#pragma warning restore CS1591 - /// /// Reference to Http handler factory /// @@ -68,18 +57,6 @@ public interface IKernel /// A list of all the semantic functions found in the directory, indexed by function name. IDictionary ImportFunctions(object functionsInstance, string? pluginName = null); - [Obsolete("Methods, properties and classes which include Skill in the name have been renamed. Use Kernel.ImportFunctions instead. This will be removed in a future release.")] - [EditorBrowsable(EditorBrowsableState.Never)] -#pragma warning disable CS1591 - IDictionary ImportSkill(object functionsInstance, string? pluginName = null); -#pragma warning restore CS1591 - - /// - /// Set the semantic memory to use - /// - /// Semantic memory instance - void RegisterMemory(ISemanticTextMemory memory); - /// /// Run a single synchronous or asynchronous . /// @@ -190,6 +167,19 @@ SKContext CreateNewContext( #region Obsolete + /// + /// Semantic memory instance + /// + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] + ISemanticTextMemory Memory { get; } + + [Obsolete("Methods, properties and classes which include Skill in the name have been renamed. Use Kernel.Functions instead. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] +#pragma warning disable CS1591 + IReadOnlyFunctionCollection Skills { get; } +#pragma warning restore CS1591 + /// /// Access registered functions by plugin name and function name. Not case sensitive. /// The function might be native or semantic, it's up to the caller handling it. @@ -201,5 +191,20 @@ SKContext CreateNewContext( [EditorBrowsable(EditorBrowsableState.Never)] ISKFunction Func(string pluginName, string functionName); + [Obsolete("Methods, properties and classes which include Skill in the name have been renamed. Use Kernel.ImportFunctions instead. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] +#pragma warning disable CS1591 + IDictionary ImportSkill(object functionsInstance, string? pluginName = null); +#pragma warning restore CS1591 + + /// + /// Set the semantic memory to use + /// + /// Semantic memory instance + /// + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] + void RegisterMemory(ISemanticTextMemory memory); + #endregion } diff --git a/dotnet/src/SemanticKernel.Core/Kernel.cs b/dotnet/src/SemanticKernel.Core/Kernel.cs index 03c36548026b..c5cfcd0a8f82 100644 --- a/dotnet/src/SemanticKernel.Core/Kernel.cs +++ b/dotnet/src/SemanticKernel.Core/Kernel.cs @@ -35,18 +35,9 @@ public sealed class Kernel : IKernel, IDisposable /// public ILoggerFactory LoggerFactory { get; } - /// - public ISemanticTextMemory Memory => this._memory; - /// public IReadOnlyFunctionCollection Functions => this._functionCollection; - [Obsolete("Methods, properties and classes which include Skill in the name have been renamed. Use Kernel.Functions instead. This will be removed in a future release.")] - [EditorBrowsable(EditorBrowsableState.Never)] -#pragma warning disable CS1591 - public IReadOnlyFunctionCollection Skills => this._functionCollection; -#pragma warning restore CS1591 - /// public IPromptTemplateEngine PromptTemplateEngine { get; } @@ -122,15 +113,6 @@ public IDictionary ImportFunctions(object functionsInstance return functions; } - [Obsolete("Methods, properties and classes which include Skill in the name have been renamed. Use Kernel.ImportFunctions instead. This will be removed in a future release.")] - [EditorBrowsable(EditorBrowsableState.Never)] -#pragma warning disable CS1591 - public IDictionary ImportSkill(object functionsInstance, string? pluginName = null) - { - return this.ImportFunctions(functionsInstance, pluginName); - } -#pragma warning restore CS1591 - /// public ISKFunction RegisterCustomFunction(ISKFunction customFunction) { @@ -142,12 +124,6 @@ public ISKFunction RegisterCustomFunction(ISKFunction customFunction) return customFunction; } - /// - public void RegisterMemory(ISemanticTextMemory memory) - { - this._memory = memory; - } - /// public Task RunAsync(ISKFunction skFunction, ContextVariables? variables = null, @@ -368,6 +344,17 @@ private static Dictionary ImportFunctions(object pluginInst #region Obsolete =============================================================================== + /// + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public ISemanticTextMemory Memory => this._memory; + + [Obsolete("Methods, properties and classes which include Skill in the name have been renamed. Use Kernel.Functions instead. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] +#pragma warning disable CS1591 + public IReadOnlyFunctionCollection Skills => this._functionCollection; +#pragma warning restore CS1591 + /// [Obsolete("Func shorthand no longer no longer supported. Use Kernel.Functions collection instead. This will be removed in a future release.")] [EditorBrowsable(EditorBrowsableState.Never)] @@ -375,5 +362,23 @@ public ISKFunction Func(string pluginName, string functionName) { return this.Functions.GetFunction(pluginName, functionName); } + + /// + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public void RegisterMemory(ISemanticTextMemory memory) + { + this._memory = memory; + } + + [Obsolete("Methods, properties and classes which include Skill in the name have been renamed. Use Kernel.ImportFunctions instead. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] +#pragma warning disable CS1591 + public IDictionary ImportSkill(object functionsInstance, string? pluginName = null) + { + return this.ImportFunctions(functionsInstance, pluginName); + } +#pragma warning restore CS1591 + #endregion } diff --git a/dotnet/src/SemanticKernel.Core/KernelBuilder.cs b/dotnet/src/SemanticKernel.Core/KernelBuilder.cs index d9dcee0309ad..b8a5494e6354 100644 --- a/dotnet/src/SemanticKernel.Core/KernelBuilder.cs +++ b/dotnet/src/SemanticKernel.Core/KernelBuilder.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using System; +using System.ComponentModel; using System.Linq; using System.Reflection; using System.Threading; @@ -59,7 +60,9 @@ public IKernel Build() // TODO: decouple this from 'UseMemory' kernel extension if (this._memoryStorageFactory != null) { +#pragma warning disable CS0618 // This will be removed in a future release. instance.UseMemory(this._memoryStorageFactory.Invoke()); +#pragma warning restore CS0618 // This will be removed in a future release. } return instance; @@ -82,6 +85,8 @@ public KernelBuilder WithLoggerFactory(ILoggerFactory loggerFactory) /// /// Semantic text memory entity to add. /// Updated kernel builder including the semantic text memory entity. + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] public KernelBuilder WithMemory(ISemanticTextMemory memory) { Verify.NotNull(memory); @@ -94,6 +99,8 @@ public KernelBuilder WithMemory(ISemanticTextMemory memory) /// /// The store factory. /// Updated kernel builder including the semantic text memory entity. + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] public KernelBuilder WithMemory(Func factory) where TStore : ISemanticTextMemory { Verify.NotNull(factory); @@ -106,6 +113,8 @@ public KernelBuilder WithMemory(Func factory) wh /// /// Storage to add. /// Updated kernel builder including the memory storage. + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] public KernelBuilder WithMemoryStorage(IMemoryStore storage) { Verify.NotNull(storage); @@ -118,6 +127,8 @@ public KernelBuilder WithMemoryStorage(IMemoryStore storage) /// /// The storage factory. /// Updated kernel builder including the memory storage. + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] public KernelBuilder WithMemoryStorage(Func factory) where TStore : IMemoryStore { Verify.NotNull(factory); @@ -130,6 +141,8 @@ public KernelBuilder WithMemoryStorage(Func fact /// /// The storage factory. /// Updated kernel builder including the memory storage. + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] public KernelBuilder WithMemoryStorage(Func factory) where TStore : IMemoryStore { Verify.NotNull(factory); diff --git a/dotnet/src/SemanticKernel.Core/Memory/MemoryConfiguration.cs b/dotnet/src/SemanticKernel.Core/Memory/MemoryConfiguration.cs index caa177670924..fb08aeb3cb93 100644 --- a/dotnet/src/SemanticKernel.Core/Memory/MemoryConfiguration.cs +++ b/dotnet/src/SemanticKernel.Core/Memory/MemoryConfiguration.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using Microsoft.SemanticKernel.AI.Embeddings; using Microsoft.SemanticKernel.Diagnostics; @@ -21,6 +23,8 @@ public static class MemoryConfiguration /// Kernel instance /// Memory storage /// Kernel service id for embedding generation + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static void UseMemory(this IKernel kernel, IMemoryStore storage, string? embeddingsServiceId = null) { var embeddingGenerator = kernel.GetService(embeddingsServiceId); @@ -35,6 +39,8 @@ public static void UseMemory(this IKernel kernel, IMemoryStore storage, string? /// Embedding generator /// Memory storage [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "The embeddingGenerator object is disposed by the kernel")] + [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] + [EditorBrowsable(EditorBrowsableState.Never)] public static void UseMemory(this IKernel kernel, ITextEmbeddingGeneration embeddingGenerator, IMemoryStore storage) { Verify.NotNull(storage); diff --git a/dotnet/src/SemanticKernel.Core/Memory/SemanticTextMemory.cs b/dotnet/src/SemanticKernel.Core/Memory/SemanticTextMemory.cs index 52209b13f72a..32fae7dba086 100644 --- a/dotnet/src/SemanticKernel.Core/Memory/SemanticTextMemory.cs +++ b/dotnet/src/SemanticKernel.Core/Memory/SemanticTextMemory.cs @@ -14,7 +14,7 @@ namespace Microsoft.SemanticKernel.Memory; /// Implementation of . Provides methods to save, retrieve, and search for text information /// in a semantic memory store. /// -public sealed class SemanticTextMemory : ISemanticTextMemory, IDisposable +public sealed class SemanticTextMemory : ISemanticTextMemory { private readonly ITextEmbeddingGeneration _embeddingGenerator; private readonly IMemoryStore _storage; @@ -128,16 +128,4 @@ public async Task> GetCollectionsAsync(CancellationToken cancellat { return await this._storage.GetCollectionsAsync(cancellationToken).ToListAsync(cancellationToken).ConfigureAwait(false); } - - /// - /// Disposes the resources used by the instance. - /// - public void Dispose() - { - // ReSharper disable once SuspiciousTypeConversion.Global - if (this._embeddingGenerator is IDisposable emb) { emb.Dispose(); } - - // ReSharper disable once SuspiciousTypeConversion.Global - if (this._storage is IDisposable storage) { storage.Dispose(); } - } }