Building a Chatbot with Azure AI and C#/.NET

Introduction

Chatbots have become increasingly popular in various applications, from customer support to virtual assistants. Azure AI provides powerful tools for creating intelligent chatbots that can understand and respond to user queries. In this article, we’ll explore how to build a chatbot using Azure AI services and C#/.NET, step by step, with practical examples and code samples.

A chatbot is a computer program or application designed to simulate human conversation with users through natural language. Chatbots are used to interact with users in a chat-like interface, answering questions, providing information, offering assistance, and even performing tasks. They can be integrated into various platforms, including websites, messaging apps, and voice assistants.

Chatbots can be broadly categorized into two types:

  1. Rule-Based Chatbots: These chatbots follow predefined rules and are programmed to respond to specific keywords or phrases. They work based on a set of predetermined responses and can handle common queries effectively. However, they lack the ability to understand the context of the conversation beyond the programmed rules.
  2. AI-Powered Chatbots: These chatbots leverage artificial intelligence and natural language processing (NLP) to understand and respond to user queries in a more context-aware and dynamic manner. They can comprehend the intent behind a question and generate responses that are not explicitly preprogrammed.

In this article, we will discuss about building a chatbot with Azure AI and C#. This type of chatbot can pull answers from predefined text sources, such as a JSON file containing frequently asked questions (FAQs). When a user asks a question, the chatbot can search through the predefined text source to find the best matching answer based on the user’s input. This approach is a simplified example of an AI-powered chatbot that uses predefined text data to provide responses.

To create more advanced AI-powered chatbots, you can utilize machine learning models, such as natural language understanding (NLU) models, to better understand user input and generate contextually relevant responses. These models can extract meaning from unstructured text and improve the chatbot’s ability to engage in natural and dynamic conversations with users.

Prerequisites

Before we dive into building our chatbot, ensure you have the following prerequisites in place:

  1. An active Azure subscription.
  2. Visual Studio with the .NET SDK installed.
  3. A basic understanding of C# and .NET.

Step 1: Setting up Azure Resources

