How I Taught ChatGPT to Read the Clock: Introducing Semantic Kernel

Oliver Scheer
medialesson
Published in
4 min readApr 25, 2024

This article is a guide to developing your first semantic kernel app using dotnet and C#, enabling you to add dynamic features to your AI solution.

Challenge and Problem Statement

A common limitation of AI models is their static nature. For instance, when asked “Is the queen still alive?” ChatGPT might respond affirmatively based on outdated information. Such models struggle with dynamically changing information and complex calculations not readily available in public documents.

What Time Is It?

Ever wondered why ChatGPT can’t provide the current date and time? As a text-generating engine, it relies on predictions from existing data. Attempting to ask for the current date, time, or day of the week yields no response.

Below is the initial version of my sample application with no additional plugins.

To enhance your AI solution’s intelligence, you can leverage the plugin feature of the open-source Semantic Kernel SDK. This enables you to write your own "features" for a large language model.

Requirements

To create your first semantic kernel plugin, I recommend using the latest version of dotnet and Visual Studio Code.

Additionally, you’ll need to install the Semantic Kernel SDK in your project with: dotnet add package Microsoft.SemanticKernel.

You’ll also need an existing Azure OpenAI Service in your Azure Tenant.

Code

The demo application is a basic console chat application offering only rudimentary mathematical and datetime calculation functions.

Configuration

Create a configuration file named appsetting.json, and include your model's name, endpoint, and key in the json.

{
"OpenAIEndpoint": "",
"OpenAPIKey": "",
"ModelName": ""
}

Plugin Code

Create a new file with the name DateTimePlugin.cs.

using Microsoft.SemanticKernel;
using System.ComponentModel;

namespace Oliver.AI.Samples.ChatGPTPlugin.Plugins
{
public sealed class DateTimePlugin
{
[KernelFunction, Description("What date is today?")]
public static DateTime GetDate()
{
return DateTime.Today;
}

[KernelFunction, Description("What day of week is today?")]
public static DayOfWeek GetDay()
{
return DateTime.Today.DayOfWeek;
}

[KernelFunction, Description("What time is it?")]
public static DateTime GetTime()
{
return DateTime.Now;
}
}
}

The Console Application Code

The magic to add the plugin to the existing ChatCompletionService is just s single line of code:

The complete code with the file name Program.cs.

using Microsoft.Extensions.Configuration;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Oliver.AI.Samples.ChatGPTPlugin.Plugins;

#region Configuration

// Read the condiguration from an appsettings.json file
// to avoid exploiting the API key and endpoint in a demo

var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", true)
.AddJsonFile("appsettings.Development.json", true)
.Build();

string endpoint = configuration["OpenAIEndpoint"] ?? "";
string modelName = configuration["ModelName"] ?? "";
string apiKey = configuration["OpenAPIKey"] ?? "";

#endregion

// Create kernel
IKernelBuilder builder = Kernel.CreateBuilder();

// Add a text or chat completion service using either:
builder.Services.AddAzureOpenAIChatCompletion(modelName, endpoint, apiKey);
builder.Plugins.AddFromType<MathPlugin>();
builder.Plugins.AddFromType<DateTimePlugin>();

Kernel kernel = builder.Build();

// Create chat history
ChatHistory history = [];

// Get chat completion service
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

Console.WriteLine("Olivers ChatGPT Plugins");
Console.WriteLine("-----------------------");
Console.WriteLine("Type 'exit' to quit the conversation");
Console.WriteLine();

// Start the conversation
while (true)
{
// Get user input
Console.Write("User > ");
string userInput = Console.ReadLine()!;
if (userInput.ToLower() == "exit")
{
break;
}
history.AddUserMessage(userInput);

// Enable auto function calling
OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
{
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};

// Get the response from the AI
var result = chatCompletionService.GetStreamingChatMessageContentsAsync(
history,
executionSettings: openAIPromptExecutionSettings,
kernel: kernel);

// Stream the results
string fullMessage = "";
var first = true;
await foreach (var content in result.ConfigureAwait(false))
{
if (content.Role.HasValue && first)
{
Console.Write("Assistant > ");
first = false;
}
Console.Write(content.Content);
fullMessage += content.Content;
}
Console.WriteLine();
Console.WriteLine();

// Add the message from the agent to the chat history
history.AddAssistantMessage(fullMessage);
}

Console.WriteLine("Goodbye!");

Running the Application

Run the application and ask some of the following questions:

  • Which day is today?
  • What time is it?
  • Which day of the week is today?
  • Welcher Wochentag ist heute?

Video

I’ve recorded a short video demonstrating this process, which I’ve posted on YouTube.

English Version | German Version

Conclusion

With the Semantic Kernel, you can create scenarios beyond simple questions. You can retrieve data from internal sources, engage in more intensive dialogs, and much more. Stay tuned for further developments.

You can find more information here.

Originally published at https://oliverscheer.net on April 25, 2024.

Oliver works as a Principal Software Engineer at Medialesson with a 25+ years record of software development experience in real and challenging customer projects. He used to work 17 years at Microsoft as Evangelist and Software Engineer. He is focusing on DevOps, Developer Experiences and Cloud. If you want to know more about him, you can visit his website or LinkedIn profile.

--

--