{"id":3011,"date":"2024-07-23T12:26:02","date_gmt":"2024-07-23T19:26:02","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/semantic-kernel\/?p=3011"},"modified":"2024-07-23T12:26:02","modified_gmt":"2024-07-23T19:26:02","slug":"planning-with-semantic-kernel-using-automatic-function-calling","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/agent-framework\/planning-with-semantic-kernel-using-automatic-function-calling\/","title":{"rendered":"Planning with Semantic Kernel using Automatic Function Calling"},"content":{"rendered":"<p>Hello, everyone!<\/p>\n<p>AI planning is a powerful tool that allows to generate and execute complex workflows in applications based on specified goal. In Semantic Kernel, it&#8217;s possible to implement planning logic using <code class=\"language-cs language-csharp\">FunctionCallingStepwisePlanner<\/code> class. Today we want to introduce a new way how to achieve the same results by using Automatic Function Calling. This approach produces the results more reliably and uses fewer tokens comparing to <code class=\"language-cs language-csharp\">FunctionCallingStepwisePlanner<\/code>.<\/p>\n<h2><strong>Setup<\/strong><\/h2>\n<p>For demonstration purposes, we will use 2 plugins to get current date\/time and weather:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">public sealed class TimePlugin\r\n{\r\n    [KernelFunction]\r\n    [Description(\"Retrieves the current time in UTC\")]\r\n    public string GetCurrentUtcTime() =&gt; DateTime.UtcNow.ToString(\"R\");\r\n}\r\n\r\npublic sealed class WeatherPlugin\r\n{\r\n    [KernelFunction]\r\n    [Description(\"Gets the current weather for the specified city\")]\r\n    public string GetWeatherForCity(string cityName) =&gt;\r\n        cityName switch\r\n        {\r\n            \"Boston\" =&gt; \"61 and rainy\",\r\n            \"London\" =&gt; \"55 and cloudy\",\r\n            \"Miami\" =&gt; \"80 and sunny\",\r\n            \"Paris\" =&gt; \"60 and rainy\",\r\n            \"Tokyo\" =&gt; \"50 and sunny\",\r\n            \"Sydney\" =&gt; \"75 and sunny\",\r\n            \"Tel Aviv\" =&gt; \"80 and sunny\",\r\n            _ =&gt; \"31 and snowing\",\r\n        };\r\n}\r\n<\/code><\/pre>\n<p>For simplicity, let&#8217;s define a helper function to initialize <code class=\"language-cs language-csharp\">Kernel<\/code> instance to use it across examples in this article:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">public static Kernel GetKernel()\r\n{\r\n    Kernel kernel = Kernel\r\n        .CreateBuilder()\r\n        .AddOpenAIChatCompletion(\"gpt-4\", Environment.GetEnvironmentVariable(\"OpenAI__ApiKey\"))\r\n        .Build();\r\n\r\n    \/\/ Import sample plugins.\r\n    kernel.ImportPluginFromType&lt;TimePlugin&gt;();\r\n    kernel.ImportPluginFromType&lt;WeatherPlugin&gt;();\r\n\r\n    return kernel;\r\n}\r\n<\/code><\/pre>\n<h2><strong>Old approach with FunctionCallingStepwisePlanner<\/strong><\/h2>\n<p>Here is an example how to generate and execute a plan with <code class=\"language-cs language-csharp\">FunctionCallingStepwisePlanner<\/code>:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">\/\/ Get kernel\r\nKernel kernel = GetKernel();\r\n\r\n\/\/ Initialize planner\r\nFunctionCallingStepwisePlanner planner = new();\r\n\r\n\/\/ Generate and execute a plan\r\nFunctionCallingStepwisePlannerResult plannerResult = await planner.ExecuteAsync(kernel, \"Check current UTC time and return current weather in Boston city.\");\r\n\r\nConsole.WriteLine($\"Planner execution result: {plannerResult.FinalAnswer}\");\r\n\r\n\/\/ Output:\r\n\/\/ Planner execution result: The current UTC time is Sat, 06 Jul 2024 02:11:10 GMT and the weather in Boston is 61 and rainy.\r\n<\/code><\/pre>\n<p>It&#8217;s possible to get access to generated plan and see details for each step by using <code class=\"language-cs language-csharp\">plannerResult.ChatHistory<\/code>.\nIn current scenario with 2 plugins and defined goal, approximately <strong>1380<\/strong> tokens were used.<\/p>\n<h2><strong>New approach with Automatic Function Calling<\/strong><\/h2>\n<p>For Automatic Function Calling, <code class=\"language-cs language-csharp\">Kernel<\/code> object should be used with <code class=\"language-cs language-csharp\">ToolCallBehavior.AutoInvokeKernelFunctions<\/code> configured in execution settings. Here is an example:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">\/\/ Get kernel\r\nKernel kernel = GetKernel();\r\n\r\n\/\/ Enable Automatic Function Calling\r\nOpenAIPromptExecutionSettings executionSettings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };\r\n\r\n\/\/ Generate and execute a plan\r\nFunctionResult result = await kernel.InvokePromptAsync(\"Check current UTC time and return current weather in Boston city.\", new(executionSettings));\r\n\r\nConsole.WriteLine($\"Auto Function Calling execution result: {result}\");\r\n\r\n\/\/ Output:\r\n\/\/ Auto Function Calling execution result: The current UTC time is Sat, 06 Jul 2024 02:11:16 GMT. The weather right now in Boston is 61 degrees and rainy.\r\n<\/code><\/pre>\n<p>With Automatic Function Calling, planning result is the same, but token usage is significantly smaller &#8211; approximately <strong>240<\/strong> tokens.<\/p>\n<h3>Get generated plan with Automatic Function Calling<\/h3>\n<p>In both <code class=\"language-cs language-csharp\">FunctionCallingStepwisePlanner<\/code> and Automatic Function Calling approaches, generated plan lives in <code class=\"language-cs language-csharp\">ChatHistory<\/code> object. To get access to generated plan with Automatic Function Calling, <code class=\"language-cs language-csharp\">IChatCompletionService<\/code> should be used:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">\/\/ Get kernel\r\nKernel kernel = GetKernel();\r\n\r\n\/\/ Get chat completion service\r\nIChatCompletionService chatCompletionService = kernel.GetRequiredService();\r\n\r\n\/\/ Enable Automatic Function Calling\r\nOpenAIPromptExecutionSettings executionSettings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };\r\n\r\n\/\/ Initialize chat history\r\nChatHistory chatHistory = new();\r\nchatHistory.AddUserMessage(\"Check current UTC time and return current weather in Boston city.\");\r\n\r\n\/\/ Generate and execute a plan\r\nChatMessageContent result = await chatCompletionService.GetChatMessageContentAsync(chatHistory, executionSettings, kernel);\r\n\r\n\/\/ Result variable contains the result of executed plan.\r\n\/\/ ChatHistory contains generated plan with details for each step - function, arguments, function invocation result.\r\n<\/code><\/pre>\n<h2><strong>Summary<\/strong><\/h2>\n<p>Provided example shows how to use a new recommended approach for planning with Automatic Function Calling to achieve specified goal.<\/p>\n<p>By following links, you can find and run more examples for different planning scenarios such as telemetry for plan generation and execution, plan caching for reusability, using filters to control plan execution and more:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/blob\/main\/dotnet\/samples\/Concepts\/Planners\/AutoFunctionCallingPlanning.cs\">Planning with Automatic Function Calling concepts<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/tree\/main\/dotnet\/samples\/Demos\/StepwisePlannerMigration\">ASP.NET demo application with migration guide for Automatic Function Calling<\/a><\/li>\n<\/ul>\n<p>We\u2019re always interested in hearing from you. If you have feedback, questions or want to discuss further, feel free to reach out to us and the community on the<a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/discussions\">\u00a0discussion boards<\/a> on GitHub! We would also love your support, if you&#8217;ve enjoyed using Semantic Kernel, give us a star on <a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello, everyone! AI planning is a powerful tool that allows to generate and execute complex workflows in applications based on specified goal. In Semantic Kernel, it&#8217;s possible to implement planning logic using FunctionCallingStepwisePlanner class. Today we want to introduce a new way how to achieve the same results by using Automatic Function Calling. This approach [&hellip;]<\/p>\n","protected":false},"author":156732,"featured_media":2364,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[47,1],"tags":[48,63,9],"class_list":["post-3011","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-announcement","category-semantic-kernel","tag-ai","tag-microsoft-semantic-kernel","tag-semantic-kernel"],"acf":[],"blog_post_summary":"<p>Hello, everyone! AI planning is a powerful tool that allows to generate and execute complex workflows in applications based on specified goal. In Semantic Kernel, it&#8217;s possible to implement planning logic using FunctionCallingStepwisePlanner class. Today we want to introduce a new way how to achieve the same results by using Automatic Function Calling. This approach [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/3011","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/users\/156732"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/comments?post=3011"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/3011\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media\/2364"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media?parent=3011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/categories?post=3011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/tags?post=3011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}