
Recent advances in AI, particularly large language models (LLMs), are transforming how software processes and reasons about data. Modern applications increasingly combine deterministic computation with LLM reasoning to analyze trends, detect anomalies, and generate insights at scale. Semantic Kernel orchestrates these AI components, integrating models, prompts, and functions into structured pipelines that work seamlessly with traditional code. For instance, in sales analytics, it enables automated data analysis, AI-powered forecasting, narrative trend interpretation, and visualization, all within a single coordinated system.
This issue explores the core concepts of Semantic Kernel and examines key parts of the code used in the sales analytics application, highlighting how deterministic computation and AI reasoning work together.
What Semantic Kernel Is
Semantic Kernel (SK) is an open source AI orchestration framework that integrates LLM reasoning into C# code. It treats prompts, functions, and workflows as first-class building blocks, allowing deterministic code and LLM reasoning to run together in a single orchestrated pipeline. The Kernel serves as the execution engine, and any model with a chat completion API can be plugged in. SK also supports plugins, planners, memory stores, and other extensions, providing a flexible and predictable way to combine traditional code with AI reasoning.
Why Semantic Kernel Matters for Real Applications
Real applications involve full workflows: loading data, running computations, detecting patterns, generating visuals, explaining results, and triggering next steps. Semantic Kernel is designed for these orchestrated sequences.
It removes duplicated prompts, centralizes model configuration, and allows models to be swapped without rewriting code. Steps can be composed or chained while deterministic logic stays deterministic and AI reasoning remains consistent. This produces a maintainable and debuggable execution flow suitable for enterprise-scale AI applications.
Deep Technical Dive
Now that we understand what Semantic Kernel provides conceptually, let's take a closer look at how it works in practice. This section covers Kernel setup, namespaces, services, abstractions, and the execution flow behind your application.
1. Kernel Construction
At the center of every Semantic Kernel–based system is the Kernel itself. It orchestrates all AI services, function libraries, plugins, planners, and optional memory providers. The helper class demonstrates the typical pattern of creating a single shared instance for the entire application:
public static class KernelProvider
{
private static Kernel? _kernel;
public static Kernel GetKernel()
{
if (_kernel != null) return _kernel;
var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion(
modelId: "deepseek/deepseek-r1-0528-qwen3-8b",
apiKey: "not-needed",
endpoint: new Uri("http://localhost:1234/v1")
);
_kernel = builder.Build();
return _kernel;
}
}This ensures all modules share the same configuration, model provider, and dependency injection container. It functions like a centralized service in ASP.NET Core but is optimized for AI-driven workflows.
Several namespaces participate in this setup, including:
- Microsoft.SemanticKernel, the core orchestration layer
- Microsoft.SemanticKernel.ChatCompletion, which defines LLM chat abstractions
- Microsoft.Extensions.DependencyInjection, which manages service resolution
Within these namespaces you'll see important classes such as Kernel, KernelBuilder, IChatCompletionService, and ChatHistory. Together they define how models are registered, how prompts are constructed, and how results flow back through your application.
The lifecycle is modular: create a builder, register model providers and optional plugins, build the Kernel, and retrieve services as needed. Once constructed, the Kernel serves as the execution engine for all LLM reasoning.
2. How Semantic Kernel Handles Chat Completion
Semantic Kernel provides a unified abstraction layer over LLM chat APIs. Instead of calling the provider directly, the application retrieves the SK-managed chat interface:
var chatService = kernel.GetRequiredService<IChatCompletionService>();This triggers several internal steps. The Kernel resolves the registered chat service, creates an execution context, and converts your ChatHistory into a provider-specific format. SK adapts system, user, assistant, and tool messages to the provider schema and issues the API call.
When the response returns, it is wrapped in a strongly typed ChatMessageContent object, ensuring consistent handling across providers. Core types like ChatHistory, ChatMessageContent, ChatRole, and IChatCompletionService shield your code from vendor-specific differences. ChatHistory supports multiple message types, keeping handling clean and structured while enabling rich conversational workflows.
The result is an architecture where deterministic logic and AI reasoning work together predictably, without scattering provider-specific code throughout your application.
How the Sales Analytics Application Uses SK
The application is built around four key modules:
- SalesDataLoader
- SalesTrendAnalyzer
- SalesChartGenerator
- SalesAnomalyDetector
Module 1: SalesDataLoader
This module is fully deterministic and loads raw data into a structured format. It reads a CSV file, parses each row, and constructs a list of SalesRecord objects:
public class SalesRecord
{
public string Date { get; set; } = string.Empty;
public decimal Sales { get; set; }
}The loader retrieves the CSV path, checks that the file exists, and then loads the sales data into memory:
public static class SalesDataLoader
{
public static async Task RunAsync()
{
string csvPath = SalesDataUtilities.GetCsvPath();
if (!SalesDataUtilities.CheckCsvExists(csvPath))
{
return;
}
var salesData = SalesDataUtilities.LoadSalesData(csvPath);
Console.WriteLine("Loaded Sales Data (First 5 records):");
Console.WriteLine("Date\t\tSales");
Console.WriteLine("----\t\t-----");
foreach (var record in salesData.Take(5))
{
Console.WriteLine($"{record.Date}\t{record.Sales:C}");
}
Console.WriteLine($"\nTotal records loaded: {salesData.Count}");
}
}There is no AI involvement at this stage. This module provides a reliable foundation for SK-powered components downstream.
Module 2: SalesTrendAnalyzer
Here, deterministic math meets LLM reasoning. It first computes totals, averages, and extremes:
var total = records.Sum(r => r.Sales);
var average = records.Average(r => r.Sales);
var max = records.Max(r => r.Sales);
var min = records.Min(r => r.Sales);The Kernel then orchestrates narrative interpretation:
var kernel = SemanticKernelHelper.GetKernel();
var chatService = kernel.GetRequiredService<IChatCompletionService>();
var chat = new ChatHistory();
chat.AddSystemMessage("You are a professional sales analyst. Analyze sales data, identify trends, calculate metrics, and provide insights clearly and concisely.");
chat.AddUserMessage($"Analyze this sales data: [{dataSummary}]. Total sales: {totalSales:C}, Average: {averageSales:C}, Max: {maxSales:C}, Min: {minSales:C}. Identify trends, peak periods, and provide business insights.");
var settings = new OpenAIPromptExecutionSettings
{
Temperature = 0.3,
MaxTokens = 1000
};
var response = await chatService.GetChatMessageContentAsync(chat, executionSettings: settings);
Console.WriteLine(result.Content);Please consider that:
- Temperature controls creativity and variability in the model's responses. A lower value (0.3) keeps the output more focused and deterministic, ideal for business reporting.
- MaxTokens limits the response length. Setting it to 1000 ensures the model can provide a detailed analysis without cutting off prematurely.
This approach combines precise calculations with human-like interpretation, coordinated cleanly by the Kernel.
Module 3: SalesChartGenerator
This module uses AI for forecasting and deterministic code for visualization. The prompt instructs the LLM to return predicted values:
chat.AddSystemMessage("You are a sales forecasting expert. Your ONLY goal is to output three comma-separated decimal sales numbers for the next three months. DO NOT include any introductory text, explanation, thoughts, currency symbols, or trailing punctuation. The output must be PURELY the three numbers separated by commas.");
var userMessage = $@"Historical Dates: [{dateContext}]
Historical Sales Amounts: [{salesAmounts}]
Based on this historical sales data, provide the next 3 months of sales.
OUTPUT FORMAT: <SALES_PREDICTIONS>NUMBER1,NUMBER2,NUMBER3</SALES_PREDICTIONS>
Please provide ONLY the content inside the <SALES_PREDICTIONS> tags.";
chat.AddUserMessage(userMessage);The model returns a comma separated list, which is parsed into decimals:
var values = result.Content.Split(',')
.Select(v => decimal.Parse(v.Trim()))
.ToList();Once the future values are available, the chart is produced using ScottPlot:
var plot = new ScottPlot.Plot(600, 400);
plot.AddScatter(historyMonths, salesHistory);
plot.AddScatter(predictionMonths, predictedSales);
plot.SaveFig("sales_chart.png");The Kernel provides prediction reasoning, while all computation and rendering remain deterministic. The resulting chart visualizes both the historical sales data and the AI-predicted values for the next three months.
Module 4: SalesAnomalyDetector
This module combines statistical anomaly detection with AI explanations. It computes mean and standard deviation:
var mean = sales.Average();
var stdev = Math.Sqrt(sales.Sum(s => Math.Pow((double)(s - mean), 2)) / sales.Count);Values that deviate significantly from the mean are collected as anomalies:
var anomalies = records
.Where(r => Math.Abs((double)(r.Sales - mean)) > 2 * stdev)
.ToList();Once the anomalies are identified, the model provides a natural language explanation of what might be happening:
chat.AddSystemMessage("You are a data analyst specializing in sales anomaly detection. Provide a detailed report on detected anomalies, including possible causes, impacts on business, and recommendations.");
chat.AddUserMessage($"Sales Data: [{dataSummary}]. Mean Sales: {mean:C}, Standard Deviation: {stdDev:F2}. Detected Anomalies: [{anomalySummary}]. Analyze these anomalies, explain potential reasons, assess business impact, and suggest actions.");This approach allows machine level detection to be paired with human like reasoning, giving both the precision of numeric methods and the interpretability of an expert explanation.
Architectural Benefits
The structure delivers clear advantages. Each module is independent, deterministic calculations remain deterministic, and AI is used only where it adds value. All prompts and model configurations flow through a single Kernel, allowing models to be replaced without changing code. This keeps the system maintainable, testable, and predictable. AI acts as a clean extension rather than scattered logic.
Opportunities for Future Expansion
Modules could be converted into Kernel plugins for improved modularity. Vector memory could enable semantic search across historical records. Automated PDF reporting could combine charts and AI summaries. A natural language query layer would allow flexible questions, and the SK Planner or tool calling could enable more advanced analytic workflows.
Final Notes
The sales analytics application showed how Semantic Kernel orchestrated a hybrid AI pipeline that included data loading, computation, LLM interpretation, forecasting, charting, and anomaly explanation. SK managed orchestration and prompting, while deterministic modules handled computation and visualization. The architecture was modular, predictable, and easy to evolve, reflecting SK's strength in blending traditional computation with AI reasoning.
Explore Semantic Kernel this week and run the Sales Analytics source code locally.
See you in the next issue.
Stay curious.
Join the Newsletter
Subscribe for AI engineering insights, system design strategies, and workflow tips.