#r "nuget: Microsoft.SemanticKernel, 1.0.0-beta1"
#!import config/Settings.cs
#!import config/Utils.cs
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Plugins.Core;
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.Planning;
using Microsoft.SemanticKernel.Planners;
using Microsoft.SemanticKernel.Connectors.AI.OpenAI;
var builder = new KernelBuilder();
// Configure AI backend used by the kernel
var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();
if (useAzureOpenAI)
builder.WithAzureChatCompletionService(model, azureEndpoint, apiKey);
else
builder.WithOpenAIChatCompletionService(model, apiKey, orgId);
var kernel = builder.Build();
The planner is located in the Microsoft.SemanticKernel.Planners.Core
package and requires Orchestration
// Load native plugin into the kernel registry, sharing its functions with prompt templates
var planner = new SequentialPlanner(kernel);
The planner needs to know what plugins are available to it. Here we'll give it access to the SummarizePlugin
and WriterPlugin
we have defined on disk.
var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "..", "..", "samples", "plugins");
kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, "SummarizePlugin");
kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, "WriterPlugin");
Define your ASK. What do you want the Kernel to do?
var ask = "Tomorrow is Valentine's day. I need to come up with a few date ideas. My significant other likes poems so write them in the form of a poem.";
var originalPlan = await planner.CreatePlanAsync(ask);
Console.WriteLine("Original plan:\n");
Console.WriteLine(JsonSerializer.Serialize(originalPlan, new JsonSerializerOptions { WriteIndented = true }));
As you can see in the above plan, the Planner has taken the user's ask and converted it into a Plan object detailing how the AI would go about solving this task.
It makes use of the plugins that the Kernel has available to it and determines which functions to call in order to fulfill the user's ask.
The output of each step of the plan gets set as setContextVariable
which makes it available as input
to the next plugin.
Let's also define an inline plugin and have it be available to the Planner. Be sure to give it a function name and plugin name.
string skPrompt = """
{{$input}}
Rewrite the above in the style of Shakespeare.
""";
var shakespeareFunction = kernel.CreateSemanticFunction(skPrompt, "Shakespeare", "ShakespearePlugin", requestSettings: new OpenAIRequestSettings { MaxTokens = 2000, Temperature = 0.2, TopP = 0.5 });
Let's update our ask using this new plugin.
var ask = @"Tomorrow is Valentine's day. I need to come up with a few date ideas.
She likes Shakespeare so write using his style. Write them in the form of a poem.";
var newPlan = await planner.CreatePlanAsync(ask);
Console.WriteLine("Updated plan:\n");
Console.WriteLine(JsonSerializer.Serialize(newPlan, new JsonSerializerOptions { WriteIndented = true }));
Now that we have different plans, let's try to execute them! The Kernel can execute the plan using RunAsync.
var originalPlanResult = await kernel.RunAsync(originalPlan);
Console.WriteLine("Original Plan results:\n");
Console.WriteLine(Utils.WordWrap(originalPlanResult.GetValue<string>(), 100));
Now lets execute and print the new plan:
var newPlanResult = await kernel.RunAsync(newPlan);
Console.WriteLine("New Plan results:\n");
Console.WriteLine(newPlanResult.GetValue<string>());