Let’s start by creating the necessary Azure resources for our chatbot.

  1. Log in to the Azure portal (https://portal.azure.com).
  2. Click on “Create a resource” and search for “Azure Bot Service.”
  3. Select “Azure Bot Service” and click “Create.”
  4. Fill in the required details, like subscription, resource group, and region.
  5. Choose or create an App Service plan.
  6. Review the terms and create the resource.

Once the resource is created, you will have an Azure Bot Service ready for development.

Step 2: Designing the Chatbot

For this example, we’ll build a basic FAQ chatbot. First, define the questions and answers your bot should be able to handle. You can store these in a JSON file, a database, or any other storage of your choice.

Here’s a sample JSON structure for FAQs:

[
    {
        "question": "What is Azure AI?",
        "answer": "Azure AI is a set of AI services offered by Microsoft through the Azure cloud platform."
    },
    {
        "question": "How can I create an Azure AI chatbot?",
        "answer": "You can create an Azure AI chatbot using Azure Bot Service."
    },
    {
        "question": "What services are offered by Azure AI?",
        "answer": "Azure AI provides a range of services, including Text Analytics, Computer Vision, and more."
    }
    // Add more FAQs as needed
]

Step 3: Building the Chatbot Logic

Now, let’s create the C# code for our chatbot using Azure Bot Framework.

  1. Create a new C# project in Visual Studio.
  2. Install the “Microsoft.Bot.Builder” package

dotnet add package Microsoft.Bot.Builder --version 4.12.2 or later

Implement the bot logic using the Bot Framework. Below is a simplified example of handling user queries:

using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

public class FAQBot : IBot
{
    private readonly List<FAQ> faqs;

    public FAQBot()
    {
        // Load FAQs from the JSON file
        string jsonFilePath = "faq.json"; // Update with your file path
        faqs = LoadFAQsFromJson(jsonFilePath);
    }

    public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
    {
        if (turnContext.Activity.Type == ActivityTypes.Message)
        {
            var userMessage = turnContext.Activity.Text;
            var answer = GetAnswer(userMessage);

            if (!string.IsNullOrWhiteSpace(answer))
            {
                await turnContext.SendActivityAsync(MessageFactory.Text(answer), cancellationToken);
            }
            else
            {
                await turnContext.SendActivityAsync(MessageFactory.Text("I'm sorry, I don't know the answer to that question."), cancellationToken);
            }
        }
    }

    private string GetAnswer(string userQuestion)
    {
        // Find the best matching answer from the FAQ list
        var matchingFAQ = faqs.FirstOrDefault(faq => userQuestion.Contains(faq.question, StringComparison.OrdinalIgnoreCase));
        return matchingFAQ?.answer;
    }

    private List<FAQ> LoadFAQsFromJson(string jsonFilePath)
    {
        try
        {
            var json = File.ReadAllText(jsonFilePath);
            return JsonConvert.DeserializeObject<List<FAQ>>(json);
        }
        catch (Exception)
        {
            // Handle file not found or JSON parsing errors
            return new List<FAQ>();
        }
    }
}

public class FAQ
{
    public string question { get; set; }
    public string answer { get; set; }
}

Make sure to update the jsonFilePath with the correct path to your JSON file. This code reads the FAQs from the JSON file, searches for a matching question, and returns the corresponding answer to the user. If no match is found, it provides a default response.

With this code and a JSON file containing your FAQs, your chatbot will be able to respond to user queries based on the predefined FAQ data.

Bot Adapter and Bot Framework

The Bot Adapter and Bot Framework are core components in the development of chatbots and conversational applications. They provide a framework and tools for building, deploying, and managing chatbots across various messaging platforms. Let’s delve into these components and how they work.

Bot Adapter

A Bot Adapter is a key component that enables communication between your bot and various channels or messaging platforms. It abstracts the complexities of interacting with different platforms and handles the following tasks:

  • Message Serialization/Deserialization: It serializes messages from your bot into a format suitable for the platform, and deserializes incoming messages into a format that your bot can understand.
  • Authentication: It manages authentication and authorization for your bot, ensuring that it can securely interact with messaging platforms.
  • Routing and Processing: The adapter routes incoming messages from users to your bot’s logic (usually the OnTurnAsync method) and routes your bot’s responses back to the user.
  • State Management: It helps manage conversation and user states, allowing you to store and retrieve data relevant to specific users or conversations.
  • Channel-Specific Features: The adapter may include platform-specific features and capabilities. For example, it might include functionality for rendering rich cards and attachments specific to a messaging platform.

Bot Framework

The Bot Framework is a comprehensive platform and set of tools developed by Microsoft for building and deploying conversational applications and chatbots. It includes the following components:

  • Bot Builder SDK: This SDK provides libraries and tools for building bots using various programming languages (e.g., C#, JavaScript, Python). It simplifies bot development by offering pre-built components for handling common bot tasks, such as message processing and conversation management.
  • Bot Services: Microsoft Azure offers Bot Services, which allow you to create, deploy, and manage bots in the cloud. These services include Azure Bot Service, which makes it easy to deploy bots to popular messaging platforms, and Azure Bot Framework, which provides additional capabilities for managing bots at scale.
  • Bot Emulator: A tool that lets you test your bot locally during development, making it easier to debug and refine your bot’s behavior.
  • Bot Channels: The Bot Framework supports a wide range of channels, including popular messaging platforms like Microsoft Teams, Slack, Facebook Messenger, and more. You can configure your bot to interact with these channels seamlessly.
  • LUIS (Language Understanding): The Bot Framework integrates with LUIS, a natural language processing service, to enable your bot to understand and interpret user input more effectively.
  • QnA Maker: This is a part of the Bot Framework ecosystem and allows you to easily create question-and-answer knowledge bases for your bot.
  • Azure Cognitive Services: You can integrate various Azure AI services, like Text Analytics and Computer Vision, with your bot to enhance its capabilities.

Together, the Bot Adapter and the Bot Framework provide a robust infrastructure for building, deploying, and managing chatbots that can communicate with users across multiple messaging platforms. They abstract much of the underlying complexities, allowing developers to focus on building the bot’s logic and functionality.

Managing Conversations & State

Managing conversations and state for multiple users is a critical aspect of developing a bot that can handle interactions from many users concurrently. The bot framework provides mechanisms for managing user-specific and conversation-specific states and ensures that responses are sent to the correct user. Here’s how it works:

  1. User and Conversation States: The bot framework allows you to maintain user-specific and conversation-specific states. User state is data that is relevant to an individual user, such as preferences or settings. Conversation state is data shared among all users within a specific conversation or channel.
  2. User and Conversation IDs: Each incoming activity includes information about the user who sent the message, such as a user ID. Similarly, the conversation has a unique ID associated with it. These IDs are used to differentiate between users and conversations.
  3. State Management Middleware: State management middleware is used to handle and store user and conversation states. This middleware can be included in your bot’s pipeline to automatically manage states. You configure it to store and retrieve data for each user and conversation using the respective IDs.
  4. Context: The ITurnContext object passed to the OnTurnAsync method contains information about the incoming activity, including the user and conversation IDs. This context is used to interact with the state management middleware to read and write user and conversation-specific data.
  5. Response Routing: When you send a response, you don’t need to explicitly specify the recipient. The bot framework, based on the user and conversation IDs in the incoming activity, ensures that the response is routed to the correct user and conversation.
  6. Parallelism: The bot framework is designed to handle multiple conversations and users in parallel. Each interaction is typically processed in a separate thread, allowing the bot to respond to multiple users simultaneously without conflicts.

By using user and conversation states and managing these states with state management middleware, the bot framework can handle thousands of users concurrently, ensuring that each user receives responses that are specific to their interaction and maintaining a context-aware conversation. This state management and context-awareness are essential for building effective and responsive chatbots that can handle real-world usage scenarios.

BotFrameworkHttpAdapter

The BotFrameworkHttpAdapter is part of the Microsoft Bot Framework and is provided as a built-in class. The BotFrameworkHttpAdapter is a critical component that handles communication between your bot and the various channels or platforms where your bot is deployed. It abstracts the messaging protocols, authentication, and other communication details, allowing you to focus on writing the logic for your bot rather than low-level messaging handling.

You can use the BotFrameworkHttpAdapter to:

  1. Handle incoming activities (user messages, commands, etc.).
  2. Send responses back to the user.
  3. Manage conversation state and user state.
  4. Integrate your bot with various channels (e.g., Microsoft Teams, Slack, Facebook Messenger).

By registering the BotFrameworkHttpAdapter in your application, you ensure that it can handle incoming messages, route them to the appropriate bot, and manage the communication between your bot and the messaging platform. Below is an example of how to register and use the BotFrameworkHttpAdapter in a .NET application:

services.AddSingleton<IBotFrameworkHttpAdapter, BotFrameworkHttpAdapter>();

By registering the BotFrameworkHttpAdapter as a service in your application’s dependency injection container, you make it available for use throughout your application to handle bot-to-channel communication.

OnTurnAsync Pipeline

The OnTurnAsync method in a Microsoft Bot Framework-based chatbot is a critical part of the bot’s processing pipeline. It is automatically invoked and called by the Bot Framework each time a user interacts with the bot. Here’s how it works and what happens in the pipeline when a user enters a question:

  1. User Interaction: When a user interacts with the bot, this interaction is typically sent to the bot via an activity. An activity represents a communication from the user to the bot. This activity could be a message, a command, or any other type of interaction.
  2. Bot Adapter: The Bot Framework uses a bot adapter to communicate with the user and handle incoming activities. The bot adapter listens for incoming activities, processes them, and invokes the appropriate bot methods to handle the user’s input. In the case of an incoming message, the bot adapter triggers the OnTurnAsync method.
  3. OnTurnAsync Invocation: The OnTurnAsync method is the entry point for processing user interactions. It is automatically called by the bot framework when a new activity arrives. The method is responsible for handling the activity, understanding the user’s input, and generating an appropriate response.
  4. User Message Handling: Within the OnTurnAsync method, the bot checks if the incoming activity is a message (typically a user message). If it is a message, the bot extracts the text of the user’s input (the user’s question) from the activity.
  5. FAQ Matching: The bot then searches for a matching question in the FAQ data (e.g., the JSON file) to find a suitable answer. It uses the GetAnswer method to identify the answer that corresponds to the user’s question.
  6. Response Generation: Based on the result of the FAQ matching, the bot prepares a response. If a matching FAQ is found, the answer is retrieved, and the bot constructs a response. If no matching FAQ is found, a default response is generated.
  7. Sending Response: Finally, the bot uses the turnContext to send the response back to the user. The await turnContext.SendActivityAsync(...) line is used to send the response as an activity.

This entire process happens in response to the user’s input, and the OnTurnAsync method is invoked by the Bot Framework as part of its processing pipeline. The Bot Framework abstracts much of the low-level messaging handling, allowing developers to focus on creating the logic that processes and responds to user interactions.

Register FAQBot

In a Microsoft Bot Framework-based application, you typically need to register and initialize the bot within the application code so that the framework knows which bot to use and how to route incoming messages to the appropriate bot.

To register and initialize the FAQBot class in your application, you would generally follow these steps:

  1. Create a Bot Adapter: You’ll need to create a bot adapter (usually an instance of BotFrameworkAdapter) that will handle incoming activities and manage communication with the bot.
  2. Create a Bot Instance: Create an instance of your FAQBot class. This is where you’ll set up the bot’s behavior and define its responses.
  3. Register the Bot with the Bot Adapter: Register your FAQBot instance with the bot adapter. This tells the adapter which bot to use to handle incoming messages.
  4. Initialize the Adapter and Start Listening: Initialize the bot adapter and start listening for incoming activities (user interactions).

Here’s an example of how this might look in C# code:

using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Add bot services
        services.AddSingleton<IBotFrameworkHttpAdapter, BotFrameworkHttpAdapter>();
        services.AddSingleton<FAQBot>(); // Register the FAQBot

        // ...
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // ...

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers(); // Set up API endpoints for the bot
        });

        // Start listening for activities
        var bot = app.ApplicationServices.GetRequiredService<FAQBot>();
        var adapter = app.ApplicationServices.GetRequiredService<IBotFrameworkHttpAdapter>();

        // Register the bot with the adapter
        adapter.ProcessAsync(RequestDelegate(bot.OnTurnAsync), HttpContext, CancellationToken);
    }
}

