{"id":3569,"date":"2024-10-28T09:21:16","date_gmt":"2024-10-28T16:21:16","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/semantic-kernel\/?p=3569"},"modified":"2024-10-28T09:21:16","modified_gmt":"2024-10-28T16:21:16","slug":"diving-into-function-calling-and-its-json-schema-in-semantic-kernel-net","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/agent-framework\/diving-into-function-calling-and-its-json-schema-in-semantic-kernel-net\/","title":{"rendered":"Diving into Function Calling and its JSON Schema in Semantic Kernel .NET"},"content":{"rendered":"<h1 id=\"diving-into-function-calling-and-its-json-schema-in-semantic-kernel-c\">Diving into Function Calling and its JSON Schema in Semantic Kernel .NET<\/h1>\n<p><strong>Function-calling<\/strong>\u00a0is one of the most exciting features of certain Large Language Models (LLMs), enabling developers to execute code directly in response to user queries. In Semantic Kernel, we streamline the process by allowing you to use built-in plugins or integrate your own code with ease. Today, we\u2019ll explore how Semantic Kernel creates a function-calling JSON schema\u2014a critical component that helps the model determine which function to invoke in various contexts.<\/p>\n<p>For those unfamiliar, function-calling refers to running local code, often on a user&#8217;s machine or within their deployment, to satisfy a user&#8217;s query to an LLM. If you\u2019ve ever asked an LLM to perform math calculations without the code interpreter, you might have noticed it sometimes produces inaccurate results. Since LLMs generate responses based on probabilistic models, the outcome may not always be correct for operations like large number addition (e.g., 102982 + 2828381). To handle such deterministic tasks more accurately, we use function calling. For further reading, check out OpenAI&#8217;s\u00a0<a href=\"https:\/\/platform.openai.com\/docs\/guides\/function-calling\" target=\"_blank\" rel=\"nofollow noopener\">function calling documentation<\/a>.<\/p>\n<p>Semantic Kernel provides abstractions over various LLMs. When a user configures their execution settings with\u00a0<code>functionChoiceBehavior = FunctionChoiceBehavior.Auto();<\/code>, the SDK includes a special JSON payload with a\u00a0<code>tools<\/code>\u00a0attribute in the request settings. We\u2019ll explore different plugin\/function configurations and the JSON payloads they generate.<\/p>\n<h2 id=\"a-simple-example-adding-two-numbers\">A Simple Example: Adding Two Numbers<\/h2>\n<p>Let&#8217;s start with a simple example of adding two numbers. Here\u2019s a Semantic Kernel (SK) plugin\/function:<\/p>\n<pre><code class=\"csharp\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ A sample Math Plugin.\r\n\/\/\/ &lt;\/summary&gt;\r\n[KernelFunction, Description(\"Adds two numbers together and provides the result\")]\r\n[return: Description(\"The result of adding the two numbers\")]\r\npublic int AddNumbers(\r\n    [Description(\"The first number to add\")] int numberOne,\r\n    [Description(\"The second number to add\")] int numberTwo)\r\n{\r\n    \/\/ A sample Semantic Kernel Function to add two numbers.\r\n    return numberOne + numberTwo;\r\n}<\/code><\/pre>\n<p>Once the C# code is compiled and executed, the Semantic Kernel SDK scans for functions marked with the\u00a0<code>[KernelFunction]<\/code>\u00a0attribute. It parses these functions for their names, input parameters, and output types, which are stored in\u00a0<code>KernelParameterMetadata<\/code>. This metadata is crucial for building the JSON schema the model uses to call the correct function.<\/p>\n<p>The\u00a0<code>Description<\/code>\u00a0attributes help provide context to the model about the function\u2019s purpose and the expected inputs and outputs.<\/p>\n<h3 id=\"json-schema-for-the-addnumbers-plugin\">JSON Schema for the AddNumbers Plugin<\/h3>\n<p>As mentioned, the information parsed from a kernel function is stored in KernelParameterMetadata. When constructing the JSON schema, we classify the parameter type\u2014integer, string, boolean, or object.<\/p>\n<p>Here\u2019s the JSON schema for the AddNumbers plugin:<\/p>\n<pre><code class=\"json\">{\r\n    \"type\": \"function\",\r\n    \"function\": {\r\n        \"name\": \"Math_AddNumbers\",\r\n        \"description\": \"Adds two numbers together and provides the result\",\r\n        \"parameters\": {\r\n            \"type\": \"object\",\r\n            \"properties\": {\r\n                \"numberOne\": {\r\n                    \"type\": \"integer\",\r\n                    \"description\": \"The first number to add\"\r\n                },\r\n                \"numberTwo\": {\r\n                    \"type\": \"integer\",\r\n                    \"description\": \"The second number to add\"\r\n                }\r\n            },\r\n            \"required\": [\r\n                \"numberOne\", \"numberTwo\"\r\n            ]\r\n        }\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>The schema specifies that both\u00a0<code>numberOne<\/code>\u00a0and\u00a0<code>numberTwo<\/code>\u00a0are required integer inputs. This schema enables the model to recognize which parameters are necessary for this function call.<\/p>\n<h2 id=\"a-more-complex-example-working-with-complex-types\">A More Complex Example: Working with Complex Types<\/h2>\n<p>Let\u2019s explore a more advanced example with complex data types. First, we\u2019ll define a C# model class\u00a0<code>ComplexRequest<\/code>, which contains two properties &#8211;\u00a0<code>StartDate<\/code>\u00a0and\u00a0<code>EndDate<\/code>. These properties are annotated with\u00a0<code>DataAnnotations<\/code>\u00a0attributes to indicate that they are required and to provide descriptions and example values. You can refer to the\u00a0<a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.componentmodel.dataannotations?view=net-8.0\" target=\"_blank\" rel=\"nofollow noopener\">DataAnnotations<\/a>\u00a0for more details on using these annotations in C#.<\/p>\n<h3 id=\"defining-the-model-class\">Defining the Model Class<\/h3>\n<pre><code class=\"csharp\">public class ComplexRequest\r\n{\r\n    [Required]\r\n    [Display(Description = \"The start date in ISO 8601 format\")]\r\n    public string StartDate { get; set; }\r\n\r\n    [Required]\r\n    [Display(Description = \"The end date in ISO 8601 format\")]\r\n    public string EndDate { get; set; }\r\n\r\n    \/\/ Example values\r\n    public static readonly string[] StartDateExamples = { \"2023-01-01\", \"2024-05-20\" };\r\n    public static readonly string[] EndDateExamples = { \"2023-01-01\", \"2024-05-20\" };\r\n}\r\n<\/code><\/pre>\n<p>Next, we define a plugin named\u00a0<code>ComplexTypePlugin<\/code>, containing a function\u00a0<code>BookHoliday<\/code>\u00a0that accepts a\u00a0<code>ComplexRequest<\/code>\u00a0object.<\/p>\n<h3 id=\"creating-the-plugin\">Creating the Plugin<\/h3>\n<pre><code class=\"csharp\">public class ComplexTypePlugin\r\n{\r\n    [KernelFunction, Description(\"Answer a request\")]\r\n    [return: Description(\"The result is the boolean value True if successful, False if unsuccessful.\")]\r\n    public bool BookHoliday \r\n            ([Description(\"A request to answer.\")] \r\n             ComplexRequest request)\r\n    {\r\n        return true;\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>This kernel function\u2019s input parameter\u00a0<code>request<\/code>\u00a0is of type\u00a0<code>ComplexRequest<\/code>. When the SDK parses this function, it recurses through the\u00a0<code>ComplexRequest<\/code>\u00a0class to identify the required properties, like\u00a0<code>StartDate<\/code>\u00a0and\u00a0<code>EndDate<\/code>, for inclusion in the JSON schema.<\/p>\n<h3 id=\"json-schema-for-complex-types\">JSON Schema for Complex Types<\/h3>\n<p>Here\u2019s the generated JSON schema:<\/p>\n<pre><code class=\"json\">{\r\n    \"type\": \"function\",\r\n    \"function\": {\r\n        \"name\": \"complex-book_holiday\",\r\n        \"description\": \"Answer a request\",\r\n        \"parameters\": {\r\n            \"type\": \"object\",\r\n            \"properties\": {\r\n                \"request\": {\r\n                    \"type\": \"object\",\r\n                    \"properties\": {\r\n                        \"StartDate\": {\r\n                            \"type\": \"string\",\r\n                            \"description\": \"The start date in ISO 8601 format\"\r\n                        },\r\n                        \"EndDate\": {\r\n                            \"type\": \"string\",\r\n                            \"description\": \"The end date in ISO 8601 format\"\r\n                        }\r\n                    },\r\n                    \"required\": [\r\n                        \"StartDate\",\r\n                        \"EndDate\"\r\n                    ],\r\n                    \"description\": \"A request to answer.\"\r\n                }\r\n            },\r\n            \"required\": [\r\n                \"request\"\r\n            ]\r\n        }\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>The schema breaks down the\u00a0<code>ComplexRequest<\/code>\u00a0object into its individual properties, ensuring that the required fields\u00a0<code>StartDate<\/code>\u00a0and\u00a0<code>EndDate<\/code>\u00a0are validated before the function call proceeds.<\/p>\n<h2 id=\"example-interaction\">Example Interaction<\/h2>\n<p>When this plugin is used in a model, you might see an interaction like this:<\/p>\n<pre><code class=\"bash\">User: &gt; Answer a request for me.\r\nAssistant: &gt; Certainly! Please provide me with the start date and end date for your request, and I shall endeavor to assist you with it!\r\n<\/code><\/pre>\n<p>I can then respond with:<\/p>\n<pre><code class=\"bash\">User: &gt; The start date is Feb 10, 2023 to Mar 10, 2024.\r\nAssistant: &gt; The request has been successfully answered with a resounding \"True\"! If there are any further inquiries or additional assistance you seek, do not hesitate to ask!\r\n<\/code><\/pre>\n<p>You\u2019ll notice that I didn\u2019t need to format my exact dates in ISO-8601 format. We can tell the model how to format the dates, and it will follow along to the best of its ability. The following dates are what the model returned as part of the function call arguments:<\/p>\n<pre><code class=\"bash\">request.start_date = '2023-02-10'\r\nrequest.end_date = '2024-03-10'\r\n<\/code><\/pre>\n<p>Then, our plugin code that expects the ISO-8601 format can proceed without a hitch.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>In summary, we&#8217;ve explored function calling within the Semantic Kernel SDK, focusing on JSON schema construction and the importance of parameter communication. To sum up:<\/p>\n<ol>\n<li>We can provide string descriptions via the\u00a0<code>KernelFunction<\/code>\u00a0attribute\u2019s\u00a0<code>Description<\/code>\u00a0parameter and input parameter descriptions to help give the model more context about our function or parameters.<\/li>\n<li>We can define complex objects that use underlying complex type objects, along with annotations or models to give further information and context to the model, which can aid it in choosing the correct function to invoke to complete the user\u2019s query.<\/li>\n<\/ol>\n<p>For complete implementations around handling auto function calling in dotnet\/C#, please see our code samples\u00a0<a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/tree\/main\/dotnet\/samples\/Concepts\/FunctionCalling\" target=\"_blank\" rel=\"nofollow noopener\">FunctionCalling in dotnet<\/a>.<\/p>\n<p>As we continue bringing you new features in Semantic Kernel, we want to highlight that we are tracking an\u00a0<a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/issues\/7946\" target=\"_blank\" rel=\"nofollow noopener\">issue<\/a>\u00a0related adding support for OpenAI\u2019s structured outputs. If you\u2019re looking for a challenge on the C# side and want to help us out with this, please feel free to comment on the open issue we\u2019re tracking or create a\u00a0<a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/discussions\" target=\"_blank\" rel=\"nofollow noopener\">GitHub discussion<\/a>\u00a0to let us know you\u2019d like to assist with the integration. We\u2019ll be happy to work with you.<\/p>\n<p>Thank you for your time, and we welcome any feedback related to this post or Semantic Kernel in general.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Diving into Function Calling and its JSON Schema in Semantic Kernel .NET Function-calling\u00a0is one of the most exciting features of certain Large Language Models (LLMs), enabling developers to execute code directly in response to user queries. In Semantic Kernel, we streamline the process by allowing you to use built-in plugins or integrate your own code [&hellip;]<\/p>\n","protected":false},"author":149071,"featured_media":2311,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[78,47],"tags":[79,48,63,9],"class_list":["post-3569","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-announcement","tag-net","tag-ai","tag-microsoft-semantic-kernel","tag-semantic-kernel"],"acf":[],"blog_post_summary":"<p>Diving into Function Calling and its JSON Schema in Semantic Kernel .NET Function-calling\u00a0is one of the most exciting features of certain Large Language Models (LLMs), enabling developers to execute code directly in response to user queries. In Semantic Kernel, we streamline the process by allowing you to use built-in plugins or integrate your own code [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/3569","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\/149071"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/comments?post=3569"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/3569\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media\/2311"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media?parent=3569"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/categories?post=3569"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/tags?post=3569"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}