<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>2025-12 on Funky Si's Blog</title><link>https://www.funkysi1701.com/2025/12/</link><description>Recent content in 2025-12 on Funky Si's Blog</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><managingEditor>funkysi1701@gmail.com (Simon Foster)</managingEditor><webMaster>funkysi1701@gmail.com (Simon Foster)</webMaster><lastBuildDate>Fri, 12 Dec 2025 10:00:00 +0000</lastBuildDate><atom:link href="https://www.funkysi1701.com/2025/12/index.xml" rel="self" type="application/rss+xml"/><item><title>Creating a Festive Naughty or Nice Checker Using Semantic Kernel and .NET</title><link>https://www.funkysi1701.com/posts/2025/festive-naughty-or-nice-checker/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Fri, 12 Dec 2025 10:00:00 +0000</pubDate><guid>https://www.funkysi1701.com/posts/2025/festive-naughty-or-nice-checker/</guid><category term=".NET">.NET</category><category term="SemanticKernel">SemanticKernel</category><category term="AI">AI</category><category term="Christmas">Christmas</category><category term="festive">festive</category><category term="naughtyornice">naughtyornice</category><category term="C-Sharp">C-Sharp</category><category term="machinelearning">machinelearning</category><category term="tutorial">tutorial</category><media:content medium="image" type="image/png" url="https://www.funkysi1701.com/images/2025/festive-tech-calendar.png"/><description>&lt;p&gt;&lt;img class="img-fluid" alt="Festive Tech Calendar" src="https://www.funkysi1701.com/cdn-cgi/image/width=800,quality=75/images/2025/festive-tech-calendar.png" loading="lazy"
width="817" height="545"
/&gt;
&lt;/p&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;a class="anchor ms-1" href="#introduction" aria-label="Permalink: Introduction"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m excited to be taking part in this year&amp;rsquo;s &lt;a href="https://festivetechcalendar.com/" target="_blank" rel="noopener noreferrer"&gt;Festive Tech Calendar&lt;/a&gt;
, a community-driven advent calendar showcasing amazing technical content throughout December. Make sure to check out the other excellent posts created by developers from around the world!&lt;/p&gt;
&lt;p&gt;In this festive tutorial, we&amp;rsquo;ll build a fun &amp;ldquo;Naughty or Nice&amp;rdquo; checker using Microsoft&amp;rsquo;s Semantic Kernel and .NET. This playful AI-powered tool analyzes text descriptions and delivers a verdict on whether someone has been naughty or nice this year—perfect for adding some holiday cheer to your portfolio! Whether you&amp;rsquo;re new to AI integration or looking to explore Semantic Kernel, this beginner-friendly guide will walk you through creating a complete working application from scratch. By the end, you&amp;rsquo;ll have a deployable web app and understand how to integrate large language models into your .NET projects.&lt;/p&gt;
&lt;h2 id="my-take-on-ai"&gt;My Take on AI&lt;a class="anchor ms-1" href="#my-take-on-ai" aria-label="Permalink: My Take on AI"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before diving into code, I want to share a quick perspective on using AI in development. While building this demo, I used &lt;a href="https://github.com/copilot" target="_blank" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt;
to transform a basic UI into something more festive.&lt;/p&gt;
&lt;p&gt;Starting with a simple, functional interface:&lt;/p&gt;
&lt;p&gt;&lt;img class="img-fluid" alt="boring looking application" src="https://www.funkysi1701.com/cdn-cgi/image/width=800,quality=75/images/2025/before.png" loading="lazy"
width="1487" height="347"
/&gt;
&lt;/p&gt;
&lt;p&gt;After a few prompts to Copilot, I had a Christmas-themed demo with loading spinners and festive icons:&lt;/p&gt;
&lt;p&gt;&lt;img class="img-fluid" alt="Christmas version" src="https://www.funkysi1701.com/cdn-cgi/image/width=800,quality=75/images/2025/after.png" loading="lazy"
width="1128" height="432"
/&gt;
&lt;/p&gt;
&lt;p&gt;Could I have coded this myself? Absolutely. But I&amp;rsquo;d rather focus my energy on the backend Semantic Kernel integration than wrestling with CSS animations. &lt;strong&gt;This is where AI shines—handling the tedious parts so you can focus on the interesting problems.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="the-reality-check"&gt;The Reality Check&lt;a class="anchor ms-1" href="#the-reality-check" aria-label="Permalink: The Reality Check"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;That said, AI isn&amp;rsquo;t magic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hallucinations happen&lt;/strong&gt; - I&amp;rsquo;ve lost time chasing incorrect suggestions, so don&amp;rsquo;t retire your search engine just yet&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ownership questions remain&lt;/strong&gt; - Who owns AI-generated code? This is still being figured out&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It&amp;rsquo;s a tool, not a replacement&lt;/strong&gt; - AI augments developers; it doesn&amp;rsquo;t replace critical thinking&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My approach: Use AI as a productivity multiplier, but always verify, understand, and own what you ship.&lt;/p&gt;
&lt;h2 id="what-is-semantic-kernel"&gt;What is Semantic Kernel?&lt;a class="anchor ms-1" href="#what-is-semantic-kernel" aria-label="Permalink: What is Semantic Kernel?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Semantic Kernel is an open-source SDK from Microsoft that makes it easy to integrate AI models into your .NET applications. It allows you to use large language models (LLMs) for tasks like text analysis, summarization, and more.&lt;/p&gt;
&lt;h2 id="project-overview"&gt;Project Overview&lt;a class="anchor ms-1" href="#project-overview" aria-label="Permalink: Project Overview"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ll create a simple web app that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accepts a name or short description of someone&amp;rsquo;s behaviour&lt;/li&gt;
&lt;li&gt;Uses Semantic Kernel to analyze the input&lt;/li&gt;
&lt;li&gt;Returns a festive verdict: Naughty or Nice&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites&lt;a class="anchor ms-1" href="#prerequisites" aria-label="Permalink: Prerequisites"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;.NET 10 (I am not using any .NET 10 specific features so could probably be rewritten with older versions)&lt;/li&gt;
&lt;li&gt;Semantic Kernel (NuGet package)&lt;/li&gt;
&lt;li&gt;An OpenAI API key - ⚠️ &lt;strong&gt;Note&lt;/strong&gt;: API usage costs ~$0.01-0.05 per request&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="openai-and-costs"&gt;OpenAI and Costs&lt;a class="anchor ms-1" href="#openai-and-costs" aria-label="Permalink: OpenAI and Costs"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For this example I have used an OpenAI API Key. This is not free, however while writing this example I have only spent a few pounds in tokens. For more information about OpenAI head over to &lt;a href="https://platform.openai.com/" target="_blank" rel="noopener noreferrer"&gt;https://platform.openai.com/&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;For this reason I have not provided a live demo, (I don&amp;rsquo;t want you all using my API key), and no API keys are included in my example code.&lt;/p&gt;
&lt;h2 id="step-1-setting-up-the-project"&gt;Step 1: Setting Up the Project&lt;a class="anchor ms-1" href="#step-1-setting-up-the-project" aria-label="Permalink: Step 1: Setting Up the Project"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Create a new Blazor Web App:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dotnet new blazor -n NaughtyOrNiceChecker
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd NaughtyOrNiceChecker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Install the required NuGet packages: (Microsoft.SemanticKernel.Connectors.OpenAI Version 1.67.1 as I write this)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dotnet add package Microsoft.SemanticKernel.Connectors.OpenAI
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add your OpenAI configuration to appsettings.json:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;OpenAI&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;your-api-key-here&amp;#34;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// Head over to https://platform.openai.com/settings/organization/api-keys
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Model&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;gpt-5&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// I am using gpt-5 but feel free to experiment with other models
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;🔒 &lt;strong&gt;Security&lt;/strong&gt;: Never commit API keys to GitHub. Use user secrets or environment variables.&lt;/p&gt;
&lt;p&gt;The code for my project can be found on GitHub at &lt;a href="https://github.com/funkysi1701/FestiveTechCalendar2025" target="_blank" rel="noopener noreferrer"&gt;https://github.com/funkysi1701/FestiveTechCalendar2025&lt;/a&gt;
.&lt;/p&gt;
&lt;h2 id="step-2-integrate-semantic-kernel"&gt;Step 2: Integrate Semantic Kernel&lt;a class="anchor ms-1" href="#step-2-integrate-semantic-kernel" aria-label="Permalink: Step 2: Integrate Semantic Kernel"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Configure Semantic Kernel to use your LLM provider (OpenAI). In the &lt;code&gt;Program.cs&lt;/code&gt; file you will see the following code, this loads the OpenAI key and model from your &lt;code&gt;appsettings.json&lt;/code&gt; config file, and allows it to be used by Semantic Kernel.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; key = builder.Configuration.GetValue&amp;lt;&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&amp;gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;OpenAI:Key&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; model = builder.Configuration.GetValue&amp;lt;&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&amp;gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;OpenAI:Model&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (!&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;.IsNullOrEmpty(key))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; builder.Services.AddOpenAIChatCompletion(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; modelId: model ?? &lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ApplicationException(&lt;span style="color:#e6db74"&gt;&amp;#34;Missing OpenAI Config&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; apiKey: key
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;builder.Services.AddKernel();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="step-3-create-the-blazor-component"&gt;Step 3: Create the Blazor Component&lt;a class="anchor ms-1" href="#step-3-create-the-blazor-component" aria-label="Permalink: Step 3: Create the Blazor Component"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Create a new file &lt;code&gt;Components/Pages/NaughtyOrNice.razor&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@page &lt;span style="color:#e6db74"&gt;&amp;#34;/naughty-or-nice&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@inject Kernel _kernel
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@rendermode InteractiveServer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;PageTitle&amp;gt;Naughty or Nice Checker&amp;lt;/PageTitle&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;h3&amp;gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;🎅&lt;/span&gt; Naughty or Nice Checker&amp;lt;/h3&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;div class=&lt;span style="color:#e6db74"&gt;&amp;#34;card&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;div class=&lt;span style="color:#e6db74"&gt;&amp;#34;card-body&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;input @bind=&lt;span style="color:#e6db74"&gt;&amp;#34;input&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; placeholder=&lt;span style="color:#e6db74"&gt;&amp;#34;Describe their behavior...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; class=&lt;span style="color:#e6db74"&gt;&amp;#34;form-control mb-3&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;button @onclick=&lt;span style="color:#e6db74"&gt;&amp;#34;CheckStatus&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; class=&lt;span style="color:#e6db74"&gt;&amp;#34;btn btn-primary&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Check Status
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; @if (!&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;.IsNullOrEmpty(response))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;div class=&lt;span style="color:#e6db74"&gt;&amp;#34;alert alert-@alertClass mt-3&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;h4&amp;gt;@response&amp;lt;/h4&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@code {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; childsName = &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; response = &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; alertClass =&amp;gt; response == &lt;span style="color:#e6db74"&gt;&amp;#34;Naughty&amp;#34;&lt;/span&gt; ? &lt;span style="color:#e6db74"&gt;&amp;#34;danger&amp;#34;&lt;/span&gt; : &lt;span style="color:#e6db74"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; isLoading = &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; Task CheckStatus()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; isLoading = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; InvokeAsync(StateHasChanged);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response = &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;.Empty;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; input = (childsName).Trim();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;.IsNullOrEmpty(input))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; var cts = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; CancellationTokenSource(TimeSpan.FromSeconds(&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; prompt = &lt;span style="color:#e6db74"&gt;&amp;#34;You are Santa&amp;#39;s assistant. Given the child&amp;#39;s name or short description, &amp;#34;&lt;/span&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;decide if they are Naughty or Nice for Christmas. &amp;#34;&lt;/span&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Respond only with one word: Naughty or Nice. &amp;#34;&lt;/span&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;No punctuation, no explanation. Input: {{$input}}&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; classifyFunc = _kernel.CreateFunctionFromPrompt(prompt);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; aiResponse = &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; _kernel.InvokeAsync(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; classifyFunc,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; [&amp;#34;input&amp;#34;]&lt;/span&gt; = input
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cts.Token
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; text = aiResponse.GetValue&amp;lt;&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&amp;gt;()?.Trim();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Normalize and enforce strict output&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;.Equals(text, &lt;span style="color:#e6db74"&gt;&amp;#34;naughty&amp;#34;&lt;/span&gt;, StringComparison.OrdinalIgnoreCase))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response = &lt;span style="color:#e6db74"&gt;&amp;#34;Naughty&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;.Equals(text, &lt;span style="color:#e6db74"&gt;&amp;#34;nice&amp;#34;&lt;/span&gt;, StringComparison.OrdinalIgnoreCase))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response = &lt;span style="color:#e6db74"&gt;&amp;#34;Nice&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Fallback: default to Naughty to avoid leaking other content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response = &lt;span style="color:#e6db74"&gt;&amp;#34;Naughty&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;finally&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; isLoading = &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; InvokeAsync(StateHasChanged);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: The _kernel is injected automatically because we registered it in Program.cs with builder.Services.AddKernel().&lt;/p&gt;
&lt;h2 id="step-4-crafting-the-perfect-prompt"&gt;Step 4: Crafting the Perfect Prompt&lt;a class="anchor ms-1" href="#step-4-crafting-the-perfect-prompt" aria-label="Permalink: Step 4: Crafting the Perfect Prompt"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Getting AI to return exactly what you want requires iteration. I&amp;rsquo;ll walk you through my prompt engineering journey from verbose outputs to production-ready responses.&lt;/p&gt;
&lt;h3 id="iteration-1-too-verbose"&gt;Iteration 1: Too Verbose&lt;a class="anchor ms-1" href="#iteration-1-too-verbose" aria-label="Permalink: Iteration 1: Too Verbose"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; aiResponse = &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; _kernel.InvokePromptAsync(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;$&amp;#34;You are a tool to help Santa identify if children have been naughty or nice. &amp;#34;&lt;/span&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;$&amp;#34;Has {input} been naughty or nice this year?&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cancellationToken: cancellationToken.Token
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Santa&lt;/td&gt;
&lt;td&gt;Short answer: Nice. Why: - Spreads joy and generosity globally - Works hard with his team, treats elves and reindeer well - Answers letters and keeps promises (on-time deliveries) Minor demerits (lighthearted): - Excess cookie consumption - Occasional chimney soot prints Verdict: Firmly on the Nice List. Want a fun “Official Nice Report” for Santa you can share?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Darth Vader&lt;/td&gt;
&lt;td&gt;Not exactly a child, but Santa checks everyone. Darth Vader’s record this year includes Force-choking subordinates and aiding Imperial oppression—firmly Naughty. Mitigating note: he did protect his son and turn against the Emperor, which earns a small mercy. Final verdict: Naughty list (with a tiny redemption candy cane).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;James&lt;/td&gt;
&lt;td&gt;I don’t have access to Santa’s list or personal data, so I can’t say for sure about James. But I can help you decide with a quick Naughty/Nice check: Score each item: - Kind and helpful to family/classmates most of the time? (Yes +2, Sometimes +1, No 0) - Tells the truth and takes responsibility? (Yes +2, Sometimes +1, No 0) - Apologizes and makes things right after mistakes? (Yes +2, Sometimes +1, No 0) - Respects rules and others (no bullying or deliberate harm)? (Yes +2, Sometimes +1, No 0; deduct 2 if there’s repeated serious harm) - Does generous things (sharing, chores, helping the community)? (Yes +2, Sometimes +1, No 0) Totals: - 8–10: Nice List - 5–7: Mostly Nice (keep it up) - 2–4: Mixed (needs a December boost) - 0–1 or repeated serious harm: Naughty-for-now (with room to improve) If James needs a boost: make amends where needed, do one unprompted kindness or chore daily, be honest about mistakes right away, and share/donate something or help someone weekly. Share a few examples of James’s year and I’ll help you make the call.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skeletor&lt;/td&gt;
&lt;td&gt;Verdict: Naughty. Why: - Repeated attempts to conquer Eternia and seize Castle Grayskull - Habitual scheming, lying, and bullying his own minions - Frequent unleashing of dangerous magic on innocents Path back to the Nice List: - Call a truce with He-Man and protect Eternia for a season - Return stolen artifacts and undo harmful spells - Treat his minions fairly and do a few good deeds without expecting power in return&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This is far too wordy, I really just want a Naughty or Nice response.&lt;/p&gt;
&lt;h3 id="iteration-2-constraining-the-output"&gt;Iteration 2: Constraining the Output&lt;a class="anchor ms-1" href="#iteration-2-constraining-the-output" aria-label="Permalink: Iteration 2: Constraining the Output"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Then I tried:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; aiResponse = &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; _kernel.InvokePromptAsync(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;$&amp;#34;Given the following description, decide if the person is Naughty or Nice for Christmas. &amp;#34;&lt;/span&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;$&amp;#34;Respond only with &amp;#39;Naughty&amp;#39; or &amp;#39;Nice&amp;#39;. &amp;#34;&lt;/span&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;$&amp;#34;Description: {input}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cancellationToken: cancellationToken.Token
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Santa&lt;/td&gt;
&lt;td&gt;Nice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Darth Vader&lt;/td&gt;
&lt;td&gt;Naughty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;James&lt;/td&gt;
&lt;td&gt;Nice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skeletor&lt;/td&gt;
&lt;td&gt;Naughty&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This is better but every name I tried is giving me a Nice, so let&amp;rsquo;s see if we can try something a bit more clever. However if instead of only including a name, we include some naughty or nice actions we get some interesting results.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Santa delivered some presents&lt;/td&gt;
&lt;td&gt;Nice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Darth Vader destroyed Alderaan&lt;/td&gt;
&lt;td&gt;Naughty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;James tidied his room&lt;/td&gt;
&lt;td&gt;Nice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skeletor got cross with Evil Lynn&lt;/td&gt;
&lt;td&gt;Naughty&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="version-3-non-ai-approach-plugin-example"&gt;Version 3: Non-AI Approach (Plugin Example)&lt;a class="anchor ms-1" href="#version-3-non-ai-approach-plugin-example" aria-label="Permalink: Version 3: Non-AI Approach (Plugin Example)"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This version demonstrates Semantic Kernel&amp;rsquo;s plugin system without using AI. While it doesn&amp;rsquo;t actually help Santa (it just generates a hash-based result), it shows how you can integrate traditional .NET code into Semantic Kernel workflows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why show this?&lt;/strong&gt; To illustrate that Semantic Kernel isn&amp;rsquo;t just for AI—you can mix AI calls with regular code execution in the same pipeline.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; aiResponse = &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; _kernel.InvokeAsync(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pluginName,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;GenerateHash&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; KernelArguments
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; [&amp;#34;input&amp;#34;]&lt;/span&gt; = input
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This version invokes a semantic kernel plugin function called GenerateHash. The function itself is defined in a separate class with a KernelFunction attribute, it is really simple just generates a hash from the input string. This is just an example of how you can call .NET code from Semantic Kernel. The kernel function requires an extra line to wire up correctly I have placed this in the OnInitialized method.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; OnInitialized()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; rngPlugin = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ExamplePlugin();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; _kernel.ImportPluginFromObject(rngPlugin, pluginName);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ExamplePlugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; [KernelFunction]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; GenerateHash(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; input)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (input == &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ArgumentNullException(nameof(input));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; hash = input.GetHashCode();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; hash &amp;gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; ? &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; : &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="final-version-production-ready-implementation"&gt;Final Version: Production-Ready Implementation&lt;a class="anchor ms-1" href="#final-version-production-ready-implementation" aria-label="Permalink: Final Version: Production-Ready Implementation"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My last example is very similar to Version 2 but let&amp;rsquo;s have a look at it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; prompt = &lt;span style="color:#e6db74"&gt;&amp;#34;You are Santa&amp;#39;s assistant. Given the child&amp;#39;s name or short description, &amp;#34;&lt;/span&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;decide if they are Naughty or Nice for Christmas. Respond only with one word: Naughty or Nice. &amp;#34;&lt;/span&gt; +
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;No punctuation, no explanation. Input: {{$input}}&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; classifyFunc = _kernel.CreateFunctionFromPrompt(prompt);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; aiResponse = &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; _kernel.InvokeAsync(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; classifyFunc,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; [&amp;#34;input&amp;#34;]&lt;/span&gt; = input
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cancellationToken.Token
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we have a bit more error checking to make sure we have entered a valid string before calling OpenAI. This time we use the CreateFunctionFromPrompt method to pass in a prompt, we then invoke the prompt along with the string that has been entered.&lt;/p&gt;
&lt;p&gt;This time we check for naughty or nice in the response before returning that to the user, if neither is returned we return Naughty.&lt;/p&gt;
&lt;p&gt;This works quite well if we enter a more descriptive input.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Santa delivered some presents&lt;/td&gt;
&lt;td&gt;Nice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Darth Vader destroyed Alderaan&lt;/td&gt;
&lt;td&gt;Naughty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;James tidied his room&lt;/td&gt;
&lt;td&gt;Nice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skeletor got cross with Evil Lynn&lt;/td&gt;
&lt;td&gt;Naughty&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you can see if we describe the actions of someone we can categorize them as naughty or nice, which is basically what Santa does, so this tool should be a great help to him.&lt;/p&gt;
&lt;p&gt;&lt;img class="img-fluid" alt="Is Santa Naughty or Nice?" src="https://www.funkysi1701.com/cdn-cgi/image/width=800,quality=75/images/2025/working-naughty-nice.png" loading="lazy"
width="1169" height="618"
/&gt;
&lt;/p&gt;
&lt;h3 id="comparing-all-versions"&gt;Comparing All Versions&lt;a class="anchor ms-1" href="#comparing-all-versions" aria-label="Permalink: Comparing All Versions"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Open-ended prompt&lt;/td&gt;
&lt;td&gt;Rich explanations&lt;/td&gt;
&lt;td&gt;Too verbose&lt;/td&gt;
&lt;td&gt;Learning/debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Constrained output&lt;/td&gt;
&lt;td&gt;Concise&lt;/td&gt;
&lt;td&gt;Needs context&lt;/td&gt;
&lt;td&gt;Simple classifications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Hash-based (no AI)&lt;/td&gt;
&lt;td&gt;No API costs&lt;/td&gt;
&lt;td&gt;Not intelligent&lt;/td&gt;
&lt;td&gt;Plugin example only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Validated prompts&lt;/td&gt;
&lt;td&gt;Reliable, safe&lt;/td&gt;
&lt;td&gt;More code&lt;/td&gt;
&lt;td&gt;Production&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this tutorial, we built a festive AI-powered application using Semantic Kernel and .NET. Here&amp;rsquo;s what we accomplished:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Integrated OpenAI with Semantic Kernel in a Blazor app&lt;/li&gt;
&lt;li&gt;✅ Learned prompt engineering through iteration (4 versions!)&lt;/li&gt;
&lt;li&gt;✅ Implemented proper error handling and output validation&lt;/li&gt;
&lt;li&gt;✅ Created a fun, interactive holiday application&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have tried to highlight some of the different ways that you can use Semantic Kernel that you could use in your own projects. Some of my examples could be accomplished without the use of Semantic Kernel, for example randomly generating Naughty and Nice doesn&amp;rsquo;t need AI, however hopefully you can see that getting results from AI can then be augmented using traditional .NET code to execute other functions.&lt;/p&gt;
&lt;h3 id="key-takeaways"&gt;Key Takeaways&lt;a class="anchor ms-1" href="#key-takeaways" aria-label="Permalink: Key Takeaways"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prompt engineering matters&lt;/strong&gt; - Notice how Version 4&amp;rsquo;s explicit instructions produced better results&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validation is essential&lt;/strong&gt; - Always sanitize LLM outputs before displaying to users&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep it simple&lt;/strong&gt; - Complex doesn&amp;rsquo;t mean better (Version 3&amp;rsquo;s random approach was overkill)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="cost-considerations"&gt;Cost Considerations&lt;a class="anchor ms-1" href="#cost-considerations" aria-label="Permalink: Cost Considerations"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;During development, I spent only a few pounds on API tokens. For production:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use Azure OpenAI for predictable pricing&lt;/li&gt;
&lt;li&gt;Implement caching for common queries&lt;/li&gt;
&lt;li&gt;Set up rate limiting to prevent abuse&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="deployment-options"&gt;Deployment Options&lt;a class="anchor ms-1" href="#deployment-options" aria-label="Permalink: Deployment Options"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This Blazor app can be deployed to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Azure Static Web Apps&lt;/strong&gt; (free tier includes 2 custom domains)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure App Service&lt;/strong&gt; (full .NET hosting)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker containers&lt;/strong&gt; (run anywhere)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="next-steps"&gt;Next Steps&lt;a class="anchor ms-1" href="#next-steps" aria-label="Permalink: Next Steps"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Want to extend this project? Try:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add a database to track naughty/nice history&lt;/li&gt;
&lt;li&gt;Implement user authentication&lt;/li&gt;
&lt;li&gt;Deploy to Azure Static Web Apps&lt;/li&gt;
&lt;li&gt;Add more context (age, location) for better AI decisions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy coding and Merry Christmas! 🎄&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/semantic-kernel" target="_blank" rel="noopener noreferrer"&gt;Semantic Kernel GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/semantic-kernel/" target="_blank" rel="noopener noreferrer"&gt;Microsoft Semantic Kernel Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://platform.openai.com/docs/api-reference" target="_blank" rel="noopener noreferrer"&gt;OpenAI API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/ai-services/openai/" target="_blank" rel="noopener noreferrer"&gt;Azure OpenAI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>