In modern AI applications, "memory" is what differentiates a static completion from a dynamic conversation. In the Semantic Kernel (SK) ecosystem, this memory is managed through the ChatHistory class. Below is a complete, production-ready example of a Health & Fitness Assistant that utilizes short-term memory and multi-modal (image) processing.
using System.ComponentModel;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
// 1. Setup Kernel and OpenAI Connector
var apiKey = Environment.GetEnvironmentVariable("OPEN_AI_KEY");
if (string.IsNullOrEmpty(apiKey))
{
Console.WriteLine("Please set the OPEN_AI_KEY environment variable.");
return;
}
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(
modelId: "gpt-4o",
apiKey: apiKey)
.Build();
// 2. Configure Execution Settings (Tool calling and Temperature)
var executionSettings = new OpenAIPromptExecutionSettings
{
Temperature = 0.1,
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};
var chat = kernel.GetRequiredService<IChatCompletionService>();
// 3. Define the System Persona
var systemPrompt = """
You are a professional health and fitness assistant specializing in nutrition analysis.
When analyzing meal photos, provide:
1. Estimated calorie count
2. Macronutrients breakdown (protein, carbs, fats)
3. Health rating (1-10)
4. Brief recommendations for improvement
Keep responses concise and practical.
""";
// 4. Initialize Chat History with pre-seeded messages
List<ChatMessageContent> messages =
[
new(AuthorRole.System, systemPrompt),
new(AuthorRole.User, "I want to track my daily calorie intake. What's my total so far?"),
new(AuthorRole.Assistant,
"Currently, I don't have any meals logged. Please share a photo of your meal or describe what you've eaten today."),
];
var history = new ChatHistory(messages);
Console.WriteLine("=== Health & Fitness Assistant ===");
Console.WriteLine("Track your meals, analyze nutrition, and get fitness advice.");
Console.WriteLine("Commands:");
Console.WriteLine(" - Type 'meal' to analyze a sample meal photo");
Console.WriteLine(" - Ask about nutrition, calories, or fitness tips");
Console.WriteLine(" - Type 'exit' or press Enter to quit.\n");
// 5. Main Interaction Loop
while (true)
{
Console.Write(" User >>> ");
var prompt = Console.ReadLine();
if (string.IsNullOrEmpty(prompt) || prompt.ToLower() == "exit") break;
if (prompt.ToLower() == "meal")
{
// Adding multi-modal content (Text + Image) to history
history.AddMessage(AuthorRole.User,
[
new TextContent("Can you analyze this meal? Tell me the estimated calories, macronutrients, and if it's healthy."),
new ImageContent(new Uri("https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=800"))
]);
Console.WriteLine("\n[Analyzing meal photo...]");
}
else
{
history.AddUserMessage(prompt);
}
Console.Write(" Bot >>> ");
string fullMessage = string.Empty;
// 6. Streaming the AI response back to the console
await foreach (var token in chat.GetStreamingChatMessageContentsAsync(history, executionSettings, kernel))
{
Console.Write(token.Content);
fullMessage += token.Content;
}
Console.WriteLine("\n");
// 7. Critical Step: Save the Assistant's response to history to maintain context
history.AddAssistantMessage(fullMessage);
}
// 8. Display History Summary
Console.WriteLine("\n=== Chat History Summary ===");
foreach (var chatMessage in history)
{
Console.WriteLine($"\n{chatMessage.Role}:");
if (chatMessage.Items.Count > 1)
{
foreach (var item in chatMessage.Items)
{
if (item is TextContent textContent)
{
Console.WriteLine($" [Text] {textContent.Text}");
}
else if (item is ImageContent imageContent)
{
Console.WriteLine($" [Image] {imageContent.Uri}");
}
}
}
else
{
Console.WriteLine($" {chatMessage.Content}");
}
}