{"id":11927,"date":"2025-10-19T10:15:42","date_gmt":"2025-10-19T10:15:42","guid":{"rendered":"https:\/\/putridparrot.com\/blog\/?p=11927"},"modified":"2025-10-19T10:15:42","modified_gmt":"2025-10-19T10:15:42","slug":"lets-create-a-chatbot-agent-using-azure-ai-foundry-and-semantic-kernel-with-c","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/lets-create-a-chatbot-agent-using-azure-ai-foundry-and-semantic-kernel-with-c\/","title":{"rendered":"Let&#8217;s create a chatbot\/agent using Azure AI Foundry and Semantic Kernel with C#"},"content":{"rendered":"<p><strong>Setting up a project and model in AI Foundry<\/strong><\/p>\n<p>Let&#8217;s start by creating a project in https:\/\/ai.azure.com\/<\/p>\n<p><em>Note: I&#8217;m going to create a very simple, pretty standard chatbot for a pizza delivery service, so my project is going be called pizza, so you&#8217;re see this in the code but ofcourse replace with your preferred example or real code as this is the same setup that you&#8217;ll do for your own chatbot anyway.<\/em><\/p>\n<ul>\n<li>Navigate to https:\/\/ai.azure.com\/<\/li>\n<li>Click Create new (if not available go to the <em>Management Center | All Resources<\/em> and the option should be there)<\/li>\n<li>Select the <em>Azure AI Foundry resource<\/em>, then click <em>Next<\/em><\/li>\n<li>Supply a project name, resource group (or create one) and region &#8211; I left this as Sweden Central as I&#8217;m sure I read that it was a little more advanced than some regions, but do pick one which suites.<\/li>\n<li>Click <em>Create<\/em><\/li>\n<\/ul>\n<p>Once completed you&#8217;ll be presented with the project page. <\/p>\n<p>We&#8217;re not quite done as we need to deploy a model&#8230;<\/p>\n<ul>\n<li>From the left hand nav. bar, locate <em>My assets<\/em> and click on <em>Models + endpoints<\/em>.<\/li>\n<li>Click <em>+ Deploy model<\/em><\/li>\n<li>Select <em>Deploy base model<\/em> from the drop down<\/li>\n<li>From the <em>Select a model<\/em> popup, choose a mode, I&#8217;ve selected <em>gpt-4o-mini<\/em> which is a good model for chat completion.<\/li>\n<li>Click <em>Confirm<\/em><\/li>\n<li>Give it a <em>Deployment name<\/em> and I&#8217;ve using the <em>Deployment type<\/em> as <em>Standard<\/em> and leaving all the new fields that appear as default<\/li>\n<li>Click <em>Deploy<\/em> to assign the model to the project<\/li>\n<\/ul>\n<p>We should now see some source code samples listed. We&#8217;ll partially be using in the code part of this, but before we move on we need an <em>endpoint<\/em> and an <em>api key<\/em>.<\/p>\n<ul>\n<li>From this page on the <em>Details<\/em> tab copy the Endpoint Target URI &#8211; but we don&#8217;t need the whole this, from the project overview we can get the cutdown version but it&#8217;s basically this https:\/\/{your project}.cognitiveservices.azure.com\/<\/li>\n<li>From below the Target URI copy the Key<\/li>\n<\/ul>\n<p><strong>Writing the code<\/strong><\/p>\n<p>Create a Console application using Visual Studio. <\/p>\n<p>Let&#8217;s begin be adding the following NuGet packages<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndotnet add package Microsoft.SemanticKernel\r\ndotnet add package Microsoft.Extensions.Configuration\r\ndotnet add package Microsoft.Extensions.Configuration.Json\r\n<\/pre>\n<p>We&#8217;re using (as you can see) Semantic Kernel, now the versions seem to change pretty quickly at the moment so hopefully the code below will work but if not check against the version you&#8217;re using. For completeness here&#8217;s my versions<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&lt;ItemGroup&gt;\r\n  &lt;PackageReference Include=&quot;Microsoft.Extensions.Configuration&quot; Version=&quot;9.0.10&quot; \/&gt;\r\n  &lt;PackageReference Include=&quot;Microsoft.Extensions.Configuration.Json&quot; Version=&quot;9.0.10&quot; \/&gt;\r\n  &lt;PackageReference Include=&quot;Microsoft.SemanticKernel&quot; Version=&quot;1.66.0&quot; \/&gt;\r\n&lt;\/ItemGroup&gt;\r\n<\/pre>\n<p>Create yourself an appsettings.json file, which should look like this<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n{\r\n  &quot;AI&quot;: {\r\n    &quot;Endpoint&quot;: &quot;&lt;The Endpoint&gt;&quot;,\r\n    &quot;ApiKey&quot;: &quot;&lt;Api Key&gt;&quot;,\r\n    &quot;ApiVersion&quot;: &quot;2024-12-01-preview&quot;,\r\n    &quot;DeploymentName&quot;:  &quot;pizza&quot;\r\n  }\r\n}\r\n<\/pre>\n<p>Obviously you&#8217;ll need to supply your endpoint and API key that we copied after creating our AI Foundry project.<\/p>\n<p>Now before we go onto look at implementing the Program.cs&#8230; I&#8217;m wanting this LLM to use some custom functions to fulfil a couple of tasks such as returning the menu and placing and order.<\/p>\n<p>The AI Foundry project is an LLM which is our chat bot and it can answer questions and also generate hallucinations etc. For example without supplying my functions it will try to create a pizza menu for me, but that&#8217;s not a lot of use to our pizza place.<\/p>\n<p>What I want is the Natural Language Processing (NLP) as well as the model&#8217;s &#8220;knowledge&#8221; to work with my functions &#8211; we implement this using Plugins.<\/p>\n<p>What I want to happens is this<\/p>\n<ul>\n<li>The customer connects to the chatbot\/LLM<\/li>\n<li>The customer then asks to either order a Pizza or for information on what Pizza&#8217;s we make, i.e. the menu<\/li>\n<li>The LLM then needs to pass information to the PizzaPlugin which then returns information to the LLM to respond to the customer<\/li>\n<\/ul>\n<p>Our PizzaPlugin is a standard C# class  and we&#8217;re going to keep things simple, but you can imagine that this could call into a database or whatever you like to to get a menu and place an order.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class PizzaPlugin\r\n{\r\n    &#x5B;KernelFunction]\r\n    &#x5B;Description(&quot;Use this function to list the pizza&#039;s a customer can order&quot;)]\r\n    public string ListMenu() =&gt; &quot;We offer Meaty Feasty, Pepperoni, Veggie, and Cheese pizzas.&quot;;\r\n\r\n    &#x5B;KernelFunction]\r\n    public string PlaceOrder(string pizzaType)\r\n        =&gt; $&quot;Order placed for: {pizzaType}. It will be delivered in 30 minutes.&quot;;\r\n}\r\n<\/pre>\n<p>The KernelFunctionAttribute is registered\/added to the Semantic Kernal to supply callable plugin functions. The DescriptionAttribute is optional, but recommended if you want the LLM to understand what the function does during auto function calling (which we will be using). I&#8217;ve left the other function without this DescriptionAttribute just to demonstrate it&#8217;s not required in this case, yet our function will\/should still be called. If we have many similar functions this would be a helpful addition.<\/p>\n<p><em>Note: Try to also function names that are clearly stating their usage, i.e. use action oriented naming.<\/em><\/p>\n<p>Now let&#8217;s implement the Program.cs where we&#8217;ll, read in our configuration from the appsettings.json and then create the Semantic Kernel, add the Azure Open AI Chat services, add the plugin we just created then call into the AI Foundry LLM model we created earlier.<\/p>\n<p>We&#8217;re NOT going create all the code for an actual console based chat app, hence we&#8217;ll just predefine the &#8220;chat&#8221; part with a <em>ChatHistory<\/em> object. In a real world you may wish to keep track of the chat history.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nusing Microsoft.Extensions.Configuration;\r\nusing Microsoft.SemanticKernel;\r\nusing Microsoft.SemanticKernel.ChatCompletion;\r\nusing OpenAI.Chat;\r\nusing SemanticKernelTest.PizzaPlugin;\r\n\r\nvar config = new ConfigurationBuilder()\r\n    .AddJsonFile(&quot;appsettings.json&quot;)\r\n    .Build();\r\n\r\nvar endpoint = config&#x5B;&quot;AI:Endpoint&quot;];\r\nvar apiKey = config&#x5B;&quot;AI:ApiKey&quot;];\r\nvar apiVersion = config&#x5B;&quot;AI:ApiVersion&quot;];\r\nvar deploymentName = config&#x5B;&quot;AI:DeploymentName&quot;];\r\n\r\nvar builder = Kernel.CreateBuilder();\r\n\r\nbuilder.AddAzureOpenAIChatCompletion(\r\n    deploymentName: deploymentName,\r\n    endpoint: endpoint,\r\n    apiKey: apiKey,\r\n    apiVersion: apiVersion\r\n);\r\n\r\nvar kernel = builder.Build();\r\n\r\nvar plugin = new PizzaPlugin();\r\nkernel.Plugins.AddFromObject(plugin);\r\n\r\nvar chatCompletion = kernel.GetRequiredService&lt;IChatCompletionService&gt;();\r\n\r\nvar chatHistory = new ChatHistory();\r\nchatHistory.AddAssistantMessage(&quot;How can I help you?&quot;);\r\nchatHistory.AddUserMessage(&quot;Can I order a plan Pepperoni pizza?&quot;);\r\n\r\nvar result = await chatCompletion.GetChatMessageContentAsync(chatHistory, new PromptExecutionSettings\r\n{\r\n    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()\r\n}, kernel);\r\n\r\nConsole.WriteLine(result.Content);\r\n<\/pre>\n<p>Before you run this code, place breakpoints on the Kernel Functions in the plugin and then run the code. Hopefully all run&#8217;s ok and you&#8217;ll notice that the LLM (via Semantic Kernel) calls into the plugin methods. As you&#8217;ll hopefully see &#8211; it calls the menu to check whether the pizza supplied is one we make then orders it, if it does exist. Change the pizza to one we do not make (for example Chicken) and watch the process and output.<\/p>\n<p><strong>More settings<\/strong><\/p>\n<p>In the code above we&#8217;re using the <em>PromptExecutionSettings<\/em> but we can also use <em>OpenAIPromptExecutionSettings<\/em> instead, from this we can configure Open AI by setting the Temperature, MaxTokens and others, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar result = await chatCompletion.GetChatMessageContentAsync(chatHistory, new OpenAIPromptExecutionSettings\r\n{\r\n  Temperature = 0.7,\r\n  FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(),\r\n  MaxTokens = 100\r\n}, kernel);\r\n<\/pre>\n<p>These options are also settable in the AI Foundry. Temperature controls the randomness of the model, for example a lower value is more deterministic whereas the higher is more random the results are, the default is 1.0. <\/p>\n<ul>\n<li>0.2-0.5 is more deterministic and produces more focused outputs<\/li>\n<li>0.8-1.0 allows for more diverse and creative responses<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Setting up a project and model in AI Foundry Let&#8217;s start by creating a project in https:\/\/ai.azure.com\/ Note: I&#8217;m going to create a very simple, pretty standard chatbot for a pizza delivery service, so my project is going be called pizza, so you&#8217;re see this in the code but ofcourse replace with your preferred example [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[761,3,762],"tags":[],"class_list":["post-11927","post","type-post","status-publish","format-standard","hentry","category-ai","category-c","category-chatbot"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11927","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=11927"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11927\/revisions"}],"predecessor-version":[{"id":11948,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11927\/revisions\/11948"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=11927"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=11927"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=11927"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}