/* Copyright (c) Microsoft. All rights reserved. Example that demonstrates how to use Semantic Kernel in conjunction with dependency injection. Loads app configuration from: - appsettings.json. - appsettings.{Environment}.json. - Secret Manager when the app runs in the "Development" environment (set through the DOTNET_ENVIRONMENT variable). - Environment variables. - Command-line arguments. */ using HomeAutomation.Options; using HomeAutomation.Plugins; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.ChatCompletion; // For Azure OpenAI configuration #pragma warning disable IDE0005 // Using directive is unnecessary. using Microsoft.SemanticKernel.Connectors.OpenAI; namespace HomeAutomation; internal static class Program { internal static async Task Main(string[] args) { HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); builder.Configuration.AddUserSecrets(); // Actual code to execute is found in Worker class builder.Services.AddHostedService(); // Get configuration builder.Services.AddOptions() .Bind(builder.Configuration.GetSection(OpenAIOptions.SectionName)) .ValidateDataAnnotations() .ValidateOnStart(); /* Alternatively, you can use plain, Azure OpenAI after loading AzureOpenAIOptions instead of OpenAI builder.Services.AddOptions() .Bind(builder.Configuration.GetSection(AzureOpenAIOptions.SectionName)) .ValidateDataAnnotations() .ValidateOnStart(); */ // Chat completion service that kernels will use builder.Services.AddSingleton(sp => { OpenAIOptions openAIOptions = sp.GetRequiredService>().Value; // A custom HttpClient can be provided to this constructor return new OpenAIChatCompletionService(openAIOptions.ChatModelId, openAIOptions.ApiKey); /* Alternatively, you can use plain, Azure OpenAI after loading AzureOpenAIOptions instead of OpenAI options with builder.Services.AddOptions: AzureOpenAIOptions azureOpenAIOptions = sp.GetRequiredService>().Value; return new AzureOpenAIChatCompletionService(azureOpenAIOptions.ChatDeploymentName, azureOpenAIOptions.Endpoint, azureOpenAIOptions.ApiKey); */ }); // Add plugins that can be used by kernels // The plugins are added as singletons so that they can be used by multiple kernels builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddKeyedSingleton("OfficeLight"); builder.Services.AddKeyedSingleton("PorchLight", (sp, key) => { return new MyLightPlugin(turnedOn: true); }); /* To add an OpenAI or OpenAPI plugin, you need to be using Microsoft.SemanticKernel.Plugins.OpenApi. Then create a temporary kernel, use it to load the plugin and add it as keyed singleton. Kernel kernel = new(); KernelPlugin openAIPlugin = await kernel.ImportPluginFromOpenAIAsync("", new Uri("")); builder.Services.AddKeyedSingleton("MyImportedOpenAIPlugin", openAIPlugin); KernelPlugin openApiPlugin = await kernel.ImportPluginFromOpenApiAsync("", new Uri("")); builder.Services.AddKeyedSingleton("MyImportedOpenApiPlugin", openApiPlugin);*/ // Add a home automation kernel to the dependency injection container builder.Services.AddKeyedTransient("HomeAutomationKernel", (sp, key) => { // Create a collection of plugins that the kernel will use KernelPluginCollection pluginCollection = []; pluginCollection.AddFromObject(sp.GetRequiredService()); pluginCollection.AddFromObject(sp.GetRequiredService()); pluginCollection.AddFromObject(sp.GetRequiredKeyedService("OfficeLight"), "OfficeLight"); pluginCollection.AddFromObject(sp.GetRequiredKeyedService("PorchLight"), "PorchLight"); // When created by the dependency injection container, Semantic Kernel logging is included by default return new Kernel(sp, pluginCollection); }); using IHost host = builder.Build(); await host.RunAsync(); } }