Files
semantic-kernel/dotnet/samples/KernelSyntaxExamples/Example40_DIContainer.cs
T
Mark Wallace 562d73c6cf .Net: Extract template engine from Kernel.Core (#2562)
### Motivation and Context

1. Why is this change required? This is part of the work to extract
functionality from Semantic Kernel core prior to 1.0 release.
2. What problem does it solve? Provides a pattern to follow for
additional template engine implementations.
3. What scenario does it contribute to? Contributes to the goal of
reducing the Semantic Kernel core to focus on AI orchestration.
4. If it fixes an open issue, please link to the issue here.
https://github.com/microsoft/semantic-kernel/issues/2527

### Description

- Create new template engine project in the extensions folder
- Move template engine code from semantic kernel abstractions and core
- Refactor `IPromptTemplateEngine` so that it doesn't depend on details
of the default implementation
- Refactor `PromptTemplateEngine` to match the new interface definition
- Move template engine unit tests to the extensions unit tests project

### Contribution Checklist

- [x] The code builds clean without any errors or warnings
- [x] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [x] All unit tests pass, and I have added new tests where possible
- [x] I didn't break anyone 😄
2023-08-29 08:50:11 +00:00

134 lines
6.0 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.AI.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.AI.OpenAI.ChatCompletion;
using Microsoft.SemanticKernel.Memory;
using Microsoft.SemanticKernel.Services;
using Microsoft.SemanticKernel.SkillDefinition;
using Microsoft.SemanticKernel.TemplateEngine;
using Microsoft.SemanticKernel.TemplateEngine.Prompt;
using RepoUtils;
/**
* The following examples show how to use SK SDK in applications using DI/IoC containers.
*/
public static class Example40_DIContainer
{
public static async Task RunAsync()
{
await UseKernelInDIPowerAppAsync();
await UseKernelInDIPowerApp_AdvancedScenarioAsync();
}
/// <summary>
/// This example shows how to register a Kernel in a DI container using KernelBuilder instead of
/// registering its dependencies.
/// </summary>
private static async Task UseKernelInDIPowerAppAsync()
{
//Bootstrapping code that initializes the modules, components, and classes that applications use.
//For regular .NET applications, the bootstrapping code usually resides either in the Main method or very close to it.
//In ASP.NET Core applications, the bootstrapping code is typically located in the ConfigureServices method of the Startup class.
//Registering Kernel dependencies
var collection = new ServiceCollection();
collection.AddTransient<ILogger>((_) => ConsoleLogger.Logger);
//Registering Kernel
collection.AddTransient<IKernel>((serviceProvider) =>
{
return Kernel.Builder
.WithLoggerFactory(serviceProvider.GetRequiredService<LoggerFactory>())
.WithOpenAIChatCompletionService(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
.Build();
});
//Registering class that uses Kernel to execute a skill
collection.AddTransient<KernelClient>();
//Creating a service provider for resolving registered services
var serviceProvider = collection.BuildServiceProvider();
//If an application follows DI guidelines, the following line is unnecessary because DI will inject an instance of the KernelClient class to a class that references it.
//DI container guidelines - https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines#recommendations
var kernelClient = serviceProvider.GetRequiredService<KernelClient>();
//Execute the function
await kernelClient.SummarizeAsync("What's the tallest building in South America?");
}
/// <summary>
/// This example shows how to registered Kernel and all its dependencies in DI container.
/// </summary>
private static async Task UseKernelInDIPowerApp_AdvancedScenarioAsync()
{
//Bootstrapping code that initializes the modules, components, and classes that applications use.
//For regular .NET applications, the bootstrapping code usually resides either in the Main method or very close to it.
//In ASP.NET Core applications, the bootstrapping code is typically located in the ConfigureServices method of the Startup class.
//Registering AI services Kernel is going to use
var aiServicesCollection = new AIServiceCollection();
aiServicesCollection.SetService<IChatCompletion>(() => new AzureChatCompletion(TestConfiguration.OpenAI.ChatModelId,
TestConfiguration.AzureOpenAI.Endpoint,
TestConfiguration.AzureOpenAI.ApiKey));
//Registering Kernel dependencies
var collection = new ServiceCollection();
collection.AddTransient<ILogger>((_) => ConsoleLogger.Logger);
collection.AddTransient<KernelConfig>();
collection.AddTransient<ISkillCollection, SkillCollection>();
collection.AddTransient<IPromptTemplateEngine, PromptTemplateEngine>();
collection.AddTransient<ISemanticTextMemory>((_) => NullMemory.Instance);
collection.AddTransient<IAIServiceProvider>((_) => aiServicesCollection.Build()); //Registering AI service provider that is used by Kernel to resolve AI services runtime
//Registering Kernel
collection.AddTransient<IKernel, Kernel>();
//Registering class that uses Kernel to execute a skill
collection.AddTransient<KernelClient>();
//Creating a service provider for resolving registered services
var serviceProvider = collection.BuildServiceProvider();
//If an application follows DI guidelines, the following line is unnecessary because DI will inject an instance of the KernelClient class to a class that references it.
//DI container guidelines - https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines#recommendations
var kernelClient = serviceProvider.GetRequiredService<KernelClient>();
//Execute the function
await kernelClient.SummarizeAsync("What's the tallest building in South America?");
}
/// <summary>
/// Class that uses/references Kernel.
/// </summary>
#pragma warning disable CA1812 // Avoid uninstantiated internal classes
private sealed class KernelClient
#pragma warning restore CA1812 // Avoid uninstantiated internal classes
{
private readonly IKernel _kernel;
private readonly ILogger _logger;
public KernelClient(IKernel kernel, ILogger logger)
{
this._kernel = kernel;
this._logger = logger;
}
public async Task SummarizeAsync(string ask)
{
string folder = RepoFiles.SampleSkillsPath();
var sumSkill = this._kernel.ImportSemanticSkillFromDirectory(folder, "SummarizeSkill");
var result = await this._kernel.RunAsync(ask, sumSkill["Summarize"]);
this._logger.LogWarning("Result - {0}", result);
}
}
}