Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Note
This document is not final and will get increasingly better!
This guide is intended to help you upgrade from a pre-v1 version of the .NET Semantic Kernel SDK to v1+.
The pre-v1 version used as a reference for this document was the 0.26.231009 version which was the last version before the first beta release where the majority of the changes started to happen.
Package Changes
As a result of many packages being redefined, removed and renamed, also considering that we did a good cleanup and namespace simplification many of our old packages needed to be renamed, deprecated and removed. The table below shows the changes in our packages.
All packages that start with Microsoft.SemanticKernel were truncated with a .. prefix for brevity.
| Previous Name | V1 Name | Version | Reason |
|---|---|---|---|
| ..Connectors.AI.HuggingFace | ..Connectors.HuggingFace | preview | |
| ..Connectors.AI.OpenAI | ..Connectors.OpenAI | v1 | |
| ..Connectors.AI.Oobabooga | MyIA.SemanticKernel.Connectors.AI.Oobabooga | alpha | Community driven connector ⚠️ Not ready for v1+ yet |
| ..Connectors.Memory.Kusto | ..Connectors.Kusto | alpha | |
| ..Connectors.Memory.DuckDB | ..Connectors.DuckDB | alpha | |
| ..Connectors.Memory.Pinecone | ..Connectors.Pinecone | alpha | |
| ..Connectors.Memory.Redis | ..Connectors.Redis | alpha | |
| ..Connectors.Memory.Qdrant | ..Connectors.Qdrant | alpha | |
| -- | ..Connectors.Postgres | alpha | |
| ..Connectors.Memory.AzureCognitiveSearch | ..Connectors.Memory.AzureAISearch | alpha | |
| ..Functions.Semantic | - Removed - | Merged in Core | |
| ..Reliability.Basic | - Removed - | Replaced by .NET Dependency Injection | |
| ..Reliability.Polly | - Removed - | Replaced by .NET Dependency Injection | |
| ..TemplateEngine.Basic | - Removed - | Merged in Core | |
| ..Planners.Core | ..Planners.OpenAI Planners.Handlebars |
preview | |
| -- | ..Experimental.Agents | alpha | |
| -- | ..Experimental.Orchestration.Flow | v1 |
Reliability Packages - Replaced by .NET Dependency Injection
The Reliability Basic and Polly packages now can be achieved using the .net dependency injection ConfigureHttpClientDefaults service collection extension to inject the desired resiliency policies to the HttpClient instances.
// Before
var retryConfig = new BasicRetryConfig
{
MaxRetryCount = 3,
UseExponentialBackoff = true,
};
retryConfig.RetryableStatusCodes.Add(HttpStatusCode.Unauthorized);
var kernel = new KernelBuilder().WithRetryBasic(retryConfig).Build();
// After
builder.Services.ConfigureHttpClientDefaults(c =>
{
// Use a standard resiliency policy, augmented to retry on 401 Unauthorized for this example
c.AddStandardResilienceHandler().Configure(o =>
{
o.Retry.ShouldHandle = args => ValueTask.FromResult(args.Outcome.Result?.StatusCode is HttpStatusCode.Unauthorized);
});
});
Package Removal and Changes Needed
Ensure that if you use any of the packages below you match the latest version that V1 uses:
| Package Name | Version |
|---|---|
| Microsoft.Extensions.Configuration | 8.0.0 |
| Microsoft.Extensions.Configuration.Binder | 8.0.0 |
| Microsoft.Extensions.Configuration.EnvironmentVariables | 8.0.0 |
| Microsoft.Extensions.Configuration.Json | 8.0.0 |
| Microsoft.Extensions.Configuration.UserSecrets | 8.0.0 |
| Microsoft.Extensions.DependencyInjection | 8.0.0 |
| Microsoft.Extensions.DependencyInjection.Abstractions | 8.0.0 |
| Microsoft.Extensions.Http | 8.0.0 |
| Microsoft.Extensions.Http.Resilience | 8.0.0 |
| Microsoft.Extensions.Logging | 8.0.0 |
| Microsoft.Extensions.Logging.Abstractions | 8.0.0 |
| Microsoft.Extensions.Logging.Console | 8.0.0 |
Convention Name Changes
Many of our internal naming conventions were changed to better reflect how the AI community names things. As OpenAI started the massive shift and terms like Prompt, Plugins, Models, RAG were taking shape it was clear that we needed to align with those terms to make it easier for the community to understand use the SDK.
| Previous Name | V1 Name |
|---|---|
| Semantic Function | Prompt Function |
| Native Function | Method Function |
| Context Variable | Kernel Argument |
| Request Settings | Prompt Execution Settings |
| Text Completion | Text Generation |
| Image Generation | Text to Image |
| Skill | Plugin |
Code Name Changes
Following the convention name changes, many of the code names were also changed to better reflect the new naming conventions. Abbreviations were also removed to make the code more readable.
| Previous Name | V1 Name |
|---|---|
| ContextVariables | KernelArguments |
| ContextVariables.Set | KernelArguments.Add |
| IImageGenerationService | ITextToImageService |
| ITextCompletionService | ITextGenerationService |
| Kernel.CreateSemanticFunction | Kernel.CreateFunctionFromPrompt |
| Kernel.ImportFunctions | Kernel.ImportPluginFrom____ |
| Kernel.ImportSemanticFunctionsFromDirectory | Kernel.ImportPluginFromPromptDirectory |
| Kernel.RunAsync | Kernel.InvokeAsync |
| NativeFunction | MethodFunction |
| OpenAIRequestSettings | OpenAIPromptExecutionSettings |
| RequestSettings | PromptExecutionSettings |
| SKException | KernelException |
| SKFunction | KernelFunction |
| SKFunctionMetadata | KernelFunctionAttribute |
| SKJsonSchema | KernelJsonSchema |
| SKParameterMetadata | KernelParameterMetadata |
| SKPluginCollection | KernelPluginCollection |
| SKReturnParameterMetadata | KernelReturnParameterMetadata |
| SemanticFunction | PromptFunction |
| SKContext | FunctionResult (output) |
Namespace Simplifications
The old namespaces before had a deep hierarchy matching 1:1 the directory names in the projects. This is a common practice but did mean that consumers of the Semantic Kernel packages had to add a lot of different using's in their code. We decided to reduce the number of namespaces in the Semantic Kernel packages so the majority of the functionality is in the main Microsoft.SemanticKernel namespace. See below for more details.
| Previous Name | V1 Name |
|---|---|
| Microsoft.SemanticKernel.Orchestration | Microsoft.SemanticKernel |
| Microsoft.SemanticKernel.Connectors.AI.* | Microsoft.SemanticKernel.Connectors.* |
| Microsoft.SemanticKernel.SemanticFunctions | Microsoft.SemanticKernel |
| Microsoft.SemanticKernel.Events | Microsoft.SemanticKernel |
| Microsoft.SemanticKernel.AI.* | Microsoft.SemanticKernel.* |
| Microsoft.SemanticKernel.Connectors.AI.OpenAI.* | Microsoft.SemanticKernel.Connectors.OpenAI |
| Microsoft.SemanticKernel.Connectors.AI.HuggingFace.* | Microsoft.SemanticKernel.Connectors.HuggingFace |
Kernel
The code to create and use a Kernel instance has been simplified. The IKernel interface has been eliminated as developers should not need to create their own Kernel implementation. The Kernel class represents a collection of services and plugins. The current Kernel instance is available everywhere which is consistent with the design philosophy behind the Semantic Kernel.
IKernelinterface was changed toKernelclass.Kernel.ImportFunctionswas removed and replaced byKernel.ImportPluginFrom____, where____can beFunctions,Object,PromptDirectory,Type,GrporOpenAIAsync, etc.// Before var textFunctions = kernel.ImportFunctions(new StaticTextPlugin(), "text"); // After var textFunctions = kernel.ImportPluginFromObject(new StaticTextPlugin(), "text");Kernel.RunAsyncwas removed and replaced byKernel.InvokeAsync. Order of parameters shifted, where function is the first.// Before KernelResult result = kernel.RunAsync(textFunctions["Uppercase"], "Hello World!"); // After FunctionResult result = kernel.InvokeAsync(textFunctions["Uppercase"], new() { ["input"] = "Hello World!" });Kernel.InvokeAsyncnow returns aFunctionResultinstead of aKernelResult.Kernel.InvokeAsynconly targets one function per call as first parameter. Pipelining is not supported, use the Example 60 to achieve a chaining behavior.❌ Not supported
KernelResult result = await kernel.RunAsync(" Hello World! ", textFunctions["TrimStart"], textFunctions["TrimEnd"], textFunctions["Uppercase"]);✔️ One function per call
var trimStartResult = await kernel.InvokeAsync(textFunctions["TrimStart"], new() { ["input"] = " Hello World! " }); var trimEndResult = await kernel.InvokeAsync(textFunctions["TrimEnd"], new() { ["input"] = trimStartResult.GetValue<string>() }); var finalResult = await kernel.InvokeAsync(textFunctions["Uppercase"], new() { ["input"] = trimEndResult.GetValue<string>() });✔️ Chaining using plugin Kernel injection
// Plugin using Kernel injection public class MyTextPlugin { [KernelFunction] public async Task<string> Chain(Kernel kernel, string input) { var trimStartResult = await kernel.InvokeAsync("textFunctions", "TrimStart", new() { ["input"] = input }); var trimEndResult = await kernel.InvokeAsync("textFunctions", "TrimEnd", new() { ["input"] = trimStartResult.GetValue<string>() }); var finalResult = await kernel.InvokeAsync("textFunctions", "Uppercase", new() { ["input"] = trimEndResult.GetValue<string>() }); return finalResult.GetValue<string>(); } } var plugin = kernel.ImportPluginFromObject(new MyTextPlugin(), "textFunctions"); var finalResult = await kernel.InvokeAsync(plugin["Chain"], new() { ["input"] = " Hello World! "});Kernel.InvokeAsyncdoes not accept string as input anymore, use aKernelArgumentsinstance instead. The function now is the first argument and the input argument needs to be provided as aKernelArgumentsinstance.// Before var result = await kernel.RunAsync("I missed the F1 final race", excuseFunction); // After var result = await kernel.InvokeAsync(excuseFunction, new() { ["input"] = "I missed the F1 final race" });Kernel.ImportSemanticFunctionsFromDirectorywas removed and replaced byKernel.ImportPluginFromPromptDirectory.Kernel.CreateSemanticFunctionwas removed and replaced byKernel.CreateFunctionFromPrompt.- Arguments:
OpenAIRequestSettingsis nowOpenAIPromptExecutionSettings
- Arguments:
Context Variables
ContextVariables was redefined asKernelArguments and is now a dictionary, where the key is the name of the argument and the value is the value of the argument. Methods like Set and Get were removed and the common dictionary Add or the indexer [] to set and get values should be used instead.
// Before
var variables = new ContextVariables("Today is: ");
variables.Set("day", DateTimeOffset.Now.ToString("dddd", CultureInfo.CurrentCulture));
// After
var arguments = new KernelArguments() {
["input"] = "Today is: ",
["day"] = DateTimeOffset.Now.ToString("dddd", CultureInfo.CurrentCulture)
};
// Initialize directly or use the dictionary indexer below
arguments["day"] = DateTimeOffset.Now.ToString("dddd", CultureInfo.CurrentCulture);
Kernel Builder
Many changes were made to our KernelBuilder to make it more intuitive and easier to use, as well as to make it simpler and more aligned with the .NET builders approach.
Creating a
KernelBuildercan now be only created using theKernel.CreateBuilder()method.This change make it simpler and easier to use the KernelBuilder in any code-base ensuring one main way of using the builder instead of multiple ways that adds complexity and maintenance overhead.
// Before IKernel kernel = new KernelBuilder().Build(); // After var builder = Kernel.CreateBuilder().Build();KernelBuilder.With...was renamed toKernelBuilder.Add...WithOpenAIChatCompletionServicewas renamed toAddOpenAIChatCompletionServiceWithAIService<ITextCompletion>
KernelBuilder.WithLoggerFactoryis not more used, instead use dependency injection approach to add the logger factory.IKernelBuilder builder = Kernel.CreateBuilder(); builder.Services.AddLogging(c => c.AddConsole().SetMinimumLevel(LogLevel.Information));WithAIService<T>Dependency InjectionPreviously the
KernelBuilderhad a methodWithAIService<T>that was removed and a newServiceCollection Servicesproperty is exposed to allow the developer to add services to the dependency injection container. i.e.:builder.Services.AddSingleton<ITextGenerationService>()
Kernel Result
As the Kernel became just a container for the plugins and now executes just one function there was not more need to have a KernelResult entity and all function invocations from Kernel now return a FunctionResult.
SKContext
After a lot of discussions and feedback internally and from the community, to simplify the API and make it more intuitive, the SKContext concept was diluted in different entities: KernelArguments for function inputs and FunctionResult for function outputs.
With the important decision to make Kernel a required argument of a function calling, the SKContext was removed and the KernelArguments and FunctionResult were introduced.
KernelArguments is a dictionary that holds the input arguments for the function invocation that were previously held in the SKContext.Variables property.
FunctionResult is the output of the Kernel.InvokeAsync method and holds the result of the function invocation that was previously held in the SKContext.Result property.
New Plugin Abstractions
- KernelPlugin Entity: Before V1 there was no concept of a plugin centric entity. This changed in V1 and for any function you add to a Kernel you will get a Plugin that it belongs to.
Plugins Immutability
Plugins are created by default as immutable by our out-of-the-box DefaultKernelPlugin implementation, which means that they cannot be modified or changed after creation.
Also attempting to import the plugins that share the same name in the kernel will give you a key violation exception.
The addition of the KernelPlugin abstraction allows dynamic implementations that may support mutability and we provided an example on how to implement a mutable plugin in the Example 69.
Combining multiple plugins into one
Attempting to create a plugin from directory and adding Method functions afterwards for the same plugin will not work unless you use another approach like creating both plugins separately and then combining them into a single plugin iterating over its functions to aggregate into the final plugin using kernel.ImportPluginFromFunctions("myAggregatePlugin", myAggregatedFunctions) extension.
Usage of Experimental Attribute Feature.
This features was introduced to mark some functionalities in V1 that we can possibly change or completely remove.
For mode details one the list of current released experimental features check here.
Prompt Configuration Files
Major changes were introduced to the Prompt Configuration files including default and multiple service/model configurations.
Other naming changes to note:
completionwas renamed toexecution_settingsinputwas renamed toinput_variablesdefaultValuewas renamed todefaultparameterswas renamed toinput_variables- Each property name in the
execution_settingsonce matched to theservice_idwill be used to configure the service/model execution settings. i.e.:// The "service1" execution settings will be used to configure the OpenAIChatCompletion service Kernel kernel = Kernel.CreateBuilder() .AddOpenAIChatCompletion(serviceId: "service1", modelId: "gpt-4")
Before
{
"schema": 1,
"description": "Given a text input, continue it with additional text.",
"type": "completion",
"completion": {
"max_tokens": 4000,
"temperature": 0.3,
"top_p": 0.5,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"input": {
"parameters": [
{
"name": "input",
"description": "The text to continue.",
"defaultValue": ""
}
]
}
}
After
{
"schema": 1,
"description": "Given a text input, continue it with additional text.",
"execution_settings": {
"default": {
"max_tokens": 4000,
"temperature": 0.3,
"top_p": 0.5,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"service1": {
"model_id": "gpt-4",
"max_tokens": 200,
"temperature": 0.2,
"top_p": 0.0,
"presence_penalty": 0.0,
"frequency_penalty": 0.0,
"stop_sequences": ["Human", "AI"]
},
"service2": {
"model_id": "gpt-3.5_turbo",
"max_tokens": 256,
"temperature": 0.3,
"top_p": 0.0,
"presence_penalty": 0.0,
"frequency_penalty": 0.0,
"stop_sequences": ["Human", "AI"]
}
},
"input_variables": [
{
"name": "input",
"description": "The text to continue.",
"default": ""
}
]
}