In the above code, the FAQBot is registered as a service and then retrieved from the service provider when initializing the bot adapter. The FAQBot instance’s OnTurnAsync method will be automatically called by the bot framework when incoming activities are received.

This is a simplified example, and the actual code structure can vary based on the framework and platform you are using. The key is to register your bot and set up the bot adapter to route incoming activities to your bot’s OnTurnAsync method.

Step 4: Running the Chatbot

Now that you have implemented the chatbot logic, you can test and run the chatbot.

  1. Build and run your application in Visual Studio.
  2. Deploy your bot to the Azure Bot Service created in Step 1.
  3. Test your chatbot by sending messages through the Azure Bot Service’s Web Chat or your preferred channel.

Conclusion

In this article, we’ve explored how to build a chatbot with Azure AI and C#/.NET using Azure Bot Service and the Bot Framework. Chatbots have a wide range of applications, from answering FAQs to providing customer support, and Azure AI empowers you to create intelligent and responsive chatbots to enhance user experiences. As you continue your journey into building chatbots, you can extend their capabilities by integrating other Azure AI services, such as Language Understanding and Speech Services. Happy bot building!

About the Author:

🚧 Roadblock Eliminator & Learning Advocate 🖥️ Software Architect 🚀 Efficiency & Performance Guide 🌐 Cloud Tech Specialist

Reference:

Chinta, M. (2023). Building a Chatbot with Azure AI and C#/.NET. Available at: https://medium.com/codenx/building-a-chatbot-with-azure-ai-and-c-net-9609ef82f4b2 [Accessed: 16th January 2024].

Share this on...

Rate this Post:

Share:

Topics:

AI