From 1b9abcd85560b7d526c99731c660ed9e9e21d6c2 Mon Sep 17 00:00:00 2001 From: wtulloch Date: Fri, 7 Mar 2025 11:14:55 +0000 Subject: [PATCH 1/6] Fixed C# example code so that it is actually executable --- 02-explore-agentic-frameworks/README.md | 64 ++++++++++++------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/02-explore-agentic-frameworks/README.md b/02-explore-agentic-frameworks/README.md index 279e96bb..6718d012 100644 --- a/02-explore-agentic-frameworks/README.md +++ b/02-explore-agentic-frameworks/README.md @@ -150,41 +150,34 @@ async def main(): if __name__ == "__main__": asyncio.run(main()) ``` - ```csharp // Semantic Kernel C# example -ChatHistory chatHistory = []; - -chatHistory.AddUserMessage("I'd like to go to New York on January 1, 2025."); - - -// Define a plugin that contains the function to book travel -public class BookTravelPlugin( - IPizzaService pizzaService, - IUserContext userContext, - IPaymentService paymentService) -{ +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.ChatCompletion; +using System.ComponentModel; +using Microsoft.SemanticKernel.Connectors.AzureOpenAI; - [KernelFunction("book_flight")] - [Description("Book travel given location and date")] - public async Task BookFlight( - DateTime date, - string location, - ) - { - // book travel given date,location - } -} +ChatHistory chatHistory = []; +chatHistory.AddUserMessage("I'd like to go to New York on January 1, 2025"); -IKernelBuilder kernelBuilder = new KernelBuilder(); +var kernelBuilder = Kernel.CreateBuilder(); kernelBuilder.AddAzureOpenAIChatCompletion( deploymentName: "NAME_OF_YOUR_DEPLOYMENT", apiKey: "YOUR_API_KEY", endpoint: "YOUR_AZURE_ENDPOINT" ); -kernelBuilder.Plugins.AddFromType("BookTravel"); -Kernel kernel = kernelBuilder.Build(); +kernelBuilder.Plugins.AddFromType("BookTravel"); +var kernel = kernelBuilder.Build(); + +var settings = new AzureOpenAIPromptExecutionSettings() +{ + FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() +}; + +var chatCompletion = kernel.GetRequiredService(); + +var response = await chatCompletion.GetChatMessageContentAsync(chatHistory, settings, kernel); /* Behind the scenes, the model recognizes the tool to call, what arguments it already has (location) and (date) @@ -202,16 +195,21 @@ Behind the scenes, the model recognizes the tool to call, what arguments it alre ] */ -ChatResponse response = await chatCompletion.GetChatMessageContentAsync( - chatHistory, - executionSettings: openAIPromptExecutionSettings, - kernel: kernel) - - -Console.WriteLine(response); -chatHistory.AddAssistantMessage(response); +Console.WriteLine(response.Content); +chatHistory.AddMessage(response!.Role, response!.Content!); // Example AI Model Response: Your flight to New York on January 1, 2025, has been successfully booked. Safe travels! ✈️🗽 + +// Define a plugin that contains the function to book travel +public class BookTravelPlugin +{ + [KernelFunction("book_flight")] + [Description("Book travel given location and date")] + public async Task BookFlight(DateTime date, string location) + { + return await Task.FromResult( $"Travel was booked to {location} on {date}"); + } +} ``` What you can see from this example is how you can leverage a pre-built parser to extract key information from user input, such as the origin, destination, and date of a flight booking request. This modular approach allows you to focus on the high-level logic. From 159cd698cc7995532a0ad0af6bfaa0930321040c Mon Sep 17 00:00:00 2001 From: wtulloch Date: Fri, 7 Mar 2025 11:25:42 +0000 Subject: [PATCH 2/6] minor readability fix --- 02-explore-agentic-frameworks/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/02-explore-agentic-frameworks/README.md b/02-explore-agentic-frameworks/README.md index 6718d012..25c8af9e 100644 --- a/02-explore-agentic-frameworks/README.md +++ b/02-explore-agentic-frameworks/README.md @@ -273,7 +273,7 @@ There are many ways to compare these frameworks, but let's look at some key diff ## AutoGen -Open-source framework developed by Microsoft Research's AI Frontiers Lab. Focuses on event-driven, distributed *agentic* applications, enabling multiple LLMs and SLMs, tools, and advanced multi-agent design patterns. +AutoGen is an open-source framework developed by Microsoft Research's AI Frontiers Lab. It Focuses on event-driven, distributed *agentic* applications, enabling multiple LLMs and SLMs, tools, and advanced multi-agent design patterns. AutoGen is built around the core concept of agents, which are autonomous entities that can perceive their environment, make decisions, and take actions to achieve specific goals. Agents communicate through asynchronous messages, allowing them to work independently and in parallel, enhancing system scalability and responsiveness. From 5b9063594212c988af23d3c0e8165213b2ae0e50 Mon Sep 17 00:00:00 2001 From: wtulloch Date: Fri, 7 Mar 2025 12:01:04 +0000 Subject: [PATCH 3/6] Updated c# example of creating function from prompt --- 02-explore-agentic-frameworks/README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/02-explore-agentic-frameworks/README.md b/02-explore-agentic-frameworks/README.md index 25c8af9e..a955cd21 100644 --- a/02-explore-agentic-frameworks/README.md +++ b/02-explore-agentic-frameworks/README.md @@ -477,15 +477,18 @@ Let's first cover some core components: string skPrompt = @"Summarize the provided unstructured text in a sentence that is easy to understand. Text to summarize: {{$userInput}}"; - // Register the function - kernel.CreateSemanticFunction( + // create the function from the prompt + KernelFunction summarizeFunc = kernel.CreateFunctionFromPrompt( promptTemplate: skPrompt, - functionName: "SummarizeText", - pluginName: "SemanticFunctions" + functionName: "SummarizeText" ); + + //then import into the current kernel + kernel.ImportPluginFromFunctions("SemanticFunctions", [summarizeFunc]); + ``` - Here, you first have a template prompt `skPrompt` that leaves room for the user to input text, `$userInput`. Then you register the function `SummarizeText` with the plugin `SemanticFunctions`. Note the name of the function that helps Semantic Kernel understand what the function does and when it should be called. + Here, you first have a template prompt `skPrompt` that leaves room for the user to input text, `$userInput`. Then you create the kernel function `SummarizeText` and then import it into the kernel with the plugin name `SemanticFunctions`. Note the name of the function that helps Semantic Kernel understand what the function does and when it should be called. - **Native function**: There's also native functions that the framework can call directly to carry out the task. Here's an example of such a function retrieving the content from a file: From 68ae52c2ed00efbe2be93c2dd130c8799bb45803 Mon Sep 17 00:00:00 2001 From: wtulloch Date: Sat, 8 Mar 2025 08:40:31 +0000 Subject: [PATCH 4/6] Removed the section on planning in Semantic kernel has been deprecated --- 02-explore-agentic-frameworks/README.md | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/02-explore-agentic-frameworks/README.md b/02-explore-agentic-frameworks/README.md index a955cd21..1bb5fded 100644 --- a/02-explore-agentic-frameworks/README.md +++ b/02-explore-agentic-frameworks/README.md @@ -509,29 +509,14 @@ Let's first cover some core components: string functionName = "RetrieveLocalFile"; var nativeFunctions = new NativeFunctions(); - kernel.ImportFunctions(nativeFunctions, plugInName); - ``` + //This imports the instance created + kernel.ImportPluginFromObject(nativeFunctions, pluginName); -- **Planner**: The planner orchestrates execution plans and strategies based on user input. The idea is to express how things should be carried out which then surveys as an instruction for Semantic Kernel to follow. It then invokes the necessary functions to carry out the task. Here's an example of such a plan: + //alternatively just use + kernel.ImportPluginFromType(); - ```csharp - string planDefinition = "Read content from a local file and summarize the content."; - SequentialPlanner sequentialPlanner = new SequentialPlanner(kernel); - - string assetsFolder = @"../../assets"; - string fileName = Path.Combine(assetsFolder,"docs","06_SemanticKernel", "aci_documentation.txt"); - - ContextVariables contextVariables = new ContextVariables(); - contextVariables.Add("fileName", fileName); - - var customPlan = await sequentialPlanner.CreatePlanAsync(planDefinition); - - // Execute the plan - KernelResult kernelResult = await kernel.RunAsync(contextVariables, customPlan); - Console.WriteLine($"Summarization: {kernelResult.GetValue()}"); ``` - Note especially `planDefinition` which is a simple instruction for the planner to follow. The appropriate functions are then called based on this plan, in this case our semantic function `SummarizeText` and the native function `RetrieveLocalFile`. - **Memory**: Abstracts and simplifies context management for AI apps. The idea with memory is that this is something the LLM should know about. You can store this information in a vector store which ends up being an in-memory database or a vector database or similar. Here's an example of a very simplified scenario where *facts* are added to the memory: ```csharp From 6ce44e4a93c69e91e0e2a159f07cf9bb21c20dd5 Mon Sep 17 00:00:00 2001 From: wtulloch Date: Sat, 8 Mar 2025 23:44:27 +0000 Subject: [PATCH 5/6] Clarified comment in README to specify that the alternative method resolves dependencies --- 02-explore-agentic-frameworks/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/02-explore-agentic-frameworks/README.md b/02-explore-agentic-frameworks/README.md index 1bb5fded..9a1ddc54 100644 --- a/02-explore-agentic-frameworks/README.md +++ b/02-explore-agentic-frameworks/README.md @@ -512,7 +512,7 @@ Let's first cover some core components: //This imports the instance created kernel.ImportPluginFromObject(nativeFunctions, pluginName); - //alternatively just use + //alternatively just use which will resolve dependencies kernel.ImportPluginFromType(); ``` From ee9985129f3c8a8beb3bea70b419e940cae8b6ad Mon Sep 17 00:00:00 2001 From: wtulloch Date: Sun, 9 Mar 2025 08:23:53 +0000 Subject: [PATCH 6/6] Applied fixes from copilot --- 02-explore-agentic-frameworks/README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/02-explore-agentic-frameworks/README.md b/02-explore-agentic-frameworks/README.md index 9a1ddc54..dc71a0a0 100644 --- a/02-explore-agentic-frameworks/README.md +++ b/02-explore-agentic-frameworks/README.md @@ -273,7 +273,7 @@ There are many ways to compare these frameworks, but let's look at some key diff ## AutoGen -AutoGen is an open-source framework developed by Microsoft Research's AI Frontiers Lab. It Focuses on event-driven, distributed *agentic* applications, enabling multiple LLMs and SLMs, tools, and advanced multi-agent design patterns. +AutoGen is an open-source framework developed by Microsoft Research's AI Frontiers Lab. It focuses on event-driven, distributed *agentic* applications, enabling multiple LLMs and SLMs, tools, and advanced multi-agent design patterns. AutoGen is built around the core concept of agents, which are autonomous entities that can perceive their environment, make decisions, and take actions to achieve specific goals. Agents communicate through asynchronous messages, allowing them to work independently and in parallel, enhancing system scalability and responsiveness. @@ -507,12 +507,8 @@ Let's first cover some core components: //Import native function string plugInName = "NativeFunction"; string functionName = "RetrieveLocalFile"; - - var nativeFunctions = new NativeFunctions(); - //This imports the instance created - kernel.ImportPluginFromObject(nativeFunctions, pluginName); - //alternatively just use which will resolve dependencies + //To add the functions to a kernel use the following function kernel.ImportPluginFromType(); ```