diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 938c4a7..787e6e0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -39,7 +39,7 @@ jobs: run: dotnet tool install --global dotnet-sonarscanner - name: Sonar - Begin Analyze - env: + env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: dotnet-sonarscanner begin /k:"${{ secrets.SONAR_PROJECT_KEY }}" /o:"${{ secrets.SONAR_ORGANIZATION }}" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.exclusions="**/tst/**/*" /d:sonar.cs.opencover.reportsPaths="**/tst/**/coverage.opencover.xml" /s:$GITHUB_WORKSPACE/SonarQube.Analysis.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 84d1908..429a8e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,42 @@ Also, any bug fix must start with the prefix Previous classification is not required if changes are simple or all belong to the same category. +## [6.0.4] + +### Important + +This version updates the `Semantic Kernel` library to version `1.0.0-beta8`, which introduces a lot of breaking changes in the code that mostly translate into multiple obsolescence warnings. Eventually, newer versions of this library will fix these warnings once a final version of `Semantic Kernel` is used. + +The main motivation for this update is to take advantage of the latest improvements in the `Semantic Kernel` library, like the `Stepwise Planner` or Function Calls, plus better integrations with LLMs like OpenAI, among many other improvements. + +Sadly, some warnings regarding types or members obsolescence could not be addresses until the Microsoft team behind `Semantic Kernel` provides a final version of the library. So far, these warnings are: + + - CS0618: *IKernel.PromptTemplateEngine' is obsolete: 'PromptTemplateEngine has been replaced with PromptTemplateFactory and will be null. If you pass an PromptTemplateEngine instance when creating a Kernel it will be wrapped in an instance of IPromptTemplateFactory. This will be removed in a future release.* + - CS0618: *ISKFunction.RequestSettings' is obsolete: 'Use PromptTemplateConfig.ModelSettings instead. This will be removed in a future release.* + - CS0618: *ISKFunction.SkillName' is obsolete: 'Methods, properties and classes which include Skill in the name have been renamed. Use ISKFunction.SkillName instead. This will be removed in a future release.* + +### Breaking Changes + +- Updated `Semantic Kernel` libraries to version `1.0.0-beta8`. +- `Encamina.Enmarcha.SemanticKernel.Abstractions` + * Removed method `ValidateAndThrowIfErrorOccurred`. + * Removed properties `ChatModelName`, `CompletionsModelName`, and `EmbeddingsModelName` from `SemanticKernelOptions`. +- The following methods do not throw an `ArgumentException` if the instance of `ISKFunction` is not a semantic function, since now `Semantic Kernel` does not longer differentiates between Semantic and Native functions: + * GetSemanticFunctionPromptAsync + * GetSemanticFunctionUsedTokensAsync +- The extension method `ImportQuestionAnsweringPlugin` in `Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering` does not import the Memory plugin anymore. If the usage of the Question Answering plugin requires memory support, use the `ImportQuestionAnsweringPluginWithMemory` extension method instead. Remember to add a valid instance of `ISemanticTextMemory` as a service in the dependency container. + +### Major Changes + +- New extension method `AddSemanticTextMemory` in `Encamina.Enmarcha.SemanticKernel.Connectors.Memory` to add a semantic text memory (i.e., `ISemanticTextMemory`) to the dependency container. +- New extension method `ImportQuestionAnsweringPluginWithMemory` in `Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering` to support memories when getting context for the Question Answering plugin. Remember to add a valid instance of `ISemanticTextMemory` as a service in the dependency container. +- Added `Directory.Build.targets` at Samples level to prevent generating NuGet packages of these projects. + +### Minor Changes +- Renamed sample projects to match Microsoft's naming conventions. +- Sample projects also use the new `Semantic Kernel` library version `1.0.0-beta8`. +- Some boy scouting by editing the comments in the code to have correct grammar and fixing some StyleCop warnings. + ## [6.0.3.20] ### **Major Changes** diff --git a/Directory.Build.props b/Directory.Build.props index de7120e..47bc022 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -16,14 +16,14 @@ - 6.0.3.20 + 6.0.4.0 true diff --git a/Enmarcha.sln b/Enmarcha.sln index 23fdb42..827d3d1 100644 --- a/Enmarcha.sln +++ b/Enmarcha.sln @@ -124,19 +124,21 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Encamina.Enmarcha.SemanticKernel.Abstractions", "src\Encamina.Enmarcha.SemanticKernel.Abstractions\Encamina.Enmarcha.SemanticKernel.Abstractions.csproj", "{04DA11A3-937C-4D0A-ABDA-65AE9E0FCA5C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{C082F40D-38BE-4283-829E-29346AF71EAE}" + ProjectSection(SolutionItems) = preProject + samples\Directory.Build.targets = samples\Directory.Build.targets + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Data", "Data", "{B9E33951-E387-4A80-A652-A908FCBB34F3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample_Data_CosmosDB", "samples\Data\Sample_Data_CosmosDB\Sample_Data_CosmosDB.csproj", "{264A9DAA-2556-479A-A0F0-20A1DE14AC44}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SemanticKernel", "SemanticKernel", "{43252034-27E2-4981-AC2D-EA986B287863}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample_Data_EntityFramework", "samples\Data\Sample_Data_EntityFramework\Sample_Data_EntityFramework.csproj", "{68E17F14-A683-450C-A557-F27F4DF4DFD9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Encamina.Enmarcha.Samples.Data.CosmosDB", "samples\Data\Encamina.Enmarcha.Samples.Data.CosmosDB\Encamina.Enmarcha.Samples.Data.CosmosDB.csproj", "{D2463070-D856-41B7-93DE-888E59885CD2}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SemanticKernel", "SemanticKernel", "{43252034-27E2-4981-AC2D-EA986B287863}" - ProjectSection(SolutionItems) = preProject - samples\SemanticKernel\Sample_SemanticKernel_Text\Sample_SemanticKernel_Text.csproj = samples\SemanticKernel\Sample_SemanticKernel_Text\Sample_SemanticKernel_Text.csproj - EndProjectSection +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Encamina.Enmarcha.Samples.Data.EntityFramework", "samples\Data\Encamina.Enmarcha.Samples.Data.EntityFramework\Encamina.Enmarcha.Samples.Data.EntityFramework.csproj", "{BF6C4DFC-3CB3-4C62-8B86-08C0C1537CBC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Encamina.Enmarcha.Samples.SemanticKernel.Text", "samples\SemanticKernel\Encamina.Enmarcha.Samples.SemanticKernel.Text\Encamina.Enmarcha.Samples.SemanticKernel.Text.csproj", "{9E8B3AEE-AC1C-4F46-A8D2-3EF550F64005}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample_SemanticKernel_QuestionAnswering", "samples\SemanticKernel\Sample_SemanticKernel_QuestionAnswering\Sample_SemanticKernel_QuestionAnswering.csproj", "{661506FB-E0A7-4D6E-997F-A5CA12315424}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering", "samples\SemanticKernel\Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering\Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering.csproj", "{AA1E5E93-FE02-4395-9260-C7C869F22785}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -328,18 +330,22 @@ Global {04DA11A3-937C-4D0A-ABDA-65AE9E0FCA5C}.Debug|Any CPU.Build.0 = Debug|Any CPU {04DA11A3-937C-4D0A-ABDA-65AE9E0FCA5C}.Release|Any CPU.ActiveCfg = Release|Any CPU {04DA11A3-937C-4D0A-ABDA-65AE9E0FCA5C}.Release|Any CPU.Build.0 = Release|Any CPU - {264A9DAA-2556-479A-A0F0-20A1DE14AC44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {264A9DAA-2556-479A-A0F0-20A1DE14AC44}.Debug|Any CPU.Build.0 = Debug|Any CPU - {264A9DAA-2556-479A-A0F0-20A1DE14AC44}.Release|Any CPU.ActiveCfg = Release|Any CPU - {264A9DAA-2556-479A-A0F0-20A1DE14AC44}.Release|Any CPU.Build.0 = Release|Any CPU - {68E17F14-A683-450C-A557-F27F4DF4DFD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {68E17F14-A683-450C-A557-F27F4DF4DFD9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {68E17F14-A683-450C-A557-F27F4DF4DFD9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {68E17F14-A683-450C-A557-F27F4DF4DFD9}.Release|Any CPU.Build.0 = Release|Any CPU - {661506FB-E0A7-4D6E-997F-A5CA12315424}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {661506FB-E0A7-4D6E-997F-A5CA12315424}.Debug|Any CPU.Build.0 = Debug|Any CPU - {661506FB-E0A7-4D6E-997F-A5CA12315424}.Release|Any CPU.ActiveCfg = Release|Any CPU - {661506FB-E0A7-4D6E-997F-A5CA12315424}.Release|Any CPU.Build.0 = Release|Any CPU + {D2463070-D856-41B7-93DE-888E59885CD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2463070-D856-41B7-93DE-888E59885CD2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2463070-D856-41B7-93DE-888E59885CD2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2463070-D856-41B7-93DE-888E59885CD2}.Release|Any CPU.Build.0 = Release|Any CPU + {BF6C4DFC-3CB3-4C62-8B86-08C0C1537CBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF6C4DFC-3CB3-4C62-8B86-08C0C1537CBC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF6C4DFC-3CB3-4C62-8B86-08C0C1537CBC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF6C4DFC-3CB3-4C62-8B86-08C0C1537CBC}.Release|Any CPU.Build.0 = Release|Any CPU + {9E8B3AEE-AC1C-4F46-A8D2-3EF550F64005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E8B3AEE-AC1C-4F46-A8D2-3EF550F64005}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E8B3AEE-AC1C-4F46-A8D2-3EF550F64005}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E8B3AEE-AC1C-4F46-A8D2-3EF550F64005}.Release|Any CPU.Build.0 = Release|Any CPU + {AA1E5E93-FE02-4395-9260-C7C869F22785}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA1E5E93-FE02-4395-9260-C7C869F22785}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA1E5E93-FE02-4395-9260-C7C869F22785}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA1E5E93-FE02-4395-9260-C7C869F22785}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -350,10 +356,11 @@ Global {E8152699-CECB-4BF5-884F-0A760554286E} = {CBD50B5F-AFB8-4DA1-9FD7-17D98EB3ED78} {60C7833C-1E40-4725-8561-D86B424D78A5} = {CBD50B5F-AFB8-4DA1-9FD7-17D98EB3ED78} {B9E33951-E387-4A80-A652-A908FCBB34F3} = {C082F40D-38BE-4283-829E-29346AF71EAE} - {264A9DAA-2556-479A-A0F0-20A1DE14AC44} = {B9E33951-E387-4A80-A652-A908FCBB34F3} - {68E17F14-A683-450C-A557-F27F4DF4DFD9} = {B9E33951-E387-4A80-A652-A908FCBB34F3} {43252034-27E2-4981-AC2D-EA986B287863} = {C082F40D-38BE-4283-829E-29346AF71EAE} - {661506FB-E0A7-4D6E-997F-A5CA12315424} = {43252034-27E2-4981-AC2D-EA986B287863} + {D2463070-D856-41B7-93DE-888E59885CD2} = {B9E33951-E387-4A80-A652-A908FCBB34F3} + {BF6C4DFC-3CB3-4C62-8B86-08C0C1537CBC} = {B9E33951-E387-4A80-A652-A908FCBB34F3} + {9E8B3AEE-AC1C-4F46-A8D2-3EF550F64005} = {43252034-27E2-4981-AC2D-EA986B287863} + {AA1E5E93-FE02-4395-9260-C7C869F22785} = {43252034-27E2-4981-AC2D-EA986B287863} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F30DF47A-541C-4383-BCEB-E4108D06A70E} diff --git a/README.md b/README.md index 2373a39..c3c3ec2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ -# ENMARCHA (Your package to accelerate .NET projects) +# ENMARCHA — Your package to accelerate .NET projects ENMARCHA aims to speed up the development of various .NET applications by leveraging robust modules that integrate with popular services and frameworks. +[![ENMARCHA NuGet](https://github.com/Encamina/enmarcha/actions/workflows/main.yml/badge.svg)](https://github.com/Encamina/enmarcha/actions/workflows/main.yml) + ## 🚀 Modules ### 1. **AI with Azure AI Services (Cognitive Services)** diff --git a/samples/Data/Sample_Data_CosmosDB/Bill.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Bill.cs similarity index 76% rename from samples/Data/Sample_Data_CosmosDB/Bill.cs rename to samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Bill.cs index d27c67e..69154f5 100644 --- a/samples/Data/Sample_Data_CosmosDB/Bill.cs +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Bill.cs @@ -1,7 +1,8 @@ using Newtonsoft.Json; -namespace Sample_Data_CosmosDB; -public class Bill +namespace Encamina.Enmarcha.Samples.Data.CosmosDB; + +internal class Bill { [JsonProperty("id")] public string Id { get; set; } diff --git a/samples/Data/Sample_Data_CosmosDB/Bills.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Bills.cs similarity index 85% rename from samples/Data/Sample_Data_CosmosDB/Bills.cs rename to samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Bills.cs index eee6b76..4119ee1 100644 --- a/samples/Data/Sample_Data_CosmosDB/Bills.cs +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Bills.cs @@ -1,8 +1,8 @@ using Encamina.Enmarcha.Data.Abstractions; -namespace Sample_Data_CosmosDB; +namespace Encamina.Enmarcha.Samples.Data.CosmosDB; -public class Bills +internal class Bills { private readonly IAsyncRepository billsRepository; diff --git a/samples/Data/Sample_Data_CosmosDB/Sample_Data_CosmosDB.csproj b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Encamina.Enmarcha.Samples.Data.CosmosDB.csproj similarity index 100% rename from samples/Data/Sample_Data_CosmosDB/Sample_Data_CosmosDB.csproj rename to samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Encamina.Enmarcha.Samples.Data.CosmosDB.csproj diff --git a/samples/Data/Sample_Data_CosmosDB/Program.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Program.cs similarity index 96% rename from samples/Data/Sample_Data_CosmosDB/Program.cs rename to samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Program.cs index 2896d67..cb0f6fb 100644 --- a/samples/Data/Sample_Data_CosmosDB/Program.cs +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/Program.cs @@ -5,9 +5,9 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Sample_Data_CosmosDB; +namespace Encamina.Enmarcha.Samples.Data.CosmosDB; -internal sealed class Program +internal static class Program { private static async Task Main(string[] args) { diff --git a/samples/Data/Sample_Data_CosmosDB/README.md b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/README.md similarity index 50% rename from samples/Data/Sample_Data_CosmosDB/README.md rename to samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/README.md index 5a874b9..3230e8f 100644 --- a/samples/Data/Sample_Data_CosmosDB/README.md +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/README.md @@ -1,20 +1,20 @@ -# Running the CosmosDB ENMARCHA Nuget sample +# Running the Cosmos DB with ENMARCHA -The CosmosDB ENMARCHA Nuget provides a highly useful transparent service to query information in Azure CosmosDB databases. Azure Cosmos DB is a fully managed NoSQL and relational database for modern app development. This guide will assist you in executing the sample. +The Cosmos DB ENMARCHA Nuget provides a highly useful transparent service to query information in Azure Cosmos DB databases. Azure Cosmos DB is a fully managed NoSQL and relational database for modern app development. This guide will assist you in executing the sample. ## Setup -- Use or generate a Cosmos DB in Azure. To generate a new CosmosDB, see [Azure CosmosDB documentation](https://azure.microsoft.com/es-es/free/cosmos-db/search/). +- Use or generate a Cosmos DB in Azure. To generate a new CosmosDB, see [Azure Cosmos DB documentation](https://azure.microsoft.com/es-es/free/cosmos-db/search/). - Install Visual Studio. For more information, see [Visual Studio](https://visualstudio.microsoft.com). ## Steps Here are the steps to follow to run the example properly: -- Use or generate a new CosmosDB database in Azure. Store the name of the database, the endpoint and the authorization key with read-write privileges in `appsettings.json`. +- Use or generate a new Cosmos DB database in Azure. Store the name of the database, the endpoint and the authorization key with read-write privileges in `appsettings.json`. - Create a new Container in the database called `BILLS`, keep the default configuration. - Open the solution `enmarcha.sln` in the start folder with Visual Studio. -- Go to Samples > Data right-click `Sample_Data_CosmosDB` project and click Set as Startup project. +- Go to Samples > Data right-click `Encamina.Enmarcha.Samples.Data.CosmosDB` project and click Set as Startup project. - Click on the run button. Once the program is running, a console will be displayed waiting for inputs. You can then indicate the actions you want to do. diff --git a/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/appsettings.json b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/appsettings.json new file mode 100644 index 0000000..4acdbe0 --- /dev/null +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.CosmosDB/appsettings.json @@ -0,0 +1,8 @@ +{ + "CosmosOptions": { + "AuthKey": "", // Authentication key required to connect with Azure Cosmos DB. + "Database": "", // Database name to connect with Azure Cosmos DB. + "Endpoint": "" // Azure Cosmos DB service endpoint to use. + }, + "CosmosDBContainerName": "BILLS" +} \ No newline at end of file diff --git a/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Bill.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Bill.cs new file mode 100644 index 0000000..095c33e --- /dev/null +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Bill.cs @@ -0,0 +1,12 @@ +namespace Encamina.Enmarcha.Samples.Data.EntityFramework; + +internal class Bill : IEntity +{ + public string Id { get; set; } + + public string Concept { get; set; } + + public double Amount { get; set; } + + public string EmployeeId { get; set; } +} diff --git a/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Employee.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Employee.cs new file mode 100644 index 0000000..b266542 --- /dev/null +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Employee.cs @@ -0,0 +1,8 @@ +namespace Encamina.Enmarcha.Samples.Data.EntityFramework; + +internal class Employee : IEntity +{ + public string Id { get; set; } + + public string FullName { get; set; } +} diff --git a/samples/Data/Sample_Data_EntityFramework/Sample_Data_EntityFramework.csproj b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Encamina.Enmarcha.Samples.Data.EntityFramework.csproj similarity index 100% rename from samples/Data/Sample_Data_EntityFramework/Sample_Data_EntityFramework.csproj rename to samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Encamina.Enmarcha.Samples.Data.EntityFramework.csproj diff --git a/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/FinantialDBContext.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/FinantialDBContext.cs new file mode 100644 index 0000000..32cf65e --- /dev/null +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/FinantialDBContext.cs @@ -0,0 +1,10 @@ +using Microsoft.EntityFrameworkCore; + +namespace Encamina.Enmarcha.Samples.Data.EntityFramework; + +internal class FinantialDBContext : DbContext +{ + public DbSet Bills { get; set; } + + public DbSet Employees { get; set; } +} \ No newline at end of file diff --git a/samples/Data/Sample_Data_EntityFramework/FinantialOperations.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/FinantialOperations.cs similarity index 55% rename from samples/Data/Sample_Data_EntityFramework/FinantialOperations.cs rename to samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/FinantialOperations.cs index e8ba4a6..6624cfc 100644 --- a/samples/Data/Sample_Data_EntityFramework/FinantialOperations.cs +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/FinantialOperations.cs @@ -1,29 +1,29 @@ using Encamina.Enmarcha.Data.Abstractions; -namespace Sample_Data_EntityFramework; +namespace Encamina.Enmarcha.Samples.Data.EntityFramework; -public class FinantialOperations +internal class FinantialOperations { - private readonly IFullUnitOfWork uow; + private readonly IFullUnitOfWork unitOfWork; - public FinantialOperations(IFullUnitOfWork uow) + public FinantialOperations(IFullUnitOfWork unitOfWork) { - this.uow = uow; + this.unitOfWork = unitOfWork; } public async Task AddAsync(T entity, CancellationToken cancellationToken) where T : class, IEntity { - var entityRepository = uow.GetAsyncRepository(); + var entityRepository = unitOfWork.GetAsyncRepository(); await entityRepository.AddAsync(entity, cancellationToken); - await uow.SaveAsync(cancellationToken); + await unitOfWork.SaveAsync(cancellationToken); } public async Task> GetAllAsync(CancellationToken cancellationToken) where T : class, IEntity { var list = new List(); - var entityRepository = uow.GetAsyncRepository(); + var entityRepository = unitOfWork.GetAsyncRepository(); list.AddRange(await entityRepository.GetAllAsync(cancellationToken)); return list; } diff --git a/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/FinantialUnitOfWork.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/FinantialUnitOfWork.cs new file mode 100644 index 0000000..d030332 --- /dev/null +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/FinantialUnitOfWork.cs @@ -0,0 +1,10 @@ +using Encamina.Enmarcha.Data.EntityFramework; + +namespace Encamina.Enmarcha.Samples.Data.EntityFramework; + +internal class FinantialUnitOfWork : FullUnitOfWork +{ + internal FinantialUnitOfWork(FinantialDBContext dBContext) : base(dBContext) + { + } +} diff --git a/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/IEntity.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/IEntity.cs new file mode 100644 index 0000000..bd3ac96 --- /dev/null +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/IEntity.cs @@ -0,0 +1,5 @@ +namespace Encamina.Enmarcha.Samples.Data.EntityFramework; + +internal interface IEntity +{ +} \ No newline at end of file diff --git a/samples/Data/Sample_Data_EntityFramework/Program.cs b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Program.cs similarity index 94% rename from samples/Data/Sample_Data_EntityFramework/Program.cs rename to samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Program.cs index 3563831..e60d82d 100644 --- a/samples/Data/Sample_Data_EntityFramework/Program.cs +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/Program.cs @@ -6,9 +6,9 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Sample_Data_EntityFramework; +namespace Encamina.Enmarcha.Samples.Data.EntityFramework; -internal sealed class Program +internal static class Program { private static async Task Main(string[] args) { @@ -57,7 +57,7 @@ private static async Task Main(string[] args) Console.WriteLine("Amount of the bill:"); var amount = double.Parse(Console.ReadLine()); await finantialSystemOperations.AddAsync(new Bill() { Amount = amount, Concept = concept, EmployeeId = selectedEmployee.Id }, CancellationToken.None); - Console.WriteLine("Bill succesfully uploaded"); + Console.WriteLine("Bill successfully uploaded"); } break; diff --git a/samples/Data/Sample_Data_EntityFramework/README.md b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/README.md similarity index 78% rename from samples/Data/Sample_Data_EntityFramework/README.md rename to samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/README.md index 48edfa2..1a4b94d 100644 --- a/samples/Data/Sample_Data_EntityFramework/README.md +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/README.md @@ -1,6 +1,6 @@ # Running the EntityFramework ENMARCHA Nuget sample -The EntityFramework ENMARCHA Nuget provides a similar Microsoft Entity Framework experience using SQL Server databasde. SQL Server is a relational database management system (RDBMS) developed by Microsoft. This guide will assist you in executing the sample. +The Entity Framework ENMARCHA Nuget provides a similar Microsoft Entity Framework experience using SQL Server databasde. SQL Server is a relational database management system (RDBMS) developed by Microsoft. This guide will assist you in executing the sample. ## Prerequisites @@ -32,7 +32,7 @@ CREATE TABLE BILL ``` - Go to the database general information, copy the ConnectionString and store it in `appsettings.json`. - Open the solution `enmarcha.sln` in the start folder with Visual Studio. -- Go to Samples > Data right-click `Sample_Data_CosmosDB` project and click Set as Startup project. +- Go to Samples > Data right-click `Encamina.Enmarcha.Samples.Data.EntityFramework` project and click Set as Startup project. - Click on the run button. Once the program is running, a console will be displayed waiting for inputs. You can then indicate the actions you want to do. diff --git a/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/appsettings.json b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/appsettings.json new file mode 100644 index 0000000..b74c9eb --- /dev/null +++ b/samples/Data/Encamina.Enmarcha.Samples.Data.EntityFramework/appsettings.json @@ -0,0 +1,3 @@ +{ + "DefaultConnection": "" // Your connection string. +} \ No newline at end of file diff --git a/samples/Data/Sample_Data_CosmosDB/appsettings.json b/samples/Data/Sample_Data_CosmosDB/appsettings.json deleted file mode 100644 index d82ec36..0000000 --- a/samples/Data/Sample_Data_CosmosDB/appsettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "CosmosOptions": { - "AuthKey": "Your Authorization key", // Authentication key required to connect with Azure Cosmos DB - "Database": "Your database name", // Database name to connect with Azure Cosmos DB - "Endpoint": "Your Endpoint" // Azure Cosmos DB service endpoint to use - }, - "CosmosDBContainerName": "BILLS" -} \ No newline at end of file diff --git a/samples/Data/Sample_Data_EntityFramework/FinantialDBContext.cs b/samples/Data/Sample_Data_EntityFramework/FinantialDBContext.cs deleted file mode 100644 index a3f5b56..0000000 --- a/samples/Data/Sample_Data_EntityFramework/FinantialDBContext.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Microsoft.EntityFrameworkCore; - -namespace Sample_Data_EntityFramework; - -public interface IEntity { } - -public class Employee : IEntity -{ - public string Id { get; set; } - - public string FullName { get; set; } -} - -public class Bill : IEntity -{ - public string Id { get; set; } - - public string Concept { get; set; } - - public double Amount { get; set; } - - public string EmployeeId { get; set; } -} - -public class FinantialDBContext : DbContext -{ - public DbSet Bills { get; set; } - - public DbSet Employees { get; set; } -} \ No newline at end of file diff --git a/samples/Data/Sample_Data_EntityFramework/FinantialUnitOfWork.cs b/samples/Data/Sample_Data_EntityFramework/FinantialUnitOfWork.cs deleted file mode 100644 index c300251..0000000 --- a/samples/Data/Sample_Data_EntityFramework/FinantialUnitOfWork.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Encamina.Enmarcha.Data.Abstractions; -using Encamina.Enmarcha.Data.EntityFramework; - -namespace Sample_Data_EntityFramework; - -public class FinantialUnitOfWork : FullUnitOfWork, IFullUnitOfWork -{ - public FinantialUnitOfWork(FinantialDBContext dBContext) - : base(dBContext) - { - } -} diff --git a/samples/Data/Sample_Data_EntityFramework/appsettings.json b/samples/Data/Sample_Data_EntityFramework/appsettings.json deleted file mode 100644 index f2a4e94..0000000 --- a/samples/Data/Sample_Data_EntityFramework/appsettings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "DefaultConnection": "" -} \ No newline at end of file diff --git a/samples/Directory.Build.targets b/samples/Directory.Build.targets new file mode 100644 index 0000000..1785b3a --- /dev/null +++ b/samples/Directory.Build.targets @@ -0,0 +1,10 @@ + + + + enable + latest + disable + false + + + \ No newline at end of file diff --git a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Sample_SemanticKernel_QuestionAnswering.csproj b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering.csproj similarity index 63% rename from samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Sample_SemanticKernel_QuestionAnswering.csproj rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering.csproj index 531b281..f715ff2 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Sample_SemanticKernel_QuestionAnswering.csproj +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering.csproj @@ -8,17 +8,14 @@ - - - - - - PreserveNewest - + + - + + Always + diff --git a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Example_QuestionAnsweringFromContext.cs b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/ExampleQuestionAnsweringFromContext.cs similarity index 79% rename from samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Example_QuestionAnsweringFromContext.cs rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/ExampleQuestionAnsweringFromContext.cs index 927d831..33e1023 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Example_QuestionAnsweringFromContext.cs +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/ExampleQuestionAnsweringFromContext.cs @@ -1,14 +1,16 @@ -using Encamina.Enmarcha.SemanticKernel.Abstractions; +using Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering; +using Encamina.Enmarcha.SemanticKernel.Abstractions; using Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; + using Microsoft.SemanticKernel; -using Sample_SemanticKernelQuestionAnswering.QuestionAnsweringPlugin; +namespace Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering; -public static class Example_QuestionAnsweringFromContext +internal static class ExampleQuestionAnsweringFromContext { public static async Task RunAsync() { @@ -35,7 +37,7 @@ public static async Task RunAsync() // Initialize semantic kernel var kernel = new KernelBuilder() - .WithAzureChatCompletionService(options.ChatModelDeploymentName, options.Endpoint.ToString(), options.Key) + .WithAzureOpenAIChatCompletionService(options.ChatModelDeploymentName, options.Endpoint.ToString(), options.Key) .Build(); // Import Question Answering plugin @@ -48,8 +50,10 @@ public static async Task RunAsync() var host = hostBuilder.Build(); // Initialize Q&A - var testQuestionAnswering = new TestQuestionAnswering(host.Services.GetService()); + var testQuestionAnswering = new TestQuestionAnswering(host.Services.GetRequiredService()); var result = await testQuestionAnswering.TestQuestionAnsweringFromContextAsync(); + + Console.WriteLine($@"RESULT: {result}"); } } diff --git a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Example_QuestionAnsweringFromMemory..cs b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/ExampleQuestionAnsweringFromMemory..cs similarity index 63% rename from samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Example_QuestionAnsweringFromMemory..cs rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/ExampleQuestionAnsweringFromMemory..cs index 750dcae..adfb8fb 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Example_QuestionAnsweringFromMemory..cs +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/ExampleQuestionAnsweringFromMemory..cs @@ -1,19 +1,18 @@ using Encamina.Enmarcha.SemanticKernel.Abstractions; -using Encamina.Enmarcha.SemanticKernel.Plugins.Memory; using Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; + using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Connectors.AI.OpenAI; using Microsoft.SemanticKernel.Memory; +using Microsoft.SemanticKernel.Plugins.Memory; -using Sample_SemanticKernelQuestionAnswering.Memory; -using Sample_SemanticKernelQuestionAnswering.QuestionAnsweringPlugin; - -namespace Sample_SemanticKernelQuestionAnswering; +namespace Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering; -public static class Example_QuestionAnsweringFromMemory +internal static class ExampleQuestionAnsweringFromMemory { public static async Task RunAsync() { @@ -29,30 +28,27 @@ public static async Task RunAsync() // Configure service hostBuilder.ConfigureServices((hostContext, services) => { + // Get semantic kernel options + var options = hostContext.Configuration.GetRequiredSection(nameof(SemanticKernelOptions)).Get() + ?? throw new InvalidOperationException(@$"Missing configuration for {nameof(SemanticKernelOptions)}"); + // Add Semantic Kernel options services.AddOptions().Bind(hostContext.Configuration.GetSection(nameof(SemanticKernelOptions))).ValidateDataAnnotations().ValidateOnStart(); - // Here use the desired implementation (Qdrant, Volatile...) - services.AddSingleton(); + // Here use any desired implementation (Qdrant, Volatile...) + services.AddSingleton() + .AddSemanticTextMemory(); services.AddScoped(sp => { - // Get semantic kernel options - var options = hostContext.Configuration.GetRequiredSection(nameof(SemanticKernelOptions)).Get() - ?? throw new InvalidOperationException(@$"Missing configuration for {nameof(SemanticKernelOptions)}"); - // Initialize semantic kernel var kernel = new KernelBuilder() - .WithMemoryStorage(sp.GetService()) - .WithAzureChatCompletionService(options.ChatModelDeploymentName, options.Endpoint.ToString(), options.Key) - .WithAzureTextEmbeddingGenerationService(options.EmbeddingsModelDeploymentName, options.Endpoint.ToString(), options.Key) + .WithAzureOpenAIChatCompletionService(options.ChatModelDeploymentName, options.Endpoint.ToString(), options.Key) + .WithAzureOpenAITextEmbeddingGenerationService(options.EmbeddingsModelDeploymentName, options.Endpoint.ToString(), options.Key) .Build(); // Import Question Answering plugin - kernel.ImportQuestionAnsweringPlugin(sp, ILengthFunctions.LengthByTokenCount); - - // Import Memory Plugin - kernel.ImportMemoryPlugin(ILengthFunctions.LengthByTokenCount); + kernel.ImportQuestionAnsweringPluginWithMemory(sp, ILengthFunctions.LengthByTokenCount); return kernel; }); @@ -63,12 +59,14 @@ public static async Task RunAsync() var host = hostBuilder.Build(); // Initialize mock memory - var mockMemoryInformation = new MockMemoryInformation(host.Services.GetService(), host.Services.GetService()); + var mockMemoryInformation = new MockMemoryInformation(host.Services.GetRequiredService(), host.Services.GetRequiredService()); await mockMemoryInformation.CreateCollection(); await mockMemoryInformation.SaveDataMockAsync(); // Initialize Q&A from Memory var testQuestionAnswering = new TestQuestionAnswering(host.Services.GetService()); var result = await testQuestionAnswering.TestQuestionAnsweringFromMemoryAsync(); + + Console.WriteLine($@"RESULT: {result}"); } } diff --git a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Memory/MockMemoryInformation.cs b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/MockMemoryInformation.cs similarity index 95% rename from samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Memory/MockMemoryInformation.cs rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/MockMemoryInformation.cs index c9e4458..7140ad8 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Memory/MockMemoryInformation.cs +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/MockMemoryInformation.cs @@ -2,9 +2,9 @@ using Microsoft.SemanticKernel.Memory; -namespace Sample_SemanticKernelQuestionAnswering.Memory; +namespace Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering; -public class MockMemoryInformation +internal class MockMemoryInformation { private readonly IMemoryManager memoryManager; private readonly IMemoryStore memoryStore; diff --git a/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/Program.cs b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/Program.cs new file mode 100644 index 0000000..7f67a94 --- /dev/null +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/Program.cs @@ -0,0 +1,10 @@ +namespace Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering; + +internal static class Program +{ + private static async Task Main(string[] args) + { + await ExampleQuestionAnsweringFromContext.RunAsync(); + await ExampleQuestionAnsweringFromMemory.RunAsync(); + } +} diff --git a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/README.MD b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/README.MD similarity index 52% rename from samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/README.MD rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/README.MD index b10fcea..e01be00 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/README.MD +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/README.MD @@ -1,8 +1,8 @@ -# Introduction -This is an example project mock of Question Answering plugin to SemanticKernel. -There are two mock examples that you can run QuestionAnswering plugin from Context and QuestionAnswering plugin from Memory. -- See [QuestionAnswering from context plugin](./Example_QuestionAnsweringFromContext.cs). -- See [QuestionAnswering from memory plugin](./Example_QuestionAnsweringFromMemory..cs). +# Introduction +This is an example project mock of Question Answering plugin to Semantic Kernel. +There are two mock examples that you can run: + - Question Answering plugin from Context → [Question Answering from context plugin](./Example_QuestionAnsweringFromContext.cs). + - Question Answering plugin from Memory → [Question Answering from memory plugin](./Example_QuestionAnsweringFromMemory..cs). # Configuration The configuration can be found commented in the [appsettings](./appsettings.json) diff --git a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/QuestionAnsweringPlugin/TestQuestionAnswering.cs b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/TestQuestionAnswering.cs similarity index 80% rename from samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/QuestionAnsweringPlugin/TestQuestionAnswering.cs rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/TestQuestionAnswering.cs index 0473b74..32dbeef 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/QuestionAnsweringPlugin/TestQuestionAnswering.cs +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/TestQuestionAnswering.cs @@ -3,22 +3,20 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Orchestration; -namespace Sample_SemanticKernelQuestionAnswering.QuestionAnsweringPlugin; +namespace Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering; /// /// Example class of Question Answering Plugin. /// -public class TestQuestionAnswering +internal class TestQuestionAnswering { private readonly IKernel kernel; - /// public TestQuestionAnswering(IKernel kernel) { this.kernel = kernel; } - /// public async Task TestQuestionAnsweringFromContextAsync() { var input = @"What year was the French Revolution?"; @@ -37,15 +35,15 @@ public async Task TestQuestionAnsweringFromContextAsync() contextVariables.Set(PluginsInfo.QuestionAnsweringPlugin.Functions.QuestionAnsweringFromContext.Parameters.Input, input); contextVariables.Set(PluginsInfo.QuestionAnsweringPlugin.Functions.QuestionAnsweringFromContext.Parameters.Context, context); - var functionQuestionAnswering = kernel.Func(PluginsInfo.QuestionAnsweringPlugin.Name, PluginsInfo.QuestionAnsweringPlugin.Functions.QuestionAnsweringFromContext.Name); + var functionQuestionAnswering = kernel.Functions.GetFunction(PluginsInfo.QuestionAnsweringPlugin.Name, PluginsInfo.QuestionAnsweringPlugin.Functions.QuestionAnsweringFromContext.Name); var resultContext = await kernel.RunAsync(contextVariables, functionQuestionAnswering); + var result = resultContext.GetValue(); - Console.WriteLine($"# Result: {resultContext.Result} \n"); + Console.WriteLine($"# Result: {result} \n"); - return resultContext.Result; + return result; } - /// public async Task TestQuestionAnsweringFromMemoryAsync() { var input = "What period occurred the Industrial Revolution?"; @@ -59,12 +57,12 @@ public async Task TestQuestionAnsweringFromMemoryAsync() Console.WriteLine($"# Question: {input} \n"); - var functionQuestionAnswering = kernel.Func(PluginsInfo.QuestionAnsweringPlugin.Name, PluginsInfo.QuestionAnsweringPlugin.Functions.QuestionAnsweringFromMemoryQuery.Name); + var functionQuestionAnswering = kernel.Functions.GetFunction(PluginsInfo.QuestionAnsweringPlugin.Name, PluginsInfo.QuestionAnsweringPlugin.Functions.QuestionAnsweringFromMemoryQuery.Name); var resultContext = await kernel.RunAsync(contextVariables, functionQuestionAnswering); + var result = resultContext.GetValue(); - Console.WriteLine($"# Result: {resultContext.Result} \n"); + Console.WriteLine($"# Result: {result} \n"); - return resultContext.Result; + return result; } - } diff --git a/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/appsettings.json b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/appsettings.json new file mode 100644 index 0000000..12ced34 --- /dev/null +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.QuestionAnswering/appsettings.json @@ -0,0 +1,10 @@ +{ + "SemanticKernelOptions": { + "ChatModelName": "", // Name (sort of a unique identifier) of the model to use for chat. + "ChatModelDeploymentName": "", // Model deployment name on the LLM (for example OpenAI) to use for chat. + "EmbeddingsModelName": "", // Name (sort of a unique identifier) of the model to use for embeddings. + "EmbeddingsModelDeploymentName": "", // Model deployment name on the LLM (for example OpenAI) to use for embeddings. + "Endpoint": "", // URL for an LLM resource (like OpenAI). This should include protocol and host name. + "Key": "" // Key credential used to authenticate to an LLM resource. + } +} diff --git a/samples/SemanticKernel/Sample_SemanticKernel_Text/Sample_SemanticKernel_Text.csproj b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/Encamina.Enmarcha.Samples.SemanticKernel.Text.csproj similarity index 63% rename from samples/SemanticKernel/Sample_SemanticKernel_Text/Sample_SemanticKernel_Text.csproj rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/Encamina.Enmarcha.Samples.SemanticKernel.Text.csproj index ff34550..97b6a88 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_Text/Sample_SemanticKernel_Text.csproj +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/Encamina.Enmarcha.Samples.SemanticKernel.Text.csproj @@ -7,17 +7,13 @@ enable - - - - - - - PreserveNewest - - + + + Always + + - + diff --git a/samples/SemanticKernel/Sample_SemanticKernel_Text/TextPlugin/MyClass.cs b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/Example.cs similarity index 84% rename from samples/SemanticKernel/Sample_SemanticKernel_Text/TextPlugin/MyClass.cs rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/Example.cs index 63e4ba2..7d04bd6 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_Text/TextPlugin/MyClass.cs +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/Example.cs @@ -3,9 +3,9 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Orchestration; -namespace Sample_SemanticKernel_Text.Text; +namespace Encamina.Enmarcha.Samples.SemanticKernel.Text; -public class MyClass +internal class Example { private readonly IKernel kernel; @@ -16,7 +16,7 @@ public class MyClass English playwright Watts Phillips, who knew Dumas in his later life, described him as ""the most generous, large - hearted being in the world.He also was the most delightfully amusing and egotistical creature on the face of the earth.His tongue was like a windmill – once set in motion, you never knew when he would stop, especially if the theme was himself."""; /// - public MyClass(IKernel kernel) + public Example(IKernel kernel) { this.kernel = kernel; Console.WriteLine($"# Context: {input} \n"); @@ -29,10 +29,12 @@ public async Task TestSummaryAsync() contextVariables.Set(PluginsInfo.TextPlugin.Functions.Summarize.Parameters.Input, input); contextVariables.Set(PluginsInfo.TextPlugin.Functions.Summarize.Parameters.MaxWordsCount, "15"); - var functionSummarize = kernel.Func(PluginsInfo.TextPlugin.Name, PluginsInfo.TextPlugin.Functions.Summarize.Name); + var functionSummarize = kernel.Functions.GetFunction(PluginsInfo.TextPlugin.Name, PluginsInfo.TextPlugin.Functions.Summarize.Name); var resultContext = await kernel.RunAsync(contextVariables, functionSummarize); - Console.WriteLine($"# Summary: {resultContext.Result} \n"); + var result = resultContext.GetValue(); + + Console.WriteLine($"# Summary: {result} \n"); } /// @@ -42,10 +44,11 @@ public async Task TextKeyPhrasesAsync() contextVariables.Set(PluginsInfo.TextPlugin.Functions.KeyPhrases.Parameters.Input, input); contextVariables.Set(PluginsInfo.TextPlugin.Functions.KeyPhrases.Parameters.TopKeyphrases, "2"); - var functionSummarize = kernel.Func(PluginsInfo.TextPlugin.Name, PluginsInfo.TextPlugin.Functions.KeyPhrases.Name); + var functionSummarize = kernel.Functions.GetFunction(PluginsInfo.TextPlugin.Name, PluginsInfo.TextPlugin.Functions.KeyPhrases.Name); var resultContext = await kernel.RunAsync(contextVariables, functionSummarize); - Console.WriteLine($"# Key Phrases: {resultContext.Result} \n"); - } + var result = resultContext.GetValue(); + Console.WriteLine($"# Key Phrases: {result} \n"); + } } diff --git a/samples/SemanticKernel/Sample_SemanticKernel_Text/Program.cs b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/Program.cs similarity index 78% rename from samples/SemanticKernel/Sample_SemanticKernel_Text/Program.cs rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/Program.cs index 843288b..a23c631 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_Text/Program.cs +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/Program.cs @@ -4,11 +4,12 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; + using Microsoft.SemanticKernel; -using Sample_SemanticKernel_Text.Text; +namespace Encamina.Enmarcha.Samples.SemanticKernel.Text; -internal sealed class Program +internal static class Program { private static async Task Main(string[] args) { @@ -30,7 +31,7 @@ private static async Task Main(string[] args) // Initialize semantic kernel var kernel = new KernelBuilder() - .WithAzureChatCompletionService(options.ChatModelDeploymentName, options.Endpoint.ToString(), options.Key) + .WithAzureOpenAIChatCompletionService(options.ChatModelDeploymentName, options.Endpoint.ToString(), options.Key) .Build(); kernel.ImportTextPlugin(); @@ -42,10 +43,10 @@ private static async Task Main(string[] args) var host = hostBuilder.Build(); // Initialize Examples - var exampleClass = new MyClass(host.Services.GetService()); + var example = new Example(host.Services.GetRequiredService()); - await exampleClass.TestSummaryAsync(); + await example.TestSummaryAsync(); - await exampleClass.TextKeyPhrasesAsync(); + await example.TextKeyPhrasesAsync(); } } diff --git a/samples/SemanticKernel/Sample_SemanticKernel_Text/README.MD b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/README.MD similarity index 76% rename from samples/SemanticKernel/Sample_SemanticKernel_Text/README.MD rename to samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/README.MD index d145431..e0f1ebf 100644 --- a/samples/SemanticKernel/Sample_SemanticKernel_Text/README.MD +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/README.MD @@ -1,6 +1,6 @@ # Introduction -This is an example project mock of Text plugin to SemanticKernel. -There are two mock examples of the text plugin in which one can summarise and other one can extract keywords. +This is an example project mock of Text plugin to Semantic Kernel. +There are two mock examples of the text plugin in which one can summarize and other one can extract keywords. # Configuration The configuration can be found commented in the [appsettings](./appsettings.json) diff --git a/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/appsettings.json b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/appsettings.json new file mode 100644 index 0000000..6ec609b --- /dev/null +++ b/samples/SemanticKernel/Encamina.Enmarcha.Samples.SemanticKernel.Text/appsettings.json @@ -0,0 +1,8 @@ +{ + "SemanticKernelOptions": { + "ChatModelName": "", // Name (sort of a unique identifier) of the model to use for chat. + "ChatModelDeploymentName": "", // Model deployment name on the LLM (for example OpenAI) to use for chat. + "Endpoint": "", // URL for an LLM resource (like OpenAI). This should include protocol and host name. + "Key": "" // Key credential used to authenticate to an LLM resource. + } +} diff --git a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Program.cs b/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Program.cs deleted file mode 100644 index b62a41b..0000000 --- a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/Program.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Sample_SemanticKernelQuestionAnswering; -internal sealed class Program -{ - private static async Task Main(string[] args) - { - await Example_QuestionAnsweringFromContext.RunAsync(); - await Example_QuestionAnsweringFromMemory.RunAsync(); - } -} diff --git a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/appsettings.json b/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/appsettings.json deleted file mode 100644 index f050144..0000000 --- a/samples/SemanticKernel/Sample_SemanticKernel_QuestionAnswering/appsettings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "SemanticKernelOptions": { - "ChatModelName": "gpt-35-turbo", // Name (sort of a unique identifier) of the model to use for chat - "ChatModelDeploymentName": "gpt-35-turbo", // Model deployment name on the LLM (for example OpenAI) to use for chat - "EmbeddingsModelName": "text-embedding-ada-002", // Name (sort of a unique identifier) of the model to use for embeddings - "EmbeddingsModelDeploymentName": "text-embedding-ada-002", // Model deployment name on the LLM (for example OpenAI) to use for embeddings - "Endpoint": "https://your-url.openai.azure.com/", // Uri for an LLM resource (like OpenAI). This should include protocol and hostname. - "Key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // Key credential used to authenticate to an LLM resource - // .... - } -} diff --git a/samples/SemanticKernel/Sample_SemanticKernel_Text/appsettings.json b/samples/SemanticKernel/Sample_SemanticKernel_Text/appsettings.json deleted file mode 100644 index 327c9ea..0000000 --- a/samples/SemanticKernel/Sample_SemanticKernel_Text/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "SemanticKernelOptions": { - "ChatModelName": "gpt-35-turbo", // Name (sort of a unique identifier) of the model to use for chat - "ChatModelDeploymentName": "gpt-35-turbo", // Model deployment name on the LLM (for example OpenAI) to use for chat - "Endpoint": "https://your-url.openai.azure.com/", // Uri for an LLM resource (like OpenAI). This should include protocol and hostname. - "Key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // Key credential used to authenticate to an LLM resource - // .... - } -} diff --git a/src/Encamina.Enmarcha.AI.OpenAI.Abstractions/ModelInfo.cs b/src/Encamina.Enmarcha.AI.OpenAI.Abstractions/ModelInfo.cs index a911df8..56a0bfa 100644 --- a/src/Encamina.Enmarcha.AI.OpenAI.Abstractions/ModelInfo.cs +++ b/src/Encamina.Enmarcha.AI.OpenAI.Abstractions/ModelInfo.cs @@ -1,7 +1,5 @@ using System.Collections.ObjectModel; -using static System.Net.WebRequestMethods; - namespace Encamina.Enmarcha.AI.OpenAI.Abstractions; /// @@ -58,7 +56,7 @@ public sealed class ModelInfo public string Id { get; init; } /// - /// Gets the maximium number of tokens allowed for the model. + /// Gets the maximum number of tokens allowed for the model. /// public int MaxTokens { get; init; } diff --git a/src/Encamina.Enmarcha.SemanticKernel.Abstractions/Encamina.Enmarcha.SemanticKernel.Abstractions.csproj b/src/Encamina.Enmarcha.SemanticKernel.Abstractions/Encamina.Enmarcha.SemanticKernel.Abstractions.csproj index e948041..6909143 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Abstractions/Encamina.Enmarcha.SemanticKernel.Abstractions.csproj +++ b/src/Encamina.Enmarcha.SemanticKernel.Abstractions/Encamina.Enmarcha.SemanticKernel.Abstractions.csproj @@ -4,8 +4,10 @@ netstandard2.1 - - + + + + diff --git a/src/Encamina.Enmarcha.SemanticKernel.Abstractions/ILengthFunctions.cs b/src/Encamina.Enmarcha.SemanticKernel.Abstractions/ILengthFunctions.cs index b3ae830..7fdf48e 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Abstractions/ILengthFunctions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Abstractions/ILengthFunctions.cs @@ -1,4 +1,4 @@ -using Microsoft.SemanticKernel.Connectors.AI.OpenAI.Tokenizers; +using SharpToken; namespace Encamina.Enmarcha.SemanticKernel.Abstractions; @@ -6,7 +6,17 @@ namespace Encamina.Enmarcha.SemanticKernel.Abstractions; public interface ILengthFunctions : AI.Abstractions.ILengthFunctions { /// - /// Gets the number of tokens uisng on the specified text. If the text is or empty (i.e., ), returns zero (0). + /// Gets the number of tokens using encodings for models like `GPT-3.5-Turbo` and `GPT-4` from OpenAI on the specified text. + /// If the text is or empty (i.e., ), returns zero (0). /// - public static Func LengthByTokenCount => (text) => string.IsNullOrEmpty(text) ? 0 : GPT3Tokenizer.Encode(text).Count; -} \ No newline at end of file + /// + /// + public static Func LengthByTokenCount => (text) => string.IsNullOrEmpty(text) ? 0 : GptEncoding.GetEncoding("cl100k_base").Encode(text).Count; + + /// + /// Gets the number of tokens using a given encoding on the specified text. + /// If the text is or empty (i.e., ), returns zero (0). + /// + /// + public static Func LengthByTokenCountUsingEncoding => (encoding, text) => string.IsNullOrEmpty(text) ? 0 : GptEncoding.GetEncoding(encoding).Encode(text).Count; +} diff --git a/src/Encamina.Enmarcha.SemanticKernel.Abstractions/SKContextExtensions.cs b/src/Encamina.Enmarcha.SemanticKernel.Abstractions/SKContextExtensions.cs index d05f81d..82ca7c4 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Abstractions/SKContextExtensions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Abstractions/SKContextExtensions.cs @@ -25,18 +25,4 @@ public static string GetContextVariable(this SKContext context, string variableN ? throw new ArgumentException($"Variable {variableName} not found in SK Context.") : null; } - - /// - /// Checks if an error occurred in a Semantic Kernel context, and throws an exception if so. - /// - /// The SKContext object. - [Obsolete(@"Due to changes in Semantic Kernel library, this method will be removed in future versions of this library. Use common exception handling techniques instead.")] - public static void ValidateAndThrowIfErrorOccurred(this SKContext context) - { - if (context.ErrorOccurred) - { - // Current implementation of Semantic Kernel sets `ErrorOccurred` to `true` if `LastException` is not null. - throw new InvalidOperationException(context.LastException.Message); - } - } } \ No newline at end of file diff --git a/src/Encamina.Enmarcha.SemanticKernel.Abstractions/SemanticKernelOptions.cs b/src/Encamina.Enmarcha.SemanticKernel.Abstractions/SemanticKernelOptions.cs index 335dd42..672bd45 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Abstractions/SemanticKernelOptions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Abstractions/SemanticKernelOptions.cs @@ -27,6 +27,7 @@ public sealed class SemanticKernelOptions /// /// /// This property is required if is not . + /// It is usually used with the Encamina.Enmarcha.AI.OpenAI.Abstractions.ModelInfo class to get metadata and information about the model. /// /// /// This model name must match the model names from the LLM (like OpenAI), like for example gpt-4 or gpt-35-turbo. @@ -52,6 +53,7 @@ public sealed class SemanticKernelOptions /// /// /// This property is required if is not . + /// It is usually used with the Encamina.Enmarcha.AI.OpenAI.Abstractions.ModelInfo class to get metadata and information about the model. /// /// /// This model name must match the model names from the LLM (like OpenAI), like for example gpt-4 or gpt-35-turbo. @@ -62,7 +64,7 @@ public sealed class SemanticKernelOptions public string CompletionsModelName { get; init; } /// - /// Gets the model deployment name on the LLM (for example OpenAI) to use for embddings. + /// Gets the model deployment name on the LLM (for example OpenAI) to use for embeddings. /// /// /// WARNING: The model name does not necessarily have to be the same as the model ID. For example, a model of type «text-embedding-ada-002» might be called «MyEmbeddings»; @@ -77,6 +79,7 @@ public sealed class SemanticKernelOptions /// /// /// This property is required if is not . + /// It is usually used with the Encamina.Enmarcha.AI.OpenAI.Abstractions.ModelInfo class to get metadata and information about the model. /// /// /// This model name must match the model names from the LLM (like OpenAI), like for example gpt-4 or gpt-35-turbo. @@ -87,7 +90,7 @@ public sealed class SemanticKernelOptions public string EmbeddingsModelName { get; init; } /// - /// Gets the for an LLM resource (like OpenAI). This should include protocol and hostname. + /// Gets the for an LLM resource (like OpenAI). This should include protocol and host name. /// [Required] [Uri] diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/BasePptxDocumentConnector.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/BasePptxDocumentConnector.cs index b945677..4ba3fdd 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/BasePptxDocumentConnector.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/BasePptxDocumentConnector.cs @@ -1,10 +1,12 @@ -using System.Text; +// Ignore Spelling: pptx + +using System.Text; using CommunityToolkit.Diagnostics; using DocumentFormat.OpenXml.Packaging; -using Microsoft.SemanticKernel.Skills.Document; +using Microsoft.SemanticKernel.Plugins.Document; namespace Encamina.Enmarcha.SemanticKernel.Connectors.Document.Connectors; @@ -46,13 +48,13 @@ public string ReadText(Stream stream) /// public virtual void Initialize(Stream stream) { - // Intentionally not implemented to comly with the Liskov Substitution Principle... + // Intentionally not implemented to comply with the Liskov Substitution Principle... } /// public virtual void AppendText(Stream stream, string text) { - // Intentionally not implemented to comly with the Liskov Substitution Principle... + // Intentionally not implemented to comply with the Liskov Substitution Principle... } /// diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/CleanPdfDocumentConnector.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/CleanPdfDocumentConnector.cs index 737142a..013fe2c 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/CleanPdfDocumentConnector.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/CleanPdfDocumentConnector.cs @@ -1,4 +1,6 @@ -using CommunityToolkit.Diagnostics; +// Ignore Spelling: pdf + +using CommunityToolkit.Diagnostics; using UglyToad.PdfPig; using UglyToad.PdfPig.Content; diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/ParagraphPptxDocumentConnector.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/ParagraphPptxDocumentConnector.cs index 9d52e8e..85f567f 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/ParagraphPptxDocumentConnector.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/ParagraphPptxDocumentConnector.cs @@ -1,4 +1,6 @@ -using System.Text; +// Ignore Spelling: pptx + +using System.Text; using CommunityToolkit.Diagnostics; diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/PdfDocumentConnector.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/PdfDocumentConnector.cs index e18e90d..f56ab22 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/PdfDocumentConnector.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/PdfDocumentConnector.cs @@ -1,6 +1,8 @@ -using CommunityToolkit.Diagnostics; +// Ignore Spelling: pdf -using Microsoft.SemanticKernel.Skills.Document; +using CommunityToolkit.Diagnostics; + +using Microsoft.SemanticKernel.Plugins.Document; using UglyToad.PdfPig; diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/PdfWithTocDocumentConnector.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/PdfWithTocDocumentConnector.cs index 43955d7..570fa5b 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/PdfWithTocDocumentConnector.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/PdfWithTocDocumentConnector.cs @@ -1,4 +1,7 @@ -using System.Text; +// Ignore Spelling: pdf +// Ignore Spelling: toc + +using System.Text; using System.Text.RegularExpressions; using CommunityToolkit.Diagnostics; @@ -88,8 +91,10 @@ private static void AddTocContent(List tocItems, IReadOnlyCollection p.Number == nextTocItem.PageNumber); @@ -97,9 +102,10 @@ private static void AddTocContent(List tocItems, IReadOnlyCollection p.Number); var lastIndex = lastPage.Content.Length; diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/SlidePptxDocumentConnector.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/SlidePptxDocumentConnector.cs index e46ec7f..49dae76 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/SlidePptxDocumentConnector.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/SlidePptxDocumentConnector.cs @@ -1,4 +1,6 @@ -using System.Text; +// Ignore Spelling: pptx + +using System.Text; using CommunityToolkit.Diagnostics; diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/StrictFormatCleanPdfDocumentConnector.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/StrictFormatCleanPdfDocumentConnector.cs index 597fa17..d388114 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/StrictFormatCleanPdfDocumentConnector.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/StrictFormatCleanPdfDocumentConnector.cs @@ -1,4 +1,6 @@ -using System.Text; +// Ignore Spelling: pdf + +using System.Text; using UglyToad.PdfPig; using UglyToad.PdfPig.Content; diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/TxtDocumentConnector.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/TxtDocumentConnector.cs index 5753580..fe4add3 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/TxtDocumentConnector.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/TxtDocumentConnector.cs @@ -1,8 +1,10 @@ -using System.Text; +// Ignore Spelling: txt + +using System.Text; using CommunityToolkit.Diagnostics; -using Microsoft.SemanticKernel.Skills.Document; +using Microsoft.SemanticKernel.Plugins.Document; namespace Encamina.Enmarcha.SemanticKernel.Connectors.Document.Connectors; @@ -34,12 +36,12 @@ public string ReadText(Stream stream) /// public void Initialize(Stream stream) { - // Intentionally not implemented to comly with the Liskov Substitution Principle... + // Intentionally not implemented to comply with the Liskov Substitution Principle... } /// public void AppendText(Stream stream, string text) { - // Intentionally not implemented to comly with the Liskov Substitution Principle... + // Intentionally not implemented to comply with the Liskov Substitution Principle... } } diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/VttDocumentConnector.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/VttDocumentConnector.cs index 800b7a5..56180fd 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/VttDocumentConnector.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Connectors/VttDocumentConnector.cs @@ -1,9 +1,11 @@ -using System.Text; +// Ignore Spelling: vtt + +using System.Text; using System.Text.RegularExpressions; using CommunityToolkit.Diagnostics; -using Microsoft.SemanticKernel.Skills.Document; +using Microsoft.SemanticKernel.Plugins.Document; namespace Encamina.Enmarcha.SemanticKernel.Connectors.Document.Connectors; @@ -47,12 +49,12 @@ public string ReadText(Stream stream) /// public void Initialize(Stream stream) { - // Intentionally not implemented to comly with the Liskov Substitution Principle... + // Intentionally not implemented to comply with the Liskov Substitution Principle... } /// public void AppendText(Stream stream, string text) { - // Intentionally not implemented to comly with the Liskov Substitution Principle... + // Intentionally not implemented to comply with the Liskov Substitution Principle... } } diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/DefaultDocumentContentExtractor.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/DefaultDocumentContentExtractor.cs index 0c5415a..a478739 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/DefaultDocumentContentExtractor.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/DefaultDocumentContentExtractor.cs @@ -5,8 +5,8 @@ using Encamina.Enmarcha.SemanticKernel.Connectors.Document.Connectors; using Encamina.Enmarcha.SemanticKernel.Connectors.Document.Resources; -using Microsoft.SemanticKernel.Skills.Document; -using Microsoft.SemanticKernel.Skills.Document.OpenXml; +using Microsoft.SemanticKernel.Plugins.Document; +using Microsoft.SemanticKernel.Plugins.Document.OpenXml; namespace Encamina.Enmarcha.SemanticKernel.Connectors.Document; diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/DocumentContentExtractorBase.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/DocumentContentExtractorBase.cs index 0fdb171..818a331 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/DocumentContentExtractorBase.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/DocumentContentExtractorBase.cs @@ -1,6 +1,6 @@ using Encamina.Enmarcha.AI.Abstractions; -using Microsoft.SemanticKernel.Skills.Document; +using Microsoft.SemanticKernel.Plugins.Document; namespace Encamina.Enmarcha.SemanticKernel.Connectors.Document; diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Encamina.Enmarcha.SemanticKernel.Connectors.Document.csproj b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Encamina.Enmarcha.SemanticKernel.Connectors.Document.csproj index d57a0e2..ba54d38 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Encamina.Enmarcha.SemanticKernel.Connectors.Document.csproj +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Document/Encamina.Enmarcha.SemanticKernel.Connectors.Document.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Memory/Encamina.Enmarcha.SemanticKernel.Connectors.Memory.csproj b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Memory/Encamina.Enmarcha.SemanticKernel.Connectors.Memory.csproj index 9d8769d..73f27fd 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Memory/Encamina.Enmarcha.SemanticKernel.Connectors.Memory.csproj +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Memory/Encamina.Enmarcha.SemanticKernel.Connectors.Memory.csproj @@ -9,11 +9,13 @@ - + + + diff --git a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Memory/Extensions/IServiceCollectionExtensions.cs b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Memory/Extensions/IServiceCollectionExtensions.cs index be99122..3a9fbf1 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Connectors.Memory/Extensions/IServiceCollectionExtensions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Connectors.Memory/Extensions/IServiceCollectionExtensions.cs @@ -1,11 +1,15 @@ using Encamina.Enmarcha.Data.Qdrant.Abstractions; using Encamina.Enmarcha.Data.Qdrant.Abstractions.Extensions; +using Encamina.Enmarcha.SemanticKernel.Abstractions; + using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Microsoft.SemanticKernel.Connectors.AI.OpenAI; using Microsoft.SemanticKernel.Connectors.Memory.Qdrant; using Microsoft.SemanticKernel.Memory; +using Microsoft.SemanticKernel.Plugins.Memory; namespace Microsoft.Extensions.DependencyInjection; @@ -42,7 +46,29 @@ public static IServiceCollection AddQdrantMemoryStore(this IServiceCollection se httpClient.ConfigureHttpClientForQdrant(qdrantOptions); }); - return new QdrantMemoryStore(httpClient, qdrantOptions.VectorSize, logger: sp.GetService>()); + return new QdrantMemoryStore(httpClient, qdrantOptions.VectorSize, loggerFactory: sp.GetService()); + }); + } + + /// + /// Adds semantic text memory () to the in the specified service lifetime. + /// + /// + /// By default, the service lifetime is . + /// + /// The to add services to. + /// The lifetime for the semantic text memory. + /// The so that additional calls can be chained. + public static IServiceCollection AddSemanticTextMemory(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) + { + return services.TryAddType(serviceLifetime, sp => + { + var options = sp.GetRequiredService>().Value; + + return new MemoryBuilder() + .WithAzureOpenAITextEmbeddingGenerationService(options.EmbeddingsModelDeploymentName, options.Endpoint.ToString(), options.Key) + .WithMemoryStore(sp.GetRequiredService()) + .Build(); }); } } diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Encamina.Enmarcha.SemanticKernel.Plugins.Chat.csproj b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Encamina.Enmarcha.SemanticKernel.Plugins.Chat.csproj index a3d9bdd..6b21480 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Encamina.Enmarcha.SemanticKernel.Plugins.Chat.csproj +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Encamina.Enmarcha.SemanticKernel.Plugins.Chat.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/IKernelExtensions.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/IKernelExtensions.cs index 4bdc8ca..e2f51d2 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/IKernelExtensions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/IKernelExtensions.cs @@ -10,7 +10,6 @@ using Microsoft.Extensions.Options; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.SkillDefinition; namespace Encamina.Enmarcha.SemanticKernel.Plugins.Chat; @@ -67,6 +66,6 @@ public static IDictionary ImportChatWithHistoryPluginUsingC var chatWithHistoryPlugin = new ChatWithHistoryPlugin(kernel, semanticKernelOptions.ChatModelName, tokensLengthFunction, chatMessagesHistoryRepository, chatWithHistoryPluginOptions); - return kernel.ImportSkill(chatWithHistoryPlugin, PluginsInfo.ChatWithHistoryPlugin.Name); + return kernel.ImportFunctions(chatWithHistoryPlugin, PluginsInfo.ChatWithHistoryPlugin.Name); } } diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Plugins/ChatWithHistoryPlugin.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Plugins/ChatWithHistoryPlugin.cs index 3383b04..ff4747f 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Plugins/ChatWithHistoryPlugin.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Plugins/ChatWithHistoryPlugin.cs @@ -7,7 +7,6 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.AI.ChatCompletion; -using Microsoft.SemanticKernel.SkillDefinition; namespace Encamina.Enmarcha.SemanticKernel.Plugins.Chat.Plugins; diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Plugins/ChatWithHistoryPluginOptions.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Plugins/ChatWithHistoryPluginOptions.cs index 06e5fdc..f7d5476 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Plugins/ChatWithHistoryPluginOptions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/Plugins/ChatWithHistoryPluginOptions.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -using Microsoft.SemanticKernel.AI.ChatCompletion; +using Microsoft.SemanticKernel.Connectors.AI.OpenAI; namespace Encamina.Enmarcha.SemanticKernel.Plugins.Chat.Plugins; @@ -17,11 +17,10 @@ public class ChatWithHistoryPluginOptions public virtual int HistoryMaxMessages { get; init; } /// - /// Gets a valid instance of (from Semantic Kernel) with settings for the chat request. + /// Gets a valid instance of (from Semantic Kernel) with settings for the chat request. /// [Required] - [Obsolete(@"Due to future changes in Semantic Kernel library, this property type `ChatRequestSettings` will change to `OpenAIRequestSettings `. The signature of this property will change in future versions of this library.")] - public virtual ChatRequestSettings ChatRequestSettings { get; init; } = new() + public virtual OpenAIRequestSettings ChatRequestSettings { get; init; } = new() { MaxTokens = 1000, Temperature = 0.8, diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/PluginsInfo.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/PluginsInfo.cs index da4f1ef..2d34093 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/PluginsInfo.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Chat/PluginsInfo.cs @@ -1,16 +1,11 @@ -using System.Reflection; -using System.Xml.Linq; - -using Encamina.Enmarcha.Core.Extensions; - -using Microsoft.SemanticKernel.SkillDefinition; +using Encamina.Enmarcha.Core.Extensions; namespace Encamina.Enmarcha.SemanticKernel.Plugins.Chat; #pragma warning disable S3218 // Inner class members should not shadow outer class "static" or type members /// -/// Information about plguins in this assembly. +/// Information about plugins in this assembly. /// public static class PluginsInfo { diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/Encamina.Enmarcha.SemanticKernel.Plugins.Memory.csproj b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/Encamina.Enmarcha.SemanticKernel.Plugins.Memory.csproj index f52d153..b5d602e 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/Encamina.Enmarcha.SemanticKernel.Plugins.Memory.csproj +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/Encamina.Enmarcha.SemanticKernel.Plugins.Memory.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/IKernelExtensions.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/IKernelExtensions.cs index 0363dcf..6c48348 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/IKernelExtensions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/IKernelExtensions.cs @@ -1,7 +1,7 @@ using Encamina.Enmarcha.SemanticKernel.Plugins.Memory.Plugins; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.SkillDefinition; +using Microsoft.SemanticKernel.Memory; namespace Encamina.Enmarcha.SemanticKernel.Plugins.Memory; @@ -14,13 +14,13 @@ public static class IKernelExtensions /// Imports the «Memory» plugin and its functions into the kernel. /// /// The instance to add this plugin. + /// A valid instance of a semantic memory to recall memories associated with text. /// A function to count how many tokens are in a string or text. /// A list of all the functions found in this plugin, indexed by function name. - [Obsolete(@"Due to future changes in Semantic Kernel library, the semantic memory will be a dependency outside the `IKernel`. An additional dependency with `ISemanticTextMemory` will be added. The signature of this method will change in future versions of this library.")] - public static IDictionary ImportMemoryPlugin(this IKernel kernel, Func tokensLengthFunction) + public static IDictionary ImportMemoryPlugin(this IKernel kernel, ISemanticTextMemory semanticTextMemory, Func tokensLengthFunction) { - var memoryQueryPlugin = new MemoryQueryPlugin(kernel, tokensLengthFunction); + var memoryQueryPlugin = new MemoryQueryPlugin(semanticTextMemory, tokensLengthFunction); - return kernel.ImportSkill(memoryQueryPlugin, PluginsInfo.MemoryQueryPlugin.Name); + return kernel.ImportFunctions(memoryQueryPlugin, PluginsInfo.MemoryQueryPlugin.Name); } } diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/Plugins/MemoryQueryPlugin.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/Plugins/MemoryQueryPlugin.cs index 31a82f8..43fd439 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/Plugins/MemoryQueryPlugin.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/Plugins/MemoryQueryPlugin.cs @@ -3,7 +3,6 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Memory; -using Microsoft.SemanticKernel.SkillDefinition; namespace Encamina.Enmarcha.SemanticKernel.Plugins.Memory.Plugins; @@ -12,23 +11,22 @@ namespace Encamina.Enmarcha.SemanticKernel.Plugins.Memory.Plugins; /// public class MemoryQueryPlugin { - private readonly IKernel kernel; + private readonly ISemanticTextMemory semanticTextMemory; private readonly Func tokenLengthFunction; /// /// Initializes a new instance of the class. /// - /// The instance of the semantic kernel to work with in this plugin. + /// A valid instance of a semantic memory to recall memories associated with text. /// Function to calculate the length of a string in tokens. - [Obsolete(@"Due to future changes in Semantic Kernel library, the semantic memory will be a dependency outside the `IKernel`. The `IKernel` dependency will be replaced with `ISemanticTextMemory`. The signature of this constructor will change in future versions of this library.")] - public MemoryQueryPlugin(IKernel kernel, Func tokenLengthFunction) + public MemoryQueryPlugin(ISemanticTextMemory semanticTextMemory, Func tokenLengthFunction) { - this.kernel = kernel; + this.semanticTextMemory = semanticTextMemory; this.tokenLengthFunction = tokenLengthFunction ?? throw new ArgumentNullException(nameof(tokenLengthFunction)); } /// - /// Searchs for a query in a memory's collections. + /// Searches for a query in a memory's collections. /// /// The query to look for in the memory's collections. /// A list of collections names, separated by the value of (usually a comma). @@ -55,7 +53,7 @@ public virtual async Task QueryMemoryAsync( foreach (var documentCollection in collections) { - var results = kernel.Memory.SearchAsync( + var results = semanticTextMemory.SearchAsync( documentCollection, query, limit: resultsLimit, diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/PluginsInfo.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/PluginsInfo.cs index 709d9aa..1ac6338 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/PluginsInfo.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Memory/PluginsInfo.cs @@ -2,14 +2,12 @@ using Encamina.Enmarcha.Core.Extensions; -using Microsoft.SemanticKernel.SkillDefinition; - namespace Encamina.Enmarcha.SemanticKernel.Plugins.Memory; #pragma warning disable S3218 // Inner class members should not shadow outer class "static" or type members /// -/// Information about plguins in this assembly. +/// Information about plugins in this assembly. /// public static class PluginsInfo { diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering.csproj b/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering.csproj index 82e7171..89c7442 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering.csproj +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/IKernelExtensions.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/IKernelExtensions.cs index 9f2f170..9801398 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/IKernelExtensions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/IKernelExtensions.cs @@ -9,8 +9,9 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; + using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.SkillDefinition; +using Microsoft.SemanticKernel.Memory; namespace Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering; @@ -25,9 +26,10 @@ public static class IKernelExtensions /// The instance to add this plugin. /// A to resolve the dependencies. /// - /// A function to calculate the length by tokens of the chat messages. These functions are usually available in the «mixin» interface . + /// A function to calculate the length by tokens of the chat messages. These functions are usually available in the «mix-in» interface . /// /// A list of all the functions found in this plugin, indexed by function name. + /// public static IDictionary ImportQuestionAnsweringPlugin(this IKernel kernel, IServiceProvider serviceProvider, Func tokensLengthFunction) { Guard.IsNotNull(serviceProvider); @@ -38,10 +40,30 @@ public static IDictionary ImportQuestionAnsweringPlugin(thi var questionAnsweringPlugin = new QuestionAnsweringPlugin(kernel, modelName, tokensLengthFunction); - var memoryFunc = kernel.ImportMemoryPlugin(tokensLengthFunction); - var questionNativeFunc = kernel.ImportSkill(questionAnsweringPlugin, PluginsInfo.QuestionAnsweringPlugin.Name); + var questionNativeFunc = kernel.ImportFunctions(questionAnsweringPlugin, PluginsInfo.QuestionAnsweringPlugin.Name); var questionSemanticFunc = kernel.ImportSemanticPluginsFromAssembly(Assembly.GetExecutingAssembly()); - return memoryFunc.Union(questionNativeFunc).Union(questionSemanticFunc).ToDictionary(x => x.Key, x => x.Value); + return questionNativeFunc.Union(questionSemanticFunc).ToDictionary(x => x.Key, x => x.Value); + } + + /// + /// Imports the «Question Answering» plugin and its functions into the kernel also adding the «Memory» plugin. + /// + /// The instance to add this plugin. + /// A to resolve the dependencies. + /// + /// A function to calculate the length by tokens of the chat messages. These functions are usually available in the «mix-in» interface . + /// + /// A list of all the functions found in this plugin, indexed by function name. + /// + public static IDictionary ImportQuestionAnsweringPluginWithMemory(this IKernel kernel, IServiceProvider serviceProvider, Func tokensLengthFunction) + { + var semanticTextMemory = serviceProvider.GetRequiredService(); + + var questionAnsweringFunctions = kernel.ImportQuestionAnsweringPlugin(serviceProvider, tokensLengthFunction); + + var memoryFunc = kernel.ImportMemoryPlugin(semanticTextMemory, tokensLengthFunction); + + return memoryFunc.Union(questionAnsweringFunctions).ToDictionary(x => x.Key, x => x.Value); } } diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/Plugins/QuestionAnsweringPlugin.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/Plugins/QuestionAnsweringPlugin.cs index 037cfaf..7e93ad0 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/Plugins/QuestionAnsweringPlugin.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/Plugins/QuestionAnsweringPlugin.cs @@ -3,12 +3,10 @@ using System.Reflection; using Encamina.Enmarcha.AI.OpenAI.Abstractions; -using Encamina.Enmarcha.SemanticKernel.Abstractions; using Encamina.Enmarcha.SemanticKernel.Extensions; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Orchestration; -using Microsoft.SemanticKernel.SkillDefinition; namespace Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering.Plugins; @@ -68,10 +66,10 @@ public virtual async Task QuestionAnsweringFromMemoryQuery( var questionAnsweringVariables = new ContextVariables(); questionAnsweringVariables.Set(@"input", question); - var questionAnsweringFunction = kernel.Skills.GetFunction(PluginsInfo.QuestionAnsweringPlugin.Name, PluginsInfo.QuestionAnsweringPlugin.Functions.QuestionAnsweringFromContext.Name); + var questionAnsweringFunction = kernel.Functions.GetFunction(PluginsInfo.QuestionAnsweringPlugin.Name, PluginsInfo.QuestionAnsweringPlugin.Functions.QuestionAnsweringFromContext.Name); // Calculates the number of tokens used in the «QuestionAnsweringFromContext» function. - // This amount will be subtracted from the total tokens of the model to determine the token limit required by the «QueryMemory» funtion from the «MemoryQueryPlugin». + // This amount will be subtracted from the total tokens of the model to determine the token limit required by the «QueryMemory» function from the «MemoryQueryPlugin». var questionAnsweringFunctionUsedTokens = await kernel.GetSemanticFunctionUsedTokensAsync(questionAnsweringFunction, Assembly.GetExecutingAssembly(), questionAnsweringVariables, tokenLengthFunction, cancellationToken); @@ -85,21 +83,22 @@ var questionAnsweringFunctionUsedTokens memoryQueryVariables.Set(@"collectionSeparator", collectionSeparator.ToString(CultureInfo.InvariantCulture)); // Executes the «QueryMemory» function from the «MemoryQueryPlugin» - var memoryQueryFunction = kernel.Skills.GetFunction(Memory.PluginsInfo.MemoryQueryPlugin.Name, Memory.PluginsInfo.MemoryQueryPlugin.Functions.QueryMemory.Name); - var memoryQueryResultContext = await kernel.RunAsync(memoryQueryVariables, cancellationToken, memoryQueryFunction); - memoryQueryResultContext.ValidateAndThrowIfErrorOccurred(); + var memoryQueryFunction = kernel.Functions.GetFunction(Memory.PluginsInfo.MemoryQueryPlugin.Name, Memory.PluginsInfo.MemoryQueryPlugin.Functions.QueryMemory.Name); - // If the «QueryMemory» function from the «MemoryQueryPlugin» does not return any result, there is no point in trying to responsd. In such a case, `null` is returned. - if (string.IsNullOrWhiteSpace(memoryQueryResultContext.Result)) + var memoryQueryFunctionResult = await memoryQueryFunction.InvokeAsync(kernel.CreateNewContext(memoryQueryVariables), null, cancellationToken); + + var memoryQueryResult = memoryQueryFunctionResult.GetValue(); + + // If the «QueryMemory» function from the «MemoryQueryPlugin» does not return any result, there is no point in trying to answering the question. In such a case, `null` is returned. + if (string.IsNullOrWhiteSpace(memoryQueryResult)) { return null; } // Return to the context of the response function and set the result of the memory query. - questionAnsweringVariables.Set(@"context", memoryQueryResultContext.Result); - var questionAnsweringResultContext = await kernel.RunAsync(questionAnsweringVariables, cancellationToken, questionAnsweringFunction); - questionAnsweringResultContext.ValidateAndThrowIfErrorOccurred(); + questionAnsweringVariables.Set(@"context", memoryQueryResult); + var questionAnsweringFunctionResult = await questionAnsweringFunction.InvokeAsync(kernel.CreateNewContext(questionAnsweringVariables), null, cancellationToken); - return questionAnsweringResultContext.Result; + return questionAnsweringFunctionResult.GetValue(); } } diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/PluginsInfo.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/PluginsInfo.cs index 66e52dc..d034c0a 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/PluginsInfo.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering/PluginsInfo.cs @@ -1,15 +1,11 @@ -using System.Reflection; - -using Encamina.Enmarcha.Core.Extensions; - -using Microsoft.SemanticKernel.SkillDefinition; +using Encamina.Enmarcha.Core.Extensions; namespace Encamina.Enmarcha.SemanticKernel.Plugins.QuestionAnswering; #pragma warning disable S3218 // Inner class members should not shadow outer class "static" or type members /// -/// Information about plguins in this assembly. +/// Information about plugins in this assembly. /// public static class PluginsInfo { @@ -71,7 +67,7 @@ public static class QuestionAnsweringFromMemoryQuery public static class Parameters { /// - /// The name of the «question» parameter, used to look for an answer by searchinf a memory. + /// The name of the «question» parameter, used to look for an answer by searching a memory. /// public static readonly string Question = nameof(Question).ToLowerInvariant(); diff --git a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Text/IKernelExtensions.cs b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Text/IKernelExtensions.cs index 460e498..ea67b7f 100644 --- a/src/Encamina.Enmarcha.SemanticKernel.Plugins.Text/IKernelExtensions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel.Plugins.Text/IKernelExtensions.cs @@ -3,7 +3,6 @@ using Encamina.Enmarcha.SemanticKernel.Extensions; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.SkillDefinition; namespace Encamina.Enmarcha.SemanticKernel.Plugins.Text; diff --git a/src/Encamina.Enmarcha.SemanticKernel/Extensions/IKernelExtensions.cs b/src/Encamina.Enmarcha.SemanticKernel/Extensions/IKernelExtensions.cs index 7c96262..c32a010 100644 --- a/src/Encamina.Enmarcha.SemanticKernel/Extensions/IKernelExtensions.cs +++ b/src/Encamina.Enmarcha.SemanticKernel/Extensions/IKernelExtensions.cs @@ -1,14 +1,13 @@ using System.Reflection; - -using CommunityToolkit.Diagnostics; +using System.Text.Json; using Encamina.Enmarcha.Core.Extensions; using Encamina.Enmarcha.SemanticKernel.Extensions.Resources; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.SemanticFunctions; -using Microsoft.SemanticKernel.SkillDefinition; +using Microsoft.SemanticKernel.TemplateEngine; +using Microsoft.SemanticKernel.TemplateEngine.Basic; namespace Encamina.Enmarcha.SemanticKernel.Extensions; @@ -20,25 +19,14 @@ public static class IKernelExtensions /// /// Generates the final prompt for a given semantic function in a directory located plugin, and using the context variables. /// - /// - /// The parameter must be a semantic function (i.e., the value of the property must - /// be , otherwise an . - /// will be thrown. - /// /// The to work with. /// The semantic function representation. - /// The directory containing the plugin and the files that represens and configures the semantic function. + /// The directory containing the plugin and the files that represents and configures the semantic function. /// A collection of context variables. /// A cancellation token that can be used to receive notice of cancellation. /// A string containing the generated prompt. - /// - /// If the parameter is not a semantic function (i.e., the value of the property is . - /// will be thrown. - /// public static async Task GetSemanticFunctionPromptAsync(this IKernel kernel, ISKFunction skFunction, string functionPluginDirectory, IDictionary contextVariables, CancellationToken cancellationToken) { - Guard.IsTrue(skFunction.IsSemantic, ExceptionMessages.ResourceManager.GetFormattedStringByCurrentCulture(nameof(ExceptionMessages.NotSemanticFunction), skFunction.Name)); - var kernelContext = kernel.CreateNewContext(); foreach (var (key, value) in contextVariables) @@ -50,31 +38,20 @@ public static async Task GetSemanticFunctionPromptAsync(this IKernel ker return File.Exists(promptTemplatePath) ? await kernel.PromptTemplateEngine.RenderAsync(await File.ReadAllTextAsync(promptTemplatePath, cancellationToken), kernelContext, cancellationToken) - : throw new FileNotFoundException(ExceptionMessages.ResourceManager.GetFormattedStringByCurrentCulture(nameof(ExceptionMessages.NotSemanticFunction), skFunction.Name)); + : throw new FileNotFoundException(ExceptionMessages.ResourceManager.GetFormattedStringByCurrentCulture(nameof(ExceptionMessages.PromptFileNotFound), skFunction.Name, skFunction.SkillName, functionPluginDirectory)); } /// /// Generates the final prompt for a given semantic function from embedded resources in an assembly, using the context variables. /// - /// - /// The parameter must be a semantic function (i.e., the value of the property must - /// be , otherwise an . - /// will be thrown. - /// /// The to work with. /// The semantic function representation. /// The assembly containing the embedded resources that represents and configures the semantic function. /// A collection of context variables. /// A cancellation token that can be used to receive notice of cancellation. /// A string containing the generated prompt. - /// - /// If the parameter is not a semantic function (i.e., the value of the property is . - /// will be thrown. - /// public static async Task GetSemanticFunctionPromptAsync(this IKernel kernel, ISKFunction skFunction, Assembly assembly, IDictionary contextVariables, CancellationToken cancellationToken) { - Guard.IsTrue(skFunction.IsSemantic, ExceptionMessages.ResourceManager.GetFormattedStringByCurrentCulture(nameof(ExceptionMessages.NotSemanticFunction), skFunction.Name)); - var kernelContext = kernel.CreateNewContext(); foreach (var (key, value) in contextVariables) @@ -82,47 +59,43 @@ public static async Task GetSemanticFunctionPromptAsync(this IKernel ker kernelContext.Variables[key] = value; } - var resourceName = assembly.GetManifestResourceNames() - .SingleOrDefault(resourceName => resourceName.IndexOf($"{skFunction.SkillName}.{skFunction.Name}", StringComparison.OrdinalIgnoreCase) != -1 - && resourceName.EndsWith(Constants.PromptFile, StringComparison.OrdinalIgnoreCase)); + var resourceNames = assembly.GetManifestResourceNames() + .Where(resourceName => resourceName.IndexOf($"{skFunction.SkillName}.{skFunction.Name}", StringComparison.OrdinalIgnoreCase) != -1) + .ToList(); // Enumerate here to improve performance. + + var promptConfigurationResourceName = resourceNames.SingleOrDefault(resourceName => resourceName.EndsWith(Constants.ConfigFile, StringComparison.OrdinalIgnoreCase)); + var promptTemplateResourceName = resourceNames.SingleOrDefault(resourceName => resourceName.EndsWith(Constants.PromptFile, StringComparison.OrdinalIgnoreCase)); + + if (string.IsNullOrEmpty(promptConfigurationResourceName) || string.IsNullOrEmpty(promptTemplateResourceName)) + { + return null; + } + + // TODO : Check this once the final version of Semantic Kernel is released (it seems that it will be changed by `KernelPromptTemplateFactory`)... + var promptTemplateConfig = PromptTemplateConfig.FromJson(await ReadResourceAsync(assembly, promptConfigurationResourceName)); + var promptTemplate = new BasicPromptTemplateFactory(kernel.LoggerFactory).Create(await ReadResourceAsync(assembly, promptTemplateResourceName), promptTemplateConfig); - return await kernel.PromptTemplateEngine.RenderAsync(await ReadResourceAsync(assembly, resourceName), kernelContext, cancellationToken); + return await promptTemplate.RenderAsync(kernelContext, cancellationToken); } /// /// Calculates the current total number of tokens used in generating a prompt of a given semantic function in a directory located plugin, and using the context variables. /// - /// - /// The parameter must be a semantic function (i.e., the value of the property must - /// be , otherwise an . - /// will be thrown. - /// /// The to work with. /// The semantic function representation. - /// The directory containing the plugin and the files that represens and configures the semantic function. + /// The directory containing the plugin and the files that represents and configures the semantic function. /// A collection of context variables. /// A function to calculate length of a string in tokens.. /// A cancellation token that can be used to receive notice of cancellation. /// The total number of tokens used plus the maximum allowed response tokens specified in the function. - /// - /// If the parameter is not a semantic function (i.e., the value of the property is . - /// will be thrown. - /// public static async Task GetSemanticFunctionUsedTokensAsync(this IKernel kernel, ISKFunction skFunction, string functionPluginDirectory, IDictionary contextVariables, Func tokenLengthFunction, CancellationToken cancellationToken) { - Guard.IsTrue(skFunction.IsSemantic, ExceptionMessages.ResourceManager.GetFormattedStringByCurrentCulture(nameof(ExceptionMessages.NotSemanticFunction), skFunction.Name)); - - return tokenLengthFunction(await kernel.GetSemanticFunctionPromptAsync(skFunction, functionPluginDirectory, contextVariables, cancellationToken)) + (skFunction.RequestSettings.MaxTokens ?? 0); + return tokenLengthFunction(await kernel.GetSemanticFunctionPromptAsync(skFunction, functionPluginDirectory, contextVariables, cancellationToken)) + GetMaxTokensFrom(skFunction); } /// /// Calculates the current total number of tokens used in generating a prompt of a given semantic function from embedded resources in an assembly, using the context variables. /// - /// - /// The parameter must be a semantic function (i.e., the value of the property must - /// be , otherwise an . - /// will be thrown. - /// /// The to work with. /// The semantic function representation. /// The assembly containing the embedded resources that represents and configures the semantic function. @@ -130,15 +103,9 @@ public static async Task GetSemanticFunctionUsedTokensAsync(this IKernel ke /// A function to calculate length of a string in tokens.. /// A cancellation token that can be used to receive notice of cancellation. /// The total number of tokens used plus the maximum allowed response tokens specified in the function. - /// - /// If the parameter is not a semantic function (i.e., the value of the property is . - /// will be thrown. - /// public static async Task GetSemanticFunctionUsedTokensAsync(this IKernel kernel, ISKFunction skFunction, Assembly assembly, IDictionary contextVariables, Func tokenLengthFunction, CancellationToken cancellationToken) { - Guard.IsTrue(skFunction.IsSemantic, ExceptionMessages.ResourceManager.GetFormattedStringByCurrentCulture(nameof(ExceptionMessages.NotSemanticFunction), skFunction.Name)); - - return tokenLengthFunction(await kernel.GetSemanticFunctionPromptAsync(skFunction, assembly, contextVariables, cancellationToken)) + (skFunction.RequestSettings.MaxTokens ?? 0); + return tokenLengthFunction(await kernel.GetSemanticFunctionPromptAsync(skFunction, assembly, contextVariables, cancellationToken)) + GetMaxTokensFrom(skFunction); } /// @@ -164,13 +131,13 @@ public static IDictionary ImportSemanticPluginsFromAssembly // Example: «xxxx.yyyyy.zzzzz.[SkillName].[FunctionName].config.json» and «xxxx.yyyyy.zzzzz.[SkillName].[FunctionName].skprompt.txt» return new { - FileName = $@"{resourceNameTokens[^2]}.{resourceNameTokens[^1]}", // The file name and its extension are the last two tokens (first and second positon from the end). + FileName = $@"{resourceNameTokens[^2]}.{resourceNameTokens[^1]}", // The file name and its extension are the last two tokens (first and second position from the end). FunctionName = resourceNameTokens[^3], // Next always comes the name of the function, which is in the third position from the end. PluginName = resourceNameTokens[^4], // Finally comes the name of the plugin, which is in the fourth position from the end. ResourceName = resourceName, }; }) - .GroupBy(x => (x.PluginName, x.FunctionName), x => (x.ResourceName, x.FileName)) // Group by skill and function names to get all the resources (prompt and configuratio) for each function. + .GroupBy(x => (x.PluginName, x.FunctionName), x => (x.ResourceName, x.FileName)) // Group by skill and function names to get all the resources (prompt and configuration) for each function. ; foreach (var pluginsInfoGroup in pluginsInfoGroups) @@ -180,18 +147,22 @@ public static IDictionary ImportSemanticPluginsFromAssembly var promptTemplateConfig = PromptTemplateConfig.FromJson(ReadResource(assembly, functionConfigResourceName)); - var promptTemplate = new PromptTemplate(ReadResource(assembly, functionPromptResourceName), promptTemplateConfig, kernel.PromptTemplateEngine); - - var functionConfig = new SemanticFunctionConfig(promptTemplateConfig, promptTemplate); + // TODO : Check this once the final version of Semantic Kernel is released (it seems that it will be changed by `KernelPromptTemplateFactory`)... + var promptTemplate = new BasicPromptTemplateFactory(kernel.LoggerFactory).Create(ReadResource(assembly, functionPromptResourceName), promptTemplateConfig); var (pluginName, functionName) = pluginsInfoGroup.Key; - plugins[functionName] = kernel.RegisterSemanticFunction(pluginName, functionName, functionConfig); + plugins[functionName] = kernel.RegisterSemanticFunction(pluginName, functionName, promptTemplateConfig, promptTemplate); } return plugins; } + private static int GetMaxTokensFrom(ISKFunction sKFunction) + { + return sKFunction.RequestSettings.ExtensionData.TryGetValue(@"max_tokens", out var maxTokensObj) && maxTokensObj is JsonElement maxTokensElement && maxTokensElement.TryGetInt32(out var value) ? value : 0; + } + private static string ReadResource(Assembly assembly, string resourceName) { using var stream = assembly.GetManifestResourceStream(resourceName); diff --git a/src/Encamina.Enmarcha.SemanticKernel/Extensions/Resources/ExceptionMessages.Designer.cs b/src/Encamina.Enmarcha.SemanticKernel/Extensions/Resources/ExceptionMessages.Designer.cs index 4a6e5fb..49f68ad 100644 --- a/src/Encamina.Enmarcha.SemanticKernel/Extensions/Resources/ExceptionMessages.Designer.cs +++ b/src/Encamina.Enmarcha.SemanticKernel/Extensions/Resources/ExceptionMessages.Designer.cs @@ -61,16 +61,7 @@ internal ExceptionMessages() { } /// - /// Looks up a localized string similar to Function '{0}' is not semantic function!. - /// - internal static string NotSemanticFunction { - get { - return ResourceManager.GetString("NotSemanticFunction", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Prompt file ('skprompt.txt') for function '{0}' from plug-in '{0} not found at '{templatePath}'!. + /// Looks up a localized string similar to Prompt file ('skprompt.txt') for function '{function}' from plug-in '{plugin} not found at '{templatePath}'!. /// internal static string PromptFileNotFound { get { diff --git a/src/Encamina.Enmarcha.SemanticKernel/Extensions/Resources/ExceptionMessages.resx b/src/Encamina.Enmarcha.SemanticKernel/Extensions/Resources/ExceptionMessages.resx index 3e4b909..3426895 100644 --- a/src/Encamina.Enmarcha.SemanticKernel/Extensions/Resources/ExceptionMessages.resx +++ b/src/Encamina.Enmarcha.SemanticKernel/Extensions/Resources/ExceptionMessages.resx @@ -117,10 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Function '{0}' is not semantic function! - - Prompt file ('skprompt.txt') for function '{0}' from plug-in '{0} not found at '{templatePath}'! + Prompt file ('skprompt.txt') for function '{function}' from plug-in '{plugin} not found at '{templatePath}'! \ No newline at end of file diff --git a/src/Encamina.Enmarcha.SemanticKernel/MemoryManager.cs b/src/Encamina.Enmarcha.SemanticKernel/MemoryManager.cs index 354effa..42f7817 100644 --- a/src/Encamina.Enmarcha.SemanticKernel/MemoryManager.cs +++ b/src/Encamina.Enmarcha.SemanticKernel/MemoryManager.cs @@ -1,4 +1,6 @@ -using System.Collections.ObjectModel; +// Ignore Spelling: Upsert + +using System.Collections.ObjectModel; using System.Runtime.CompilerServices; using System.Text.Json; @@ -26,14 +28,14 @@ public class MemoryManager : IMemoryManager /// Initializes a new instance of the class. /// /// - /// A valid instance of , used to get the configured text embeddingfs generation service () required by this manager. + /// A valid instance of , used to get the configured text embeddings generation service () required by this manager. /// /// A valid instance of a to manage. public MemoryManager(IKernel kernel, IMemoryStore memoryStore) { textEmbeddingGeneration = kernel.GetService(); // If the service is not configured, a `KernelException` is thrown... - this.logger = kernel.Logger; + this.logger = kernel.LoggerFactory.CreateLogger(); this.memoryStore = memoryStore; }