├── .gitignore ├── Plugins ├── ShoppingPlugin │ └── GetGroceryList │ │ ├── skprompt.txt │ │ └── config.json ├── FoodPlugin │ └── GetRecipe │ │ ├── skprompt.txt │ │ └── config.json ├── CityPlugin │ ├── GetCity │ │ ├── skprompt.txt │ │ └── config.json │ └── GetCityIATACode │ │ ├── skprompt.txt │ │ └── config.json ├── FlightTrackerPlugin │ └── GetIATANameFunction │ │ ├── skprompt.txt │ │ └── config.json ├── GuessPlugin │ ├── GetRiddle │ │ ├── skprompt.txt │ │ └── config.json │ └── GuessWhat │ │ ├── skprompt.txt │ │ └── config.json └── ComplaintsPlugin │ ├── skprompt.txt │ └── config.json ├── Utilities.cs ├── README.md ├── Settings.cs └── semantickerneldemos.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | settings.json 2 | -------------------------------------------------------------------------------- /Plugins/ShoppingPlugin/GetGroceryList/skprompt.txt: -------------------------------------------------------------------------------- 1 | Generate a grocery list for {{$input}} -------------------------------------------------------------------------------- /Plugins/FoodPlugin/GetRecipe/skprompt.txt: -------------------------------------------------------------------------------- 1 | Generate a food recipe for a {{$input}} cuisine. -------------------------------------------------------------------------------- /Plugins/CityPlugin/GetCity/skprompt.txt: -------------------------------------------------------------------------------- 1 | Tell me a capital city of the country below. 2 | 3 | [COUNTRY] 4 | --------- 5 | {{$input}} 6 | -------------------------------------------------------------------------------- /Plugins/CityPlugin/GetCityIATACode/skprompt.txt: -------------------------------------------------------------------------------- 1 | Tell me the IATA Airport code for the city below. 2 | 3 | [CITY] 4 | --------- 5 | {{$input}} 6 | -------------------------------------------------------------------------------- /Plugins/FlightTrackerPlugin/GetIATANameFunction/skprompt.txt: -------------------------------------------------------------------------------- 1 | What's the IATA code of {{$input}}? Please provide just the code without any explanation. One word. 2 | -------------------------------------------------------------------------------- /Plugins/GuessPlugin/GetRiddle/skprompt.txt: -------------------------------------------------------------------------------- 1 | Ask a riddle with its answer in a below json format. 2 | 3 | ************************ 4 | FORMAT 5 | ************************ 6 | { 7 | "riddle": "", 8 | "answer": "" 9 | } 10 | 11 | -------------------------------------------------------------------------------- /Plugins/GuessPlugin/GuessWhat/skprompt.txt: -------------------------------------------------------------------------------- 1 | Select a well-known landmark in a big city within {{$input}}. 2 | Describe some facts about the history, tourism and culture of {{$input}}. 3 | Provide a brief description of no more than a paragraph. -------------------------------------------------------------------------------- /Plugins/GuessPlugin/GetRiddle/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": 1, 3 | "description": "Gets the riddle and its answer in a JSON format", 4 | "execution_settings": { 5 | "default": { 6 | "max_tokens": 200, 7 | "temperature": 0.8, 8 | "top_p": 0.0, 9 | "presence_penalty": 0.0, 10 | "frequency_penalty": 0.0 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Plugins/ComplaintsPlugin/skprompt.txt: -------------------------------------------------------------------------------- 1 | BE FRIENDLY. BE POLITE. BE PROFESSIONAL. 2 | APOLOGIES FOR THE INCONVENIENCE. 3 | 4 | ENSURE THAT THE PERSON FEELS HEARD ABOUT THEIR EXPERIENCE AND THAT YOU ARE TAKING THEIR FEEDBACK SERIOUSLY. 5 | 6 | DEAR {{$customerName}}, 7 | +++ 8 | WE ARE SORRY TO HEAR ABOUT {{$request}}. 9 | WE WILL DO OUR BEST TO ENSURE THAT THIS DOES NOT HAPPEN AGAIN. 10 | THANK YOU FOR BRINGING THIS TO OUR ATTENTION. 11 | +++ -------------------------------------------------------------------------------- /Plugins/CityPlugin/GetCity/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": 1, 3 | "description": "Gets a capital name of a country", 4 | "execution_settings": { 5 | "default": { 6 | "max_tokens": 100, 7 | "temperature": 0.4, 8 | "top_p": 0.0, 9 | "presence_penalty": 0.0, 10 | "frequency_penalty": 0.0 11 | } 12 | }, 13 | "input_variables": [ 14 | { 15 | "name": "input", 16 | "description": "Country name", 17 | "default": "" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Plugins/FoodPlugin/GetRecipe/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": 1, 3 | "description": "Suggest a food recipe of a cuisine", 4 | "execution_settings": { 5 | "default": { 6 | "max_tokens": 1000, 7 | "temperature": 0.5, 8 | "top_p": 0.0, 9 | "presence_penalty": 0.0, 10 | "frequency_penalty": 0.0 11 | } 12 | }, 13 | "input_variables": [ 14 | { 15 | "name": "input", 16 | "description": "cuisine", 17 | "default": "" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Plugins/CityPlugin/GetCityIATACode/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": 1, 3 | "description": "Gets the IATA Airport code of a city", 4 | "execution_settings": { 5 | "default": { 6 | "max_tokens": 100, 7 | "temperature": 0.4, 8 | "top_p": 0.0, 9 | "presence_penalty": 0.0, 10 | "frequency_penalty": 0.0 11 | } 12 | }, 13 | "input_variables": [ 14 | { 15 | "name": "input", 16 | "description": "City name", 17 | "default": "" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Plugins/ShoppingPlugin/GetGroceryList/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": 1, 3 | "description": "Suggest a grocery items for a given recipe", 4 | "execution_settings": { 5 | "default": { 6 | "max_tokens": 100, 7 | "temperature": 0.4, 8 | "top_p": 0.0, 9 | "presence_penalty": 0.0, 10 | "frequency_penalty": 0.0 11 | } 12 | }, 13 | "input_variables": [ 14 | { 15 | "name": "input", 16 | "description": "food recipe", 17 | "default": "" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Plugins/FlightTrackerPlugin/GetIATANameFunction/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": 1, 3 | "description": "Gets an IATA name of a location", 4 | "execution_settings": { 5 | "default": { 6 | "max_tokens": 100, 7 | "temperature": 0.4, 8 | "top_p": 0.0, 9 | "presence_penalty": 0.0, 10 | "frequency_penalty": 0.0 11 | } 12 | }, 13 | "input_variables": [ 14 | { 15 | "name": "input", 16 | "description": "Location name for IATA code lookup", 17 | "default": "" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Plugins/GuessPlugin/GuessWhat/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": 1, 3 | "type": "completion", 4 | "description": "Guess what is the name of the place, landmark or a thing", 5 | "completion": { 6 | "max_tokens": 50, 7 | "temperature": 0, 8 | "top_p": 0, 9 | "presence_penalty": 0, 10 | "frequency_penalty": 0 11 | }, 12 | "input": { 13 | "parameters": [ 14 | { 15 | "name": "input", 16 | "description": "Name of a country.", 17 | "defaultValue": "" 18 | } 19 | ] 20 | }, 21 | "default_backends": [] 22 | } 23 | -------------------------------------------------------------------------------- /Plugins/ComplaintsPlugin/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": 1, 3 | "type": "completion", 4 | "description": "Handle the customers complaint.", 5 | "execution_settings": { 6 | "default": { 7 | "max_tokens": 1000, 8 | "temperature": 0 9 | }, 10 | "gpt-4": { 11 | "model_id": "gpt-4-default", 12 | "max_tokens": 1000, 13 | "temperature": 0.3 14 | } 15 | }, 16 | 17 | "input_variables": [ 18 | { 19 | "name": "$customerName", 20 | "description": "The users name.", 21 | "required": true 22 | }, 23 | { 24 | "name": "$request", 25 | "description": "The user's complaint.", 26 | "required": true 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /Utilities.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System.IO; 3 | using System.Net.Http; 4 | 5 | public static class Utilities 6 | { 7 | public static async Task ShowImage(string url, int width, int height) 8 | { 9 | SKImageInfo info = new SKImageInfo(width, height); 10 | SKSurface surface = SKSurface.Create(info); 11 | SKCanvas canvas = surface.Canvas; 12 | canvas.Clear(SKColors.White); 13 | var httpClient = new HttpClient(); 14 | 15 | using (Stream stream = await httpClient.GetStreamAsync(url)) 16 | using (MemoryStream memStream = new MemoryStream()) 17 | { 18 | await stream.CopyToAsync(memStream); 19 | memStream.Seek(0, SeekOrigin.Begin); 20 | SKBitmap webBitmap = SKBitmap.Decode(memStream); 21 | canvas.DrawBitmap(webBitmap, 0, 0, null); 22 | surface.Draw(canvas, 0, 0, null); 23 | }; 24 | surface.Snapshot().Display(); 25 | } 26 | 27 | public static string WordWrap(string text, int maxLineLength) 28 | { 29 | var result = new StringBuilder(); 30 | int i; 31 | var last = 0; 32 | var space = new[] { ' ', '\r', '\n', '\t' }; 33 | do 34 | { 35 | i = last + maxLineLength > text.Length 36 | ? text.Length 37 | : (text.LastIndexOfAny(new[] { ' ', ',', '.', '?', '!', ':', ';', '-', '\n', '\r', '\t' }, Math.Min(text.Length - 1, last + maxLineLength)) + 1); 38 | if (i <= last) i = Math.Min(last + maxLineLength, text.Length); 39 | result.AppendLine(text.Substring(last, i - last).Trim(space)); 40 | last = i; 41 | } while (i < text.Length); 42 | 43 | return result.ToString(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ✈️ A (travel-themed) journey of Semantic Kernel for .NET Developers 2 | Created By: Peter De Tender - petender@microsoft.com 3 | 4 | Sample Notebook, which demonstrates different Semantic Kernel scenarios: 5 | 6 | - Prompts 7 | - Plugins 8 | - Functions 9 | - Personas 10 | 11 | The choice for using a Jupiter Notebook for my Semantic Kernel demos, is thanks to the [Polyglot Notebooks](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode?) for VS Code integration, allowing to run .NET code straight from within the Notebook, instead of running the actual code in the Terminal. This gives a smoother demo experience. (Based on the same approach used by John Maeda in the [Introducing Semantic Kernel Course](https://www.linkedin.com/learning/introducing-semantic-kernel-building-ai-based-apps/introducing-semantic-kernel?u=3322) on LinkedInLearning) 12 | 13 | In order to use this Polyglot Notebook, clone or fork the repo to your local machine, and open the semantickerneldemos.ipynb file in VS Code (or similar Dev IDE) 14 | 15 | 16 | ## Prerequisites 17 | This Polyglot notebook needs to be run from VS Code with the following pre-requisites: 18 | 19 | Software to be installed on your computer: 20 | 21 | ✔️ Visual Studio Code 22 | ✔️ The latest .Net 8.0 SDK 23 | ✔️ Polyglot Notebooks for VS Code extension 24 | 25 | Next, you need to have Azure OpenAI Service and a set of models deployed in your Azure subscription: 26 | 27 | ✔️ Azure OpenAI Service 28 | ✔️ Azure OpenAI Models 29 | 30 | >Note: 5k TPM (tokens per minute) would be enough for most of the demos. No need to max out the tokens quota in your Azure subscription. 31 | 32 | (I personally like to use the model name as the deployment name, for ease of consistency in namings, as well as to avoid confusion in model name and deployment name. These are sometimes mixed up in sample code and documentation.) 33 | 34 | * ✔️ `gpt-4-default`- GPT-4o 35 | * ✔️ `dall-e-3` - DALL-E-3 36 | * ✔️ `text-embedding-ada-002` - text-embedding-ada-002 37 | * ✔️ `text-davinci-002` - text-davinci-002 38 | * ✔️ `gpt-35-turbo-16k` - gpt-35-turbo-16k 39 | 40 | >Note: while we won't use all of these in our demos, those are typically the different models I deploy for my AI-inspired/influenced applications. Once you start using GenAI in your app, it's tempting to start using all its capabilities! 41 | 42 | 🔑 You will use the keys and endpoint parameters during the initialization of this Notebook. You will get prompted for the different parameters. The necessary settings will be stored in a new file settings.json. Make sure you reset or delete this file (see below in step 2 how to do this), before you check in this code in Source Control. 43 | -------------------------------------------------------------------------------- /Settings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text.Json; 5 | using System.Threading.Tasks; 6 | using Microsoft.DotNet.Interactive; 7 | using InteractiveKernel = Microsoft.DotNet.Interactive.Kernel; 8 | 9 | public static class Settings 10 | { 11 | private const string DefaultConfigFile = "settings.json"; 12 | private const string TypeKey = "type"; 13 | private const string ModelKey = "model"; 14 | private const string EndpointKey = "endpoint"; 15 | private const string SecretKey = "apikey"; 16 | private const string OrgKey = "org"; 17 | private const bool StoreConfigOnFile = true; 18 | 19 | // Prompt user for Azure Endpoint URL 20 | public static async Task AskAzureEndpoint(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile) 21 | { 22 | var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile); 23 | 24 | // If needed prompt user for Azure endpoint 25 | if (useAzureOpenAI && string.IsNullOrWhiteSpace(azureEndpoint)) 26 | { 27 | azureEndpoint = await InteractiveKernel.GetInputAsync("Please enter your Azure OpenAI endpoint"); 28 | } 29 | 30 | WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId); 31 | 32 | // Print report 33 | if (useAzureOpenAI) 34 | { 35 | Console.WriteLine("Settings: " + (string.IsNullOrWhiteSpace(azureEndpoint) 36 | ? "ERROR: Azure OpenAI endpoint is empty" 37 | : $"OK: Azure OpenAI endpoint configured [{configFile}]")); 38 | } 39 | 40 | return azureEndpoint; 41 | } 42 | 43 | // Prompt user for OpenAI model name / Azure OpenAI deployment name 44 | public static async Task AskModel(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile) 45 | { 46 | var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile); 47 | 48 | // If needed prompt user for model name / deployment name 49 | if (string.IsNullOrWhiteSpace(model)) 50 | { 51 | if (useAzureOpenAI) 52 | { 53 | model = await InteractiveKernel.GetInputAsync("Please enter your Azure OpenAI deployment name"); 54 | } 55 | else 56 | { 57 | // Use the best model by default, and reduce the setup friction, particularly in VS Studio. 58 | model = "gpt-3.5-turbo"; 59 | } 60 | } 61 | 62 | WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId); 63 | 64 | // Print report 65 | if (useAzureOpenAI) 66 | { 67 | Console.WriteLine("Settings: " + (string.IsNullOrWhiteSpace(model) 68 | ? "ERROR: deployment name is empty" 69 | : $"OK: deployment name configured [{configFile}]")); 70 | } 71 | else 72 | { 73 | Console.WriteLine("Settings: " + (string.IsNullOrWhiteSpace(model) 74 | ? "ERROR: model name is empty" 75 | : $"OK: AI model configured [{configFile}]")); 76 | } 77 | 78 | return model; 79 | } 80 | 81 | // Prompt user for API Key 82 | public static async Task AskApiKey(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile) 83 | { 84 | var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile); 85 | 86 | // If needed prompt user for API key 87 | if (string.IsNullOrWhiteSpace(apiKey)) 88 | { 89 | if (useAzureOpenAI) 90 | { 91 | apiKey = (await InteractiveKernel.GetPasswordAsync("Please enter your Azure OpenAI API key")).GetClearTextPassword(); 92 | orgId = ""; 93 | } 94 | else 95 | { 96 | apiKey = (await InteractiveKernel.GetPasswordAsync("Please enter your OpenAI API key")).GetClearTextPassword(); 97 | } 98 | } 99 | 100 | WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId); 101 | 102 | // Print report 103 | Console.WriteLine("Settings: " + (string.IsNullOrWhiteSpace(apiKey) 104 | ? "ERROR: API key is empty" 105 | : $"OK: API key configured [{configFile}]")); 106 | 107 | return apiKey; 108 | } 109 | 110 | // Prompt user for OpenAI Organization Id 111 | public static async Task AskOrg(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile) 112 | { 113 | var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile); 114 | 115 | // If needed prompt user for OpenAI Org Id 116 | if (!useAzureOpenAI && string.IsNullOrWhiteSpace(orgId)) 117 | { 118 | orgId = await InteractiveKernel.GetInputAsync("Please enter your OpenAI Organization Id (enter 'NONE' to skip)"); 119 | } 120 | 121 | WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId); 122 | 123 | return orgId; 124 | } 125 | 126 | // Load settings from file 127 | public static (bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId) 128 | LoadFromFile(string configFile = DefaultConfigFile) 129 | { 130 | if (!File.Exists(configFile)) 131 | { 132 | Console.WriteLine("Configuration not found: " + configFile); 133 | Console.WriteLine("\nPlease run the Setup Notebook (0-AI-settings.ipynb) to configure your AI backend first.\n"); 134 | throw new Exception("Configuration not found, please setup the notebooks first using notebook 0-AI-settings.pynb"); 135 | } 136 | 137 | try 138 | { 139 | var config = JsonSerializer.Deserialize>(File.ReadAllText(configFile)); 140 | bool useAzureOpenAI = config[TypeKey] == "azure"; 141 | string model = config[ModelKey]; 142 | string azureEndpoint = config[EndpointKey]; 143 | string apiKey = config[SecretKey]; 144 | string orgId = config[OrgKey]; 145 | if (orgId == "none") { orgId = ""; } 146 | 147 | return (useAzureOpenAI, model, azureEndpoint, apiKey, orgId); 148 | } 149 | catch (Exception e) 150 | { 151 | Console.WriteLine("Something went wrong: " + e.Message); 152 | return (true, "", "", "", ""); 153 | } 154 | } 155 | 156 | // Delete settings file 157 | public static void Reset(string configFile = DefaultConfigFile) 158 | { 159 | if (!File.Exists(configFile)) { return; } 160 | 161 | try 162 | { 163 | File.Delete(configFile); 164 | Console.WriteLine("Settings deleted. Run the notebook again to configure your AI backend."); 165 | } 166 | catch (Exception e) 167 | { 168 | Console.WriteLine("Something went wrong: " + e.Message); 169 | } 170 | } 171 | 172 | // Read and return settings from file 173 | private static (bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId) 174 | ReadSettings(bool _useAzureOpenAI, string configFile) 175 | { 176 | // Save the preference set in the notebook 177 | bool useAzureOpenAI = _useAzureOpenAI; 178 | string model = ""; 179 | string azureEndpoint = ""; 180 | string apiKey = ""; 181 | string orgId = ""; 182 | 183 | try 184 | { 185 | if (File.Exists(configFile)) 186 | { 187 | (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = LoadFromFile(configFile); 188 | } 189 | } 190 | catch (Exception e) 191 | { 192 | Console.WriteLine("Something went wrong: " + e.Message); 193 | } 194 | 195 | // If the preference in the notebook is different from the value on file, then reset 196 | if (useAzureOpenAI != _useAzureOpenAI) 197 | { 198 | Reset(configFile); 199 | useAzureOpenAI = _useAzureOpenAI; 200 | model = ""; 201 | azureEndpoint = ""; 202 | apiKey = ""; 203 | orgId = ""; 204 | } 205 | 206 | return (useAzureOpenAI, model, azureEndpoint, apiKey, orgId); 207 | } 208 | 209 | // Write settings to file 210 | private static void WriteSettings( 211 | string configFile, bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId) 212 | { 213 | try 214 | { 215 | if (StoreConfigOnFile) 216 | { 217 | var data = new Dictionary 218 | { 219 | { TypeKey, useAzureOpenAI ? "azure" : "openai" }, 220 | { ModelKey, model }, 221 | { EndpointKey, azureEndpoint }, 222 | { SecretKey, apiKey }, 223 | { OrgKey, orgId }, 224 | }; 225 | 226 | var options = new JsonSerializerOptions { WriteIndented = true }; 227 | File.WriteAllText(configFile, JsonSerializer.Serialize(data, options)); 228 | } 229 | } 230 | catch (Exception e) 231 | { 232 | Console.WriteLine("Something went wrong: " + e.Message); 233 | } 234 | 235 | // If asked then delete the credentials stored on disk 236 | if (!StoreConfigOnFile && File.Exists(configFile)) 237 | { 238 | try 239 | { 240 | File.Delete(configFile); 241 | } 242 | catch (Exception e) 243 | { 244 | Console.WriteLine("Something went wrong: " + e.Message); 245 | } 246 | } 247 | } 248 | } -------------------------------------------------------------------------------- /semantickerneldemos.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# ✈️ A (travel-themed) journey of Semantic Kernel for .NET Developers \n", 8 | "`Created By: Peter De Tender - petender@microsoft.com`\n", 9 | "\n", 10 | "Sample Notebook, which demonstrates different Semantic Kernel scenarios:\n", 11 | "- Prompts\n", 12 | "- Plugins\n", 13 | "- Functions\n", 14 | "- Personas\n", 15 | "\n", 16 | "The choice for using a Jupiter Notebook for my Semantic Kernel demos, is thanks to the [Polyglot Notebooks for VS Code](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode?) integration, allowing to run .NET code straight from within the Notebook, instead of running the actual code in the Terminal. This gives a smoother demo experience. (Based on the same approach used by John Maeda in the [Introducing Semantic Kernel Course on LinkedInLearning](https://www.linkedin.com/learning/introducing-semantic-kernel-building-ai-based-apps/introducing-semantic-kernel?u=3322))" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "---\n", 24 | "\n", 25 | "### 0. Prerequisites\n", 26 | "\n", 27 | "\n", 28 | "This `Polyglot` notebook needs to be run from VS Code with the following pre-requisites:\n", 29 | "\n", 30 | "Software to be installed on your computer:\n", 31 | "\n", 32 | "* ✔️ [Visual Studio Code](https://code.visualstudio.com/Download)\n", 33 | "* ✔️ The latest [.Net 8.0 SDK](https://dotnet.microsoft.com/en-us/download) \n", 34 | "* ✔️ [Polyglot Notebooks for VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode?)\n", 35 | "\n", 36 | "Next, you need to have Azure OpenAI Service and a set of models deployed in your Azure subscription: \n", 37 | "\n", 38 | "* ✔️ [Azure OpenAI Service](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart?)\n", 39 | "* ✔️ [Azure OpenAI Models](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/concepts/models?)\n", 40 | "\n", 41 | "**Note:** 5k TPM (tokens per minute) would be enough for most of the demos. No need to max out the tokens quota in your Azure subscription.\n", 42 | "\n", 43 | "(I personally like to use the model name as the deployment name, for ease of consistency in namings, as well as to avoid confusion in model name and deployment name. These are sometimes mixed up in sample code and documentation.)\n", 44 | "\n", 45 | " * ✔️ `gpt-4-default`- GPT-4o\n", 46 | " * ✔️ `dall-e-3` - DALL-E-3\n", 47 | " * ✔️ `text-embedding-ada-002` - text-embedding-ada-002\n", 48 | " * ✔️ `text-davinci-002` - text-davinci-002\n", 49 | " * ✔️ `gpt-35-turbo-16k` - gpt-35-turbo-16k\n", 50 | "\n", 51 | "**Note:** while we won't use all of these in our demos, those are typically the different models I deploy for my AI-inspired/influenced applications. Once you start using GenAI in your app, it's tempting to start using all its capabilities!\n", 52 | "\n", 53 | "🔑 You will use the keys and endpoint parameters during the initialization of this Notebook. You will get prompted for the different parameters. The necessary settings will be stored in a new file settings.json. **Make sure you reset or delete this file (see below in step 2 how to do this), before you check in this code in Source Control**. \n", 54 | "\n", 55 | "---" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "### 1. Starting .NET Interactive Mode \n", 63 | "\n", 64 | "👋 When you start using this Notebook, by pressing the ▶️ \"play\" button in front of a code section, it will show a prompt on top of the VSCode Menu Bar, asking \"Select kernel for semantickerneldemos\". Make sure you select \n", 65 | "\n", 66 | "```\n", 67 | "**.NET Interactive** 👈\n", 68 | "```\n", 69 | "which brings in the interactive mode into the Polyglot Notebooks. Rather nifty feature if you ask me!" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 1, 75 | "metadata": { 76 | "dotnet_interactive": { 77 | "language": "csharp" 78 | }, 79 | "polyglot_notebook": { 80 | "kernelName": "csharp" 81 | }, 82 | "vscode": { 83 | "languageId": "polyglot-notebook" 84 | } 85 | }, 86 | "outputs": [ 87 | { 88 | "name": "stdout", 89 | "output_type": "stream", 90 | "text": [ 91 | "When you see the line below this one, you'll know the code block executed successfully.\r\n" 92 | ] 93 | } 94 | ], 95 | "source": [ 96 | "// 👈 you should see a ▶️ (play) button to the left of this \n", 97 | "// code block. Clicking this button will execute the .NET Code \n", 98 | "// snippet below and display the output in the cell below.\n", 99 | "// The easiest example I could come up with is using Console.WriteLine \n", 100 | "// to output a string to the console.\n", 101 | "\n", 102 | "Console.WriteLine(\"When you see the line below this one, you'll know the code block executed successfully.\");" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": {}, 108 | "source": [ 109 | "### 2. Provide the Azure OpenAI Parameter Settings\n", 110 | "With the .NET Interactive mode working, we continue the baseline configuration of the Notebook, by providing the necessary Azure OpenAI Parameters (Think of Endpoints, API Keys and Deployment Names).\n", 111 | "\n", 112 | "Read the Output below the code section for any successful messages or failures before continuing to step 3." 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 2, 118 | "metadata": { 119 | "dotnet_interactive": { 120 | "language": "csharp" 121 | }, 122 | "polyglot_notebook": { 123 | "kernelName": "csharp" 124 | }, 125 | "vscode": { 126 | "languageId": "polyglot-notebook" 127 | } 128 | }, 129 | "outputs": [ 130 | { 131 | "ename": "Error", 132 | "evalue": "Input request cancelled", 133 | "output_type": "error", 134 | "traceback": [ 135 | "Input request cancelled" 136 | ] 137 | }, 138 | { 139 | "ename": "Error", 140 | "evalue": "System.Exception: Input request cancelled\r\n at Microsoft.DotNet.Interactive.Kernel.GetInputAsync(String prompt, Boolean isPassword, String typeHint, String valueName) in D:\\a\\_work\\1\\s\\src\\Microsoft.DotNet.Interactive\\Kernel.Static.cs:line 72\r\n at Microsoft.DotNet.Interactive.Kernel.GetInputAsync(String prompt, String typeHint, String valueName) in D:\\a\\_work\\1\\s\\src\\Microsoft.DotNet.Interactive\\Kernel.Static.cs:line 46\r\n at Submission#3.Settings.AskAzureEndpoint(Boolean _useAzureOpenAI, String configFile)\r\n at Submission#4.<>d__0.MoveNext()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)", 141 | "output_type": "error", 142 | "traceback": [ 143 | "System.Exception: Input request cancelled\r\n", 144 | " at Microsoft.DotNet.Interactive.Kernel.GetInputAsync(String prompt, Boolean isPassword, String typeHint, String valueName) in D:\\a\\_work\\1\\s\\src\\Microsoft.DotNet.Interactive\\Kernel.Static.cs:line 72\r\n", 145 | " at Microsoft.DotNet.Interactive.Kernel.GetInputAsync(String prompt, String typeHint, String valueName) in D:\\a\\_work\\1\\s\\src\\Microsoft.DotNet.Interactive\\Kernel.Static.cs:line 46\r\n", 146 | " at Submission#3.Settings.AskAzureEndpoint(Boolean _useAzureOpenAI, String configFile)\r\n", 147 | " at Submission#4.<>d__0.MoveNext()\r\n", 148 | "--- End of stack trace from previous location ---\r\n", 149 | " at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)" 150 | ] 151 | } 152 | ], 153 | "source": [ 154 | "#!import Settings.cs\n", 155 | "\n", 156 | "bool useAzureOpenAI = true;\n", 157 | "\n", 158 | "await Settings.AskAzureEndpoint(useAzureOpenAI);\n", 159 | "await Settings.AskModel(useAzureOpenAI);\n", 160 | "await Settings.AskApiKey(useAzureOpenAI);\n", 161 | "\n", 162 | "// Uncomment this if you're using OpenAI and need to set the Org Id\n", 163 | "// await Settings.AskOrg(useAzureOpenAI);" 164 | ] 165 | }, 166 | { 167 | "cell_type": "markdown", 168 | "metadata": {}, 169 | "source": [ 170 | "`In case you want to reset your settings so that you can update your API keys again, uncomment the below \n", 171 | "//Settings.Reset(); line and run the code block.`" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": null, 177 | "metadata": { 178 | "dotnet_interactive": { 179 | "language": "csharp" 180 | }, 181 | "polyglot_notebook": { 182 | "kernelName": "csharp" 183 | }, 184 | "vscode": { 185 | "languageId": "polyglot-notebook" 186 | } 187 | }, 188 | "outputs": [], 189 | "source": [ 190 | "#!import Settings.cs\n", 191 | "\n", 192 | "// Uncomment this line to reset your settings and delete the settings.json file from disk.\n", 193 | "// Settings.Reset();" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "### 3. Initiate the .NET Interactive Kernel by loading the Semantic Kernel package into a client.\n", 201 | "\n", 202 | "This will create a client so you don't have to initialise it again. \n", 203 | "\n", 204 | "Think of Microsoft’s [Semantic Kernel](https://learn.microsoft.com/en-us/semantic-kernel/overview/) as collection of stand-alone blocks (some would call it Functions??). Each block acts as a different AI service, like recognizing language, translating, providing answers to your prompt questions (GPT-model driven), or creating images with Dall-E.\n", 205 | "\n", 206 | "Semantic Kernel is a lightweight, open-source development kit that lets you easily build AI agents and integrate the latest AI models into your C#, Python, or Java codebase. It serves as an efficient middleware that enables rapid delivery of enterprise-grade solutions.\n", 207 | "\n", 208 | "Semantic Kernel combines prompts with existing APIs called [Plugins](https://learn.microsoft.com/en-us/semantic-kernel/concepts/plugins/) to perform actions. By describing your existing code to AI models, they’ll be called to address requests. When a request is made the model calls a function, and Semantic Kernel is the middleware translating the model's request to a function call and passes the results back to the model.\n", 209 | "\n", 210 | "The selected code is a C# file that demonstrates how to configure and create a kernel using the Microsoft.SemanticKernel library. The kernel is a component that provides a framework for executing code and performing various operations.\n", 211 | "\n", 212 | "``` \n", 213 | "what the code is doing: \n", 214 | "```\n", 215 | "(description has been partially created by GitHub Copilot AI, isn't that cool...)\n", 216 | "\n", 217 | "> The code begins by including two NuGet packages, Microsoft.SemanticKernel and Microsoft.SemanticKernel.Plugins.Core, with specific versions. These packages contain the necessary functionality for working with the SemanticKernel library.\n", 218 | "\n", 219 | "> Next, the code imports a file called \"Settings.cs\" using the #!import directive. This file likely contains configuration settings for the AI backend used by the kernel.\n", 220 | "\n", 221 | "> The code then includes the necessary namespaces for working with the SemanticKernel library: Microsoft.SemanticKernel and Microsoft.SemanticKernel.Plugins.Core. These namespaces provide access to the classes and methods needed to create and configure the kernel.\n", 222 | "\n", 223 | "> After that, the code creates a builder object for the kernel using the Kernel.CreateBuilder() method. The builder is responsible for configuring the kernel and specifying the components it should use.\n", 224 | "\n", 225 | "> The code then loads the configuration settings from the \"Settings.cs\" file using the Settings.LoadFromFile() method. This method likely reads the settings from a file and returns them as a tuple containing the values for variables like useAzureOpenAI, model, azureEndpoint, apiKey, and orgId.\n", 226 | "\n", 227 | "> Next, the code checks the value of the useAzureOpenAI variable. If it is true, the code adds the Azure OpenAI chat completion component to the kernel using the builder.AddAzureOpenAIChatCompletion() method, passing in the appropriate parameters. If useAzureOpenAI is false, the code adds the regular OpenAI chat completion component using the builder.AddOpenAIChatCompletion() method.\n", 228 | "\n", 229 | "> Finally, the code has configured the kernel using the builder and is ready to use it for executing code or performing other operations.\n", 230 | "\n", 231 | "> Overall, this code demonstrates how to create and configure a kernel using the Microsoft.SemanticKernel library, allowing you to leverage AI chat completion functionality in your application." 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": { 238 | "dotnet_interactive": { 239 | "language": "csharp" 240 | }, 241 | "polyglot_notebook": { 242 | "kernelName": "csharp" 243 | }, 244 | "vscode": { 245 | "languageId": "polyglot-notebook" 246 | } 247 | }, 248 | "outputs": [], 249 | "source": [ 250 | "// Getting the latest package released on 5th May, 2024 - https://www.nuget.org/packages/Microsoft.SemanticKernel/\n", 251 | "#r \"nuget: Microsoft.SemanticKernel, 1.11.1\"\n", 252 | "#r \"nuget: Microsoft.SemanticKernel.Plugins.Core, 1.11.1-alpha\"\n", 253 | "\n", 254 | "#!import Settings.cs\n", 255 | "\n", 256 | "using Microsoft.SemanticKernel;\n", 257 | "using Microsoft.SemanticKernel.Plugins.Core;\n", 258 | "using Kernel = Microsoft.SemanticKernel.Kernel;\n", 259 | "\n", 260 | "//Create Kernel builder\n", 261 | "var builder = Kernel.CreateBuilder();\n", 262 | "\n", 263 | "// Configure AI backend used by the kernel\n", 264 | "var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n", 265 | "if (useAzureOpenAI)\n", 266 | " builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n", 267 | "else\n", 268 | " builder.AddOpenAIChatCompletion(model, apiKey, orgId);" 269 | ] 270 | }, 271 | { 272 | "cell_type": "markdown", 273 | "metadata": {}, 274 | "source": [ 275 | "### 3. Semantic Kernel Plugins\n", 276 | "\n", 277 | "AI plugins act like a set of instructions or tasks that your application can execute. Think of them as an instructions book (John calls them recipes...) for your application, where each set of instructions (or recipes, or plugin) includes a list of ingredients (or functions) and steps (or triggers and actions) to accomplish a specific task.\n", 278 | "\n", 279 | "For instance, when you’re developing a chatbot that needs to answer travel-related questions, you could create a plugin with a function to fetch current travel data from a travel organization API and another function to format that data into a user-friendly message, HTML, table layout and alike.\n", 280 | "\n", 281 | "Plugins are the core components of Semantic Kernel and can work seamlessly with plugins in ChatGPT, Bing, and Microsoft 365, as well as other third-party sources. They encapsulate capabilities into single units of functionality that the kernel can run. Plugins can include both native code and requests to AI services via prompts.\n", 282 | "\n", 283 | "Plugins are two-fold, allowing you to export them to ChatGPT, Bing or Microsoft 365. Similarly, plugins created for ChatGPT, Bing, and Microsoft 365 can be imported into Semantic Kernel effortlessly.\n", 284 | "\n", 285 | "#### **Prompts**\n", 286 | "\n", 287 | "Prompts (or Prompt Functions) are the individual steps in a recipe. Each step (or function) tells your app what to do and how to achieve success when running it.\n", 288 | "\n", 289 | "For example, continuing on the travel chatbot idea, you might want it to be able to answer questions about the weather so you can plan your vacation trip. One of your prompts might be a step to decide on your preferred vacation location, based on flight cost from fetching an airline's API, followed by a step which collects the expected weather data from a weather API. Another prompt might be a step that combines the results of the flight options, together with the weather results and recommends the ultimate vacation spot.\n", 290 | "\n", 291 | "Prompts are used in plugins, which are like the full recipes in your recipe book. Each plugin can contain multiple prompts and each prompt can be triggered by certain events or conditions.\n", 292 | "\n", 293 | "#### **Functions** \n", 294 | "\n", 295 | "Native Functions in Semantic Kernel are similar to the handy-man or -woman's tools you use when doing construction work. These could be things like a saw, hammer, screwdrivers, drills and alike. They’re the tools that allow you to interact with your materials (data) and transform them in different ways (kitchen remodelling, building a house,...).\n", 296 | "\n", 297 | "For example, let’s say you’re building a chatbot and one of your instructions (plugins) is for creating furniture. One of your steps (Prompts) might be to collect different materials (wood, screws, doorhandles,...) together (combine data). While your hands can put everything together, you would also need a tool (Native Function) like a saw (to cut the panels), screwdriver (to screw everything together), etc..\n", 298 | "\n", 299 | "So, you could create a Native Function that takes your instructions (data), uses the correct tool (performs an operation on the data) and returns a finished kitchen cupboard (the result of the operation)." 300 | ] 301 | }, 302 | { 303 | "cell_type": "markdown", 304 | "metadata": {}, 305 | "source": [ 306 | "#### 3.1 Find a country's capital\n", 307 | "\n", 308 | "In this example, we demonstrate a way to find the Capital City, based on a country. If no country name gets provided (e.g. you give a city name), the AI response (Chat Completion), will tell you.\n", 309 | "\n", 310 | "```\n", 311 | "what the code is doing:\n", 312 | "```\n", 313 | "> The first line *(Kernel kernel ...)* creates an instance of the Kernel by calling the Build method on the builder object. The Kernel is the core component that orchestrates the integration between your application and AI models or services.\n", 314 | "\n", 315 | "> In the next line *(var cityPluginsDirectoryPath...)*, you construct the path to the directory where your plugins are stored. It combines the current working directory with the relative path to the “CityPlugin” directory inside the “Plugins” folder. This is where your plugin files are located.\n", 316 | "\n", 317 | "> The last line *(var cityPluginFunctions...)* imports the functions defined in the plugins located in the specified directory. The ImportPluginFromPromptDirectory method reads the plugin files and makes their functions available to the Kernel. These functions can then be used to perform specific tasks within your application." 318 | ] 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "metadata": {}, 323 | "source": [ 324 | "```\n", 325 | "import the plugin and all its functions (prompts)\n", 326 | "```" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": null, 332 | "metadata": { 333 | "dotnet_interactive": { 334 | "language": "csharp" 335 | }, 336 | "polyglot_notebook": { 337 | "kernelName": "csharp" 338 | }, 339 | "vscode": { 340 | "languageId": "polyglot-notebook" 341 | } 342 | }, 343 | "outputs": [], 344 | "source": [ 345 | "Kernel kernel = builder.Build();\n", 346 | "\n", 347 | "// Load the plugin directory\n", 348 | "var cityPluginsDirectoryPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"Plugins\",\"CityPlugin\");\n", 349 | "\n", 350 | "// Load the plugin functons\n", 351 | "var cityPluginFunctions = kernel.ImportPluginFromPromptDirectory(cityPluginsDirectoryPath);\n" 352 | ] 353 | }, 354 | { 355 | "cell_type": "markdown", 356 | "metadata": {}, 357 | "source": [ 358 | "```\n", 359 | "using the function, i.e. get the capital city name based on a given country name\n", 360 | "```" 361 | ] 362 | }, 363 | { 364 | "cell_type": "code", 365 | "execution_count": null, 366 | "metadata": { 367 | "dotnet_interactive": { 368 | "language": "csharp" 369 | }, 370 | "polyglot_notebook": { 371 | "kernelName": "csharp" 372 | }, 373 | "vscode": { 374 | "languageId": "polyglot-notebook" 375 | } 376 | }, 377 | "outputs": [], 378 | "source": [ 379 | "// Set-up the arguments (input)\n", 380 | "var arguments = new KernelArguments();\n", 381 | "arguments.Add(\"input\", \"Belgium\");\n", 382 | "\n", 383 | "// Invoke the plugin function\n", 384 | "var result = await kernel.InvokeAsync(cityPluginFunctions[\"GetCity\"], arguments);\n", 385 | "\n", 386 | "// Print the result\n", 387 | "Console.WriteLine(result.GetValue());" 388 | ] 389 | }, 390 | { 391 | "cell_type": "markdown", 392 | "metadata": {}, 393 | "source": [ 394 | "#### 3.2 Find a country's capital IATA Airline code\n", 395 | "\n", 396 | "In this example, we continue on the path of traveling. With the Capital City found. Let's try and find it's IATA Airport code.\n", 397 | "\n", 398 | "```\n", 399 | "what the code is doing:\n", 400 | "```\n", 401 | "> The first line *(Kernel kernel ...)* creates an instance of the Kernel by calling the Build method on the builder object. The Kernel is the core component that orchestrates the integration between your application and AI models or services.\n", 402 | "\n", 403 | "> In the next line *(var cityPluginsDirectoryPath...)*, you construct the path to the directory where your plugins are stored. It combines the current working directory with the relative path to the “CityPlugin” directory inside the “Plugins” folder. This is where your plugin files are located.\n", 404 | "\n", 405 | "> The last line *(var cityPluginFunctions...)* imports the functions defined in the plugins located in the specified directory. The ImportPluginFromPromptDirectory method reads the plugin files and makes their functions available to the Kernel. These functions can then be used to perform specific tasks within your application." 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "```\n", 413 | "import the plugin and all its functions (prompts)\n", 414 | "```" 415 | ] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "execution_count": null, 420 | "metadata": { 421 | "dotnet_interactive": { 422 | "language": "csharp" 423 | }, 424 | "polyglot_notebook": { 425 | "kernelName": "csharp" 426 | }, 427 | "vscode": { 428 | "languageId": "polyglot-notebook" 429 | } 430 | }, 431 | "outputs": [], 432 | "source": [ 433 | "Kernel kernel = builder.Build();\n", 434 | "\n", 435 | "// Load the plugin directory\n", 436 | "var cityPluginsDirectoryPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"Plugins\",\"CityPlugin\");\n", 437 | "\n", 438 | "// Load the plugin functons\n", 439 | "var cityPluginFunctions = kernel.ImportPluginFromPromptDirectory(cityPluginsDirectoryPath);" 440 | ] 441 | }, 442 | { 443 | "cell_type": "markdown", 444 | "metadata": {}, 445 | "source": [ 446 | "```\n", 447 | "using the function, i.e. get the IATA Airport code for a given (capital) city name\n", 448 | "```" 449 | ] 450 | }, 451 | { 452 | "cell_type": "code", 453 | "execution_count": null, 454 | "metadata": { 455 | "dotnet_interactive": { 456 | "language": "csharp" 457 | }, 458 | "polyglot_notebook": { 459 | "kernelName": "csharp" 460 | }, 461 | "vscode": { 462 | "languageId": "polyglot-notebook" 463 | } 464 | }, 465 | "outputs": [], 466 | "source": [ 467 | "// Set-up the arguments (input)\n", 468 | "var arguments = new KernelArguments();\n", 469 | "arguments.Add(\"input\", \"Brussels\");\n", 470 | "\n", 471 | "// Invoke the plugin function\n", 472 | "var result = await kernel.InvokeAsync(cityPluginFunctions[\"GetCityIATACode\"], arguments);\n", 473 | "\n", 474 | "// Print the result\n", 475 | "Console.WriteLine(result.GetValue());" 476 | ] 477 | }, 478 | { 479 | "cell_type": "markdown", 480 | "metadata": {}, 481 | "source": [ 482 | "### 3.3 Inline Functions" 483 | ] 484 | }, 485 | { 486 | "cell_type": "markdown", 487 | "metadata": {}, 488 | "source": [ 489 | "With the previous examples, the actual Semantic Kernel objects (prompt, configuration), are stored on the local file system with the application source code. In a more real-life example where no (web) server is hosting the application - such as Web Assembly Browser client or a Mobile App - your app won't necessarily have access to these **skprompt.txt** and **config.json** files (unless you integrate them into your app source files... which might not always be the right approach). Therefore, Semantic Kernel has a way to create an **inline function** with the same objective.\n", 490 | "\n", 491 | "An *inline function* is like a step in a recipe that you write directly in your program. It’s called *inline* because you define it right where you’re going to use it. I'm almost certain this could be its own C# method. " 492 | ] 493 | }, 494 | { 495 | "cell_type": "code", 496 | "execution_count": null, 497 | "metadata": { 498 | "dotnet_interactive": { 499 | "language": "csharp" 500 | }, 501 | "polyglot_notebook": { 502 | "kernelName": "csharp" 503 | }, 504 | "vscode": { 505 | "languageId": "polyglot-notebook" 506 | } 507 | }, 508 | "outputs": [], 509 | "source": [ 510 | "using Microsoft.SemanticKernel.Connectors.OpenAI;\n", 511 | "\n", 512 | "using System.Text.Json;\n", 513 | "\n", 514 | "kernel = builder.Build();\n", 515 | "\n", 516 | "// Define a prompt\n", 517 | "string skPrompt = @\"Ask an interesting new riddle about Belgium with its answer in a below json format. It should only contain a JSON message and nothing else.\n", 518 | "\n", 519 | " {\n", 520 | " \"\"Question\"\": \"\"\"\",\n", 521 | " \"\"Answer\"\": \"\"\"\"\n", 522 | " }\n", 523 | " \";\n", 524 | "\n", 525 | "// Set up the execution settings (configuration of how prompt function should behave)\n", 526 | "var executionSettings = new OpenAIPromptExecutionSettings()\n", 527 | "{\n", 528 | " MaxTokens = 200,\n", 529 | " Temperature = 0.5\n", 530 | "};\n", 531 | "\n", 532 | "// // Create a new Prompt Template\n", 533 | "// var promptTemplateConfig = new PromptTemplateConfig(skPrompt);\n", 534 | "// var promptTemplateFactory = new KernelPromptTemplateFactory();\n", 535 | "// var promptTemplate = promptTemplateFactory.Create(promptTemplateConfig);\n", 536 | "\n", 537 | "// // Render this C# template into a format that's understood by the kernel\n", 538 | "// var renderedPrompt = await promptTemplate.RenderAsync(kernel);\n", 539 | "\n", 540 | "// Create a new prompt function\n", 541 | "var guessPluginFunction = kernel.CreateFunctionFromPrompt(skPrompt, executionSettings);\n", 542 | "\n", 543 | "// Invoke a prompt function and get the result\n", 544 | "var guessPluginResult = await kernel.InvokeAsync(guessPluginFunction, new());\n", 545 | "\n", 546 | "// Parse the JSON object\n", 547 | "var riddleObject = JsonDocument.Parse(guessPluginResult.GetValue()).RootElement;\n", 548 | "\n", 549 | "// Get a riddle from the JSON object\n", 550 | "var riddle = riddleObject.GetProperty(\"Question\").GetString();\n", 551 | "\n", 552 | "// Get an answer from the JSON object\n", 553 | "var answer = riddleObject.GetProperty(\"Answer\").GetString();\n", 554 | "\n", 555 | "// Print the result\n", 556 | "Console.WriteLine(riddle + \" \" + answer);" 557 | ] 558 | }, 559 | { 560 | "cell_type": "markdown", 561 | "metadata": {}, 562 | "source": [ 563 | "### 4. Generating Images with AI (DALL-E-3)\n", 564 | "\n", 565 | "Thanks to OpenAI's Dall-E model, it becomes easy to generate cool-looking images, logos, companion designs and artistry creations.\n", 566 | "\n", 567 | "Using the well-known .NET Nuget Package from SkiaSharp, we render the image output coming from the Dall-E image generation process. Staying within the travel and country subject, we configure our skprompt as follows: \n", 568 | "\n", 569 | "`Select a well-known landmark in a big city within {{$input}}. \n", 570 | "Describe some facts about the history, tourism and culture of {{$input}}.`\n", 571 | "\n", 572 | "This prompt takes the country's name and replace with `$input`. Once replaced, it generates a single-paragraph description, which will be used as the input prompt for the image creation/generation. \n", 573 | "\n", 574 | "```\n", 575 | "What the code is doing:\n", 576 | "```\n", 577 | "\n", 578 | "> The selected code is a C# program that demonstrates how to use the Microsoft Semantic Kernel library and the AzureOpenAI API to generate an image based on a given input. Let's break down the code step by step:\n", 579 | "\n", 580 | "> The code starts by importing the necessary NuGet packages for the Microsoft Semantic Kernel library and its plugins. These packages provide the functionality for text embedding, chat completion, and image generation.\n", 581 | "\n", 582 | "> Next, the code imports a file called \"Settings.cs\" using the #!import directive. This file likely contains configuration settings for the OpenAI API, such as the endpoint, API key, and organization ID.\n", 583 | "\n", 584 | "> The code then imports the required namespaces for the Microsoft Semantic Kernel library and its plugins.\n", 585 | "\n", 586 | "> A kernel builder object is created using the Kernel.CreateBuilder() method. The kernel builder is responsible for configuring the various AI features provided by the Semantic Kernel library.\n", 587 | "\n", 588 | "> The code checks a boolean variable useAzureOpenAI to determine whether to use the Azure implementation of the OpenAI API or the default implementation. Depending on the value of useAzureOpenAI, the code adds the appropriate AI services to the kernel builder. These services include text embedding generation, chat completion, and text-to-image generation.\n", 589 | "\n", 590 | "> After configuring the AI services, the kernel builder is used to build the final kernel object.\n", 591 | "\n", 592 | "> The code retrieves instances of the text-to-image service and the text embedding generation service from the kernel. These instances will be used later to generate the image and extract embeddings from text, respectively.\n", 593 | "\n", 594 | "> The code then loads a plugin directory path and imports the plugin functions from that directory using the kernel.ImportPluginFromPromptDirectory() method. This allows the program to extend its functionality with custom plugins.\n", 595 | "\n", 596 | "> The code sets up a KernelArguments object and adds an \"input\" argument with the value \"Belgium\". This argument will be passed to the semantic function invoked later.\n", 597 | "\n", 598 | "> The code invokes the semantic function named \"GuessWhat\" using the kernel.InvokeAsync() method. The function takes the previously defined arguments and returns a result.\n", 599 | "\n", 600 | "> The image description is extracted from the result using the GetValue() method.\n", 601 | "\n", 602 | "> The image description is then passed to the dallE.GenerateImageAsync() method, which uses the DALL-E 3 model to generate an image. The method returns the URL of the generated image.\n", 603 | "\n", 604 | "> The Utilities.ShowImage() method is called to display the generated image using the SkiaSharp library. The image is resized to 512x512 pixels.\n", 605 | "\n", 606 | "> Finally, the two lines of code at the end print the image description and the URL of the generated image to the console.\n", 607 | "\n", 608 | "> Overall, this code demonstrates how to use the Microsoft Semantic Kernel library and the OpenAI API to generate an image based on a given input using text embedding and text-to-image generation services." 609 | ] 610 | }, 611 | { 612 | "cell_type": "code", 613 | "execution_count": null, 614 | "metadata": { 615 | "dotnet_interactive": { 616 | "language": "csharp" 617 | }, 618 | "polyglot_notebook": { 619 | "kernelName": "csharp" 620 | }, 621 | "vscode": { 622 | "languageId": "polyglot-notebook" 623 | } 624 | }, 625 | "outputs": [], 626 | "source": [ 627 | "#r \"nuget: Microsoft.SemanticKernel, 1.11.1\"\n", 628 | "#r \"nuget: System.Numerics.Tensors, 9.0.0-preview.3.24172.9\"\n", 629 | "#r \"nuget: SkiaSharp, 2.88.8\"\n", 630 | "\n", 631 | "#!import Utilities.cs\n", 632 | "\n", 633 | "using Microsoft.SemanticKernel;\n", 634 | "using Microsoft.SemanticKernel.TextToImage;\n", 635 | "using Microsoft.SemanticKernel.Embeddings;\n", 636 | "using Microsoft.SemanticKernel.Connectors.OpenAI;\n", 637 | "using System.Numerics.Tensors;\n", 638 | "\n", 639 | "using Kernel = Microsoft.SemanticKernel.Kernel;\n", 640 | "\n", 641 | "#pragma warning disable SKEXP0001, SKEXP0002, SKEXP0010, SKEXP0011, SKEXP0012\n", 642 | "\n", 643 | "// Load OpenAI credentials from config/settings.json\n", 644 | "var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n", 645 | "\n", 646 | "// Configure the three AI features: text embedding (using Ada), chat completion, image generation (DALL-E-3)\n", 647 | "var builder = Kernel.CreateBuilder();\n", 648 | "\n", 649 | "if(useAzureOpenAI)\n", 650 | "{\n", 651 | " builder.AddAzureOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", azureEndpoint, apiKey);\n", 652 | " builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n", 653 | " builder.AddAzureOpenAITextToImage(\"dall-e-3\", azureEndpoint, apiKey);\n", 654 | "}\n", 655 | "else\n", 656 | "{\n", 657 | " builder.AddOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", apiKey, orgId);\n", 658 | " builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n", 659 | " builder.AddOpenAITextToImage(apiKey, orgId);\n", 660 | "}\n", 661 | " \n", 662 | "var kernel = builder.Build();\n", 663 | "\n", 664 | "// Get AI service instance used to generate images\n", 665 | "var dallE = kernel.GetRequiredService();\n", 666 | "\n", 667 | "// Get AI service instance used to extract embedding from a text\n", 668 | "var textEmbedding = kernel.GetRequiredService();\n", 669 | "\n", 670 | "// Load the plugin directory\n", 671 | "var guessPluginsDirectoryPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"Plugins\",\"GuessPlugin\");\n", 672 | "\n", 673 | "// Load the plugin functons\n", 674 | "var guessPluginFunctions = kernel.ImportPluginFromPromptDirectory(guessPluginsDirectoryPath);\n", 675 | "\n", 676 | "// Setting up the SKContext\n", 677 | "var arguments = new KernelArguments();\n", 678 | "arguments.Add(\"input\", \"Belgium\");\n", 679 | "\n", 680 | "// Invoke the semantic function\n", 681 | "var imageResult = await kernel.InvokeAsync(guessPluginFunctions[\"GuessWhat\"], arguments);\n", 682 | "\n", 683 | "// Get the image description from the result\n", 684 | "var imagedescription = imageResult.GetValue();\n", 685 | "\n", 686 | "// Uncomment to see the image description\n", 687 | " Console.WriteLine(\"-----------------------------\");\n", 688 | " Console.WriteLine(\"### Generating Image Description using the country input ###\");\n", 689 | " Console.WriteLine(\"-----------------------------\");\n", 690 | " Console.WriteLine(imagedescription);\n", 691 | " Console.WriteLine(\"-----------------------------\");\n", 692 | " Console.WriteLine(\"### Generating Image using the provided description. This might take a few minutes... ###\");\n", 693 | " Console.WriteLine(\"-----------------------------\");\n", 694 | "\n", 695 | "// Use DALL-E 3 to generate an image. OpenAI in this case returns a URL (though you can ask to return a base64 image)\n", 696 | "var imageUrl = await dallE.GenerateImageAsync(imagedescription.Trim(), 1024, 1024);\n", 697 | "\n", 698 | "// Show an image using SkiaSharp library\n", 699 | "await Utilities.ShowImage(imageUrl, 512, 512);\n", 700 | "\n", 701 | "// Uncomment to see the URL of the image\n", 702 | "Console.WriteLine(imageUrl);" 703 | ] 704 | }, 705 | { 706 | "cell_type": "markdown", 707 | "metadata": {}, 708 | "source": [ 709 | "### 5. Planners \n", 710 | "\n", 711 | "[Semantic Kernel Planners](https://learn.microsoft.com/en-us/semantic-kernel/concepts/planning?pivots=programming-language-csharp) are a core component of the Semantic Kernel that provide AI orchestration. They manage the seamless integration between AI Models and Plugins by devising execution strategies from user requests. Essentially, planners determine which functions to call and in what order to fulfill a user’s request.\n", 712 | "\n", 713 | "For example, if a user asks the AI to “toggle all the lights,” the planner will:\n", 714 | "\n", 715 | "- Call a function to get the current state of all lights.\n", 716 | "- Based on the state, call functions to change the state of each light accordingly.\n", 717 | "\n", 718 | "This iterative process, where the AI can call a function, check the result, and then decide the next step, is known as function calling.\n", 719 | "\n", 720 | "```\n", 721 | "Comparison of Planners <> Plugins:\n", 722 | "```\n", 723 | "**Purpose:**\n", 724 | "- *Planners:* Focus on orchestrating and managing the execution of multiple functions to achieve a complex task.\n", 725 | "- *Plugins:* Provide the actual functions that perform specific tasks.\n", 726 | "\n", 727 | "**Functionality:**\n", 728 | "- *Planners:* Determine which functions to call and in what sequence, based on user requests.\n", 729 | "- *Plugins:* Contain the functions that perform the tasks as directed by the planner.\n", 730 | "\n", 731 | "**Integration:**\n", 732 | "- *Planners:* Work at a higher level, coordinating the use of multiple plugins to fulfill user needs.\n", 733 | "- *Plugins:* Operate at a lower level, providing the building blocks (functions) that the planner uses.\n", 734 | "\n", 735 | "In summary, planners and plugins work together within the Semantic Kernel to provide a flexible and powerful way to handle complex user requests. Planners orchestrate the process, while plugins provide the necessary functionality to execute specific tasks. \n", 736 | "\n", 737 | "```\n", 738 | "What the code is doing:\n", 739 | "```\n", 740 | "\n", 741 | "> The selected code is a C# file named \"tempcode.cs\". Let's go through it step by step.\n", 742 | "\n", 743 | "> First, there are some comments that provide information about the purpose of the code. It mentions that it is getting the latest package released on February 14th, 2024 from the NuGet package repository. The package being referenced is \"Microsoft.SemanticKernel\" with version 1.11.1.\n", 744 | "\n", 745 | "> Next, there are three lines starting with #r. These lines are known as \"reference directives\" and they are used to reference external assemblies or packages in C# code. In this case, the code is referencing three NuGet packages: \"Microsoft.SemanticKernel\", \"Microsoft.SemanticKernel.Plugins.Core\", and \"Microsoft.SemanticKernel.Planners.Handlebars\". The versions being referenced are 1.11.1, 1.11.1-alpha, and 1.11.1-preview respectively.\n", 746 | "\n", 747 | "> After the reference directives, there is a line starting with #!import. This line is likely a custom directive specific to the project or framework being used. It is importing a file named \"Settings.cs\".\n", 748 | "\n", 749 | "> The using statements follow, which are used to import namespaces into the current code file. In this case, the code is importing namespaces related to the \"Microsoft.SemanticKernel\" package and its plugins.\n", 750 | "\n", 751 | "> Next, a kernel builder object is created using the Kernel.CreateBuilder() method. The kernel builder is responsible for configuring and building the kernel, which is a central component of the \"Microsoft.SemanticKernel\" package.\n", 752 | "\n", 753 | "> The code then loads some settings from a file using the Settings.LoadFromFile() method. It retrieves values for variables such as useAzureOpenAI, model, azureEndpoint, apiKey, and orgId. These settings are used to configure the AI backend used by the kernel.\n", 754 | "\n", 755 | "> Based on the value of useAzureOpenAI, the code conditionally adds a chat completion plugin to the kernel builder. If useAzureOpenAI is true, it adds an Azure OpenAI chat completion plugin with the parameters \"gpt-4-default\", azureEndpoint, and apiKey. Otherwise, it adds an OpenAI chat completion plugin with the parameters model, apiKey, and orgId.\n", 756 | "\n", 757 | "> After that, there are several lines that add plugins to the kernel builder. The builder.Plugins.AddFromType() method is used to add plugins based on their type. In this case, it adds plugins of type TimePlugin and ConversationSummaryPlugin. Additionally, the builder.Plugins.AddFromPromptDirectory() method is used to add plugins from specific directories. It adds plugins from the directories \"plugins/FoodPlugin\" and \"plugins/ShoppingPlugin\".\n", 758 | "\n", 759 | "> Overall, this code sets up the configuration for the \"Microsoft.SemanticKernel\" package by adding references, importing namespaces, creating a kernel builder, loading settings, and adding plugins to the builder. It demonstrates how to configure and customize the behavior of the kernel for specific AI tasks." 760 | ] 761 | }, 762 | { 763 | "cell_type": "code", 764 | "execution_count": null, 765 | "metadata": { 766 | "dotnet_interactive": { 767 | "language": "csharp" 768 | }, 769 | "polyglot_notebook": { 770 | "kernelName": "csharp" 771 | }, 772 | "vscode": { 773 | "languageId": "polyglot-notebook" 774 | } 775 | }, 776 | "outputs": [], 777 | "source": [ 778 | "\n", 779 | "// Getting the latest package released on 14th Feb, 2024 - https://www.nuget.org/packages/Microsoft.SemanticKernel/\n", 780 | "#r \"nuget: Microsoft.SemanticKernel, 1.11.1\"\n", 781 | "#r \"nuget: Microsoft.SemanticKernel.Plugins.Core, 1.11.1-alpha\"\n", 782 | "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.11.1-preview\"\n", 783 | "\n", 784 | "#!import Settings.cs\n", 785 | "\n", 786 | "using Microsoft.SemanticKernel;\n", 787 | "using Microsoft.SemanticKernel.Plugins.Core;\n", 788 | "using Microsoft.SemanticKernel.Planning.Handlebars;\n", 789 | "using Kernel = Microsoft.SemanticKernel.Kernel;\n", 790 | "\n", 791 | "//Create Kernel builder\n", 792 | "var builder = Kernel.CreateBuilder();\n", 793 | "\n", 794 | "// Configure AI backend used by the kernel\n", 795 | "var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n", 796 | "if (useAzureOpenAI)\n", 797 | " builder.AddAzureOpenAIChatCompletion(\"gpt-4-default\", azureEndpoint, apiKey);\n", 798 | "else\n", 799 | " builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n", 800 | "\n", 801 | "\n", 802 | "#pragma warning disable SKEXP0050\n", 803 | "builder.Plugins.AddFromType();\n", 804 | "builder.Plugins.AddFromType();\n", 805 | "builder.Plugins.AddFromPromptDirectory(\"plugins/FoodPlugin\");\n", 806 | "builder.Plugins.AddFromPromptDirectory(\"plugins/ShoppingPlugin\");\n", 807 | "\n" 808 | ] 809 | }, 810 | { 811 | "cell_type": "markdown", 812 | "metadata": {}, 813 | "source": [ 814 | "### 5.1 Generating a Food Recipe " 815 | ] 816 | }, 817 | { 818 | "cell_type": "code", 819 | "execution_count": null, 820 | "metadata": { 821 | "dotnet_interactive": { 822 | "language": "csharp" 823 | }, 824 | "polyglot_notebook": { 825 | "kernelName": "csharp" 826 | }, 827 | "vscode": { 828 | "languageId": "polyglot-notebook" 829 | } 830 | }, 831 | "outputs": [], 832 | "source": [ 833 | "var kernel = builder.Build();\n", 834 | "\n", 835 | "string foodRecipe = \"Belgian\";\n", 836 | "var foodRecipeResult = await kernel.InvokeAsync(\"FoodPlugin\",\"GetRecipe\", new KernelArguments() { [\"input\"] = foodRecipe } );\n", 837 | "Console.WriteLine(foodRecipeResult.GetValue());" 838 | ] 839 | }, 840 | { 841 | "cell_type": "markdown", 842 | "metadata": {}, 843 | "source": [ 844 | "### 5.2 Compose a shopping list, based on the recipe" 845 | ] 846 | }, 847 | { 848 | "cell_type": "code", 849 | "execution_count": null, 850 | "metadata": { 851 | "dotnet_interactive": { 852 | "language": "csharp" 853 | }, 854 | "polyglot_notebook": { 855 | "kernelName": "csharp" 856 | }, 857 | "vscode": { 858 | "languageId": "polyglot-notebook" 859 | } 860 | }, 861 | "outputs": [], 862 | "source": [ 863 | "var groceryListResult = await kernel.InvokeAsync(\"ShoppingPlugin\",\"GetGroceryList\", new KernelArguments() { [\"input\"] = foodRecipe } );\n", 864 | "Console.WriteLine(groceryListResult.GetValue());" 865 | ] 866 | }, 867 | { 868 | "cell_type": "markdown", 869 | "metadata": {}, 870 | "source": [ 871 | "### 5.3 Planners & Plugins combined" 872 | ] 873 | }, 874 | { 875 | "cell_type": "markdown", 876 | "metadata": {}, 877 | "source": [ 878 | "In this example, we bring the power of previously described Plugins and Planners together. Using an ask, reflecting a (somewhat complex, multiple component-based) prompt provided by the user, we rely on the planner to come up with a plan. We use the plan contents as a guideline to:\n", 879 | "- show you the different iterations from understanding the prompt, \n", 880 | "- analyzing the context through Natural Language Processing, \n", 881 | "- identifying the different Plugins to use to get to the result, \n", 882 | "- and eventually showing the actual answer to the ask." 883 | ] 884 | }, 885 | { 886 | "cell_type": "code", 887 | "execution_count": null, 888 | "metadata": { 889 | "dotnet_interactive": { 890 | "language": "csharp" 891 | }, 892 | "polyglot_notebook": { 893 | "kernelName": "csharp" 894 | }, 895 | "vscode": { 896 | "languageId": "polyglot-notebook" 897 | } 898 | }, 899 | "outputs": [], 900 | "source": [ 901 | "#pragma warning disable SKEXP0060, SKEXP0061\n", 902 | "var kernel = builder.Build();\n", 903 | "var executionSettings = new OpenAIPromptExecutionSettings()\n", 904 | "{\n", 905 | " MaxTokens = 500,\n", 906 | " Temperature = 0.5\n", 907 | "};\n", 908 | "\n", 909 | "HandlebarsPlanner planner = new HandlebarsPlanner(new HandlebarsPlannerOptions() { ExecutionSettings = executionSettings, AllowLoops = true } );\n", 910 | "\n", 911 | "#pragma warning disable SKEXP0060\n", 912 | "\n", 913 | "var ask = \"My friend is visiting from Belgium. He wants to have a typical Belgian dish for dinner. Please suggest us a Belgian dish for dinner as well as the grocery list for the same. Show the output in a clear format with the distinguished sections for the dish and the grocery list. Also summarise everything in one line after the description.\";\n", 914 | "\n", 915 | "var plan = await planner.CreatePlanAsync(kernel, ask);\n", 916 | "\n", 917 | "Console.WriteLine(\"Original plan:\\n\");\n", 918 | "Console.WriteLine(plan);" 919 | ] 920 | }, 921 | { 922 | "cell_type": "code", 923 | "execution_count": null, 924 | "metadata": { 925 | "dotnet_interactive": { 926 | "language": "csharp" 927 | }, 928 | "polyglot_notebook": { 929 | "kernelName": "csharp" 930 | }, 931 | "vscode": { 932 | "languageId": "polyglot-notebook" 933 | } 934 | }, 935 | "outputs": [], 936 | "source": [ 937 | "#pragma warning disable SKEXP0060\n", 938 | "\n", 939 | "var planResult = await plan.InvokeAsync(kernel, new KernelArguments());\n", 940 | "\n", 941 | "Console.WriteLine(\"Original Plan results:\\n\");\n", 942 | "Console.WriteLine(planResult.ToString(), 1000);" 943 | ] 944 | }, 945 | { 946 | "cell_type": "markdown", 947 | "metadata": {}, 948 | "source": [ 949 | "### 6. Personas\n", 950 | "\n", 951 | "Often called a \"meta prompt\" or \"instruction\", the [persona](https://learn.microsoft.com/en-us/semantic-kernel/concepts/personas?pivots=programming-language-csharp#using-system-messages-to-set-personas) is a prompt that is used to influence how the agent responds. This allows you to influence how your agents plan tasks, generate responses, and interact with users. For example, you can use the persona to explicitly tell the agent to ask for help if it doesn't know what to do, or to be more verbose when it is explaining something.\n", 952 | "\n", 953 | "In Semantic Kernel, we often describe these prompts as \"personas\" because they're very similar to persona in user experience design. Just like how designers and UX researchers create personas to represent different types of users and the jobs-to-be-done they have, you can create personas to represent different types of agents and the tasks they are responsible for.\n", 954 | "\n", 955 | "By doing so, you can create agents that are more consistent, more reliable, and more predictable. You can also use personas to 'ground' your data, by describing its capabilities, but also what it is not allowed to do. Having a persona as travel agent, should not be able to describe how to fix your car..." 956 | ] 957 | }, 958 | { 959 | "cell_type": "code", 960 | "execution_count": null, 961 | "metadata": { 962 | "dotnet_interactive": { 963 | "language": "csharp" 964 | }, 965 | "polyglot_notebook": { 966 | "kernelName": "csharp" 967 | }, 968 | "vscode": { 969 | "languageId": "polyglot-notebook" 970 | } 971 | }, 972 | "outputs": [], 973 | "source": [ 974 | "// Getting the latest package released on 14th Feb, 2024 - https://www.nuget.org/packages/Microsoft.SemanticKernel/\n", 975 | "#r \"nuget: Microsoft.SemanticKernel, 1.11.1\"\n", 976 | "#r \"nuget: Microsoft.SemanticKernel.Plugins.Core, 1.11.1-alpha\"\n", 977 | "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.11.1-preview\"\n", 978 | "\n", 979 | "#!import Settings.cs\n", 980 | "\n", 981 | "using System;\n", 982 | "using Microsoft.SemanticKernel;\n", 983 | "using Microsoft.SemanticKernel.Plugins;\n", 984 | "\n", 985 | "// Build the kernel\n", 986 | "Kernel kernel = builder.Build();\n", 987 | "\n", 988 | "string language = \"French\";\n", 989 | "string language2 = \"Dutch\";\n", 990 | "string history = @\"I'm traveling with my kids and one of them has a peanut allergy.\";\n", 991 | "\n", 992 | "// Assign a persona to the prompt\n", 993 | "string prompt = @$\"\n", 994 | " You are a travel assistant. You are helpful, creative, and very friendly. \n", 995 | " Consider the traveler's background:\n", 996 | " ${history}\n", 997 | "\n", 998 | " Create a list of 10 helpful phrases and words in ${language} and ${language2} a traveler would find useful.\n", 999 | "\n", 1000 | " Group phrases by category. Include common direction words. \n", 1001 | " Display the phrases in the following format: \n", 1002 | " Hello - Ciao [chow]\n", 1003 | "\n", 1004 | " Begin with: 'Here are some phrases in ${language} you may find helpful:'\n", 1005 | " Followed by: 'And the same phrases in ${language2}:' \n", 1006 | " and end with: 'I hope this helps you on your trip!'\";\n", 1007 | "\n", 1008 | "var result = await kernel.InvokePromptAsync(prompt);\n", 1009 | "Console.WriteLine(result);\n", 1010 | " \n", 1011 | "\n" 1012 | ] 1013 | }, 1014 | { 1015 | "cell_type": "code", 1016 | "execution_count": null, 1017 | "metadata": { 1018 | "dotnet_interactive": { 1019 | "language": "csharp" 1020 | }, 1021 | "polyglot_notebook": { 1022 | "kernelName": "csharp" 1023 | }, 1024 | "vscode": { 1025 | "languageId": "polyglot-notebook" 1026 | } 1027 | }, 1028 | "outputs": [], 1029 | "source": [] 1030 | } 1031 | ], 1032 | "metadata": { 1033 | "kernelspec": { 1034 | "display_name": ".NET (C#)", 1035 | "language": "C#", 1036 | "name": ".net-csharp" 1037 | }, 1038 | "language_info": { 1039 | "name": "python", 1040 | "version": "3.9.13" 1041 | }, 1042 | "orig_nbformat": 4, 1043 | "polyglot_notebook": { 1044 | "kernelInfo": { 1045 | "defaultKernelName": "csharp", 1046 | "items": [ 1047 | { 1048 | "aliases": [], 1049 | "name": "csharp" 1050 | } 1051 | ] 1052 | } 1053 | } 1054 | }, 1055 | "nbformat": 4, 1056 | "nbformat_minor": 2 1057 | } 1058 | --------------------------------------------------------------------------------