Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / artificial-intelligence

Deploy an Intelligent App on Azure Container Apps with Azure AI: Part 2

5.00/5 (1 vote)
23 Oct 2023CPOL6 min read 3.2K  
In this four-part series, you’ll learn how to create an Intelligent App with Azure. This second tutorial demonstrates how to add intelligent features to this user feedback analysis application. Then, it explores how to use your new Intelligent App to analyze user feedback.

Image 1

There’s no question that artificial intelligence (AI) and machine learning (ML) are instrumental to modern development processes. And in an era where dynamic, adaptable applications are becoming increasingly in demand, integrating AI into your development practice isn’t just preferential. It’s necessary.

Intelligent Apps are apps that leverage AI algorithms to analyze user interactions and make real-time, intelligent decisions. They enable you to create an engaging, personalized user experience.

In the first article of this series, we created a basic application using Azure Container Apps and Azure AI. In this article, we’ll transform this application into an Intelligent Application and use this new and improved Intelligent App to analyze user feedback.

With Azure, creating Intelligent Apps is straightforward. Read on to see for yourself!

Prerequisites

To follow this tutorial, you’ll need:

  • An Azure account. Signing up for a free account gives you complimentary credits for the first month and access to a number of basic services. When you create a new account, you’ll have to provide a credit card to verify transactions in case you use more resources than your allocation. For these articles, we’ll minimize spending as much as possible.
  • Docker Desktop version 3.5.1 or newer installed
  • Visual Studio installed. This demonstration uses Community Edition 2022.

To see the project in action, check out the complete project code.

Building the Intelligent App

Now that we’ve set up our basic application, let’s add some intelligence to it. Our initial step involves adding two NuGet packages: Azure.AI.TextAnalytics for granting access to Azure AI and Microsoft.Extensions.Azure for seamlessly injecting the SDK.

Visual Studio package manager shows the Browse tab with "azure.ai" entered in the search bar and the Azure.AI.TextAnalytics package selected.

Visual Studio package manager shows the Browse tab with "microsoft.extensions.azure" entered in the search bar and the Microsoft.Extensions.Azure package selected.

Next, we need to register our text analytics client for dependency injection into our application. Before we can do that, the Text Analytics client requires two secrets:

  • An endpoint address
  • An access key

We need to add these into both our development and production environments. In both environments, AI_EndPoint is the endpoint variable name while AI_Key is the access key variable name.

To add these two items to your development environment, right-click on your project and select Manage User Secrets. Next, open your Publish profile, click the three dots ( ) next to Hosting, and select Manage container app settings to verify that these variables are accessible within your container. Finally, you can add these secrets to your Azure container.

Now, open the Program.cs file and modify the section where we initialize the database context to include the text analytics initialization:

C#
if (builder.Environment.IsDevelopment())
{
    builder.Services.AddDbContext<DatabaseContext>(options =>
        options.UseSqlServer(builder.Configuration["userfeedbackdatabaseconnection"]));

    builder.Services.AddAzureClients(clientBuilder =>
        clientBuilder.AddTextAnalyticsClient(new Uri(builder.Configuration["AI_EndPoint"]),
        new Azure.AzureKeyCredential(builder.Configuration["AI_Key"]))
        );
}
else
{
    builder.Services.AddDbContext<DatabaseContext>(options =>
        options.UseSqlServer(Environment.GetEnvironmentVariable("AZURE_SQL_CONNECTIONSTRING")));

    builder.Services.AddAzureClients(clientBuilder =>
        clientBuilder.AddTextAnalyticsClient(new Uri(builder.Configuration["AI_EndPoint"]),
        new Azure.AzureKeyCredential(builder.Configuration["AI_Key"]))
        );
}

Finally, let’s configure our Review Create method to retrieve sentiment analysis results from the Azure AI services API. To do this, add the following to your Review controller constructor:

C#
private readonly TextAnalyticsClient _textClient;

        public ReviewsController(DatabaseContext context, TextAnalyticsClient textClient)
        {
            _context = context;
            _textClient = textClient;
        }

Then, modify the POST Create Action in your Reviews controller to incorporate a call to the Azure AI services API for analyzing the review text:

C#
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,ProductId,ProductName,
ReviewText,PostDate,Sentiment,PositiveValue,NeutralValue,NegativeValue")] Review review)
{
    var selectedProductId = int.Parse(HttpContext.Request.Form["Products"].ToString());
    var product = await _context.Products.FirstOrDefaultAsync
                  (p => p.Id == selectedProductId);

    var sentimentResult =
        await _textClient.AnalyzeSentimentAsync(review.ReviewText);

    review.ProductId = selectedProductId;
    review.ProductName = product.Name;
    review.PostDate = DateTime.Now.ToString("yyyy-MM-dd");
    review.Sentiment = sentimentResult.Value.Sentiment.ToString();
    review.PositiveValue = (float)sentimentResult.Value.ConfidenceScores.Positive;
    review.NeutralValue = (float)sentimentResult.Value.ConfidenceScores.Neutral;
    review.NegativeValue = (float)sentimentResult.Value.ConfidenceScores.Negative;

    _context.Add(review);
    await _context.SaveChangesAsync();
    return RedirectToAction(nameof(Index));
}

In this tutorial, we use the simpler AnalyzeSentimentAsync method. It takes our review text and produces an overall sentiment analysis, assigning positive, neutral, and negative scores.

Azure’s text analytics service also supports opinion mining, a more advanced use case. Opinion mining goes beyond the basics, providing sentiment analysis for specific subjects or keywords within a text.

For instance, if a review reads, “This was a really good product, but the delivery times were way too long. I also had a hard time understanding the manual,” the opinion mining option might break this into distinct subjects and offer sentiment analysis for each:

  • “Product” with a sentiment of positive
  • “Delivery time” with a sentiment of negative
  • “Manual” with a sentiment of negative

Using Your Intelligent App to Analyze User Feedback

Now that we have our AI connected to our application, let’s create a review and see what the AI responds with.

Run the application, navigate to the /Reviews/Create folder to create a review, and click Submit. Select Clippers & Trimmers from the drop-down and write: “This was a really good trimmer for cutting my hair, but it gets caught in my beard.”

Upon inspecting the review you just posted, you’ll notice that Azure AI scored it as positive, albeit with slightly negative and neutral components.

The feedback app index displays review text for Apple Laptops and Clippers & Trimmers. The Clippers & Trimmers entry features sentiment analysis results reading Positive, with 0.96 PositiveValue, 0.01 NeutralValue, and 0.03 NegativeValue.

Now, try another review. This time, select the Headphones product from the drop-down and write the following review: “These headphones were passable. The foam on the outside was not thick enough and can hurt your head. The price is really cheap.”

This time, the AI scores the review as negative, with no positive score and a slight neutral score.

The Headphones entry features sentiment analysis results reading Negative, with 0 PositiveValue, 0.15 NeutralValue, and 0.85 NegativeValue.

By incorporating this AI-based scoring, you gain insights into customer feedback trends and can initiate specific actions based on positive or negative feedback. For example, we might want to understand how our product reviews have performed over the last seven days. Let’s update our review list page to present the average reviews during that period.

To achieve this, we’ll navigate to the ReviewController and summarize our data to display on the Index page. Then, we’ll load our products and reviews from the database, iterate through them, and average them over eight days (including the current day). Finally, we’ll compile the summarized data in a list and create a table based on the list.

Begin by creating a SentimentTrends model (a cut-down version of our review data) with this code:

C#
namespace UserFeedbackApp.Models
{
    public class SentimentTrends
    {
        public int Id { get; set; }
        public string ProductName { get; set; }
        public float PositiveValue { get; set; }
        public float NeutralValue { get; set; }
        public float NegativeValue { get; set; }
        public string PostDate { get; set; }
    }
}

Next, update the Index method in our ReviewController file using the following code:

C#
public async Task<IActionResult> Index()
{
    var reviewList = await _context.Reviews.ToListAsync();
    var productList = await _context.Products.ToListAsync();

    List<SentimentTrends> trends = new List<SentimentTrends>();

    foreach(var product in productList)
    {
         var productReviews = reviewList
        .Where(d => d.ProductId == product.Id)
        .Where(d => DateTime.ParseExact(d.PostDate, "yyyy-MM-dd", 
                    CultureInfo.InvariantCulture) >= (DateTime.Now.AddDays(-8)))
        .ToList();

        if (productReviews.Count() > 0)
        {
            float positiveValue = 0;
            float neutralValue = 0;
            float negativeValue = 0;
            foreach (var review in productReviews)
            {
                 positiveValue += review.PositiveValue;
                 neutralValue += review.NeutralValue;
                 negativeValue += review.NegativeValue;
             }

             positiveValue = (float)Math.Round(positiveValue / productReviews.Count(), 2);
             neutralValue = (float)Math.Round(neutralValue / productReviews.Count(), 2);
             negativeValue = (float)Math.Round(negativeValue / productReviews.Count(), 2);

             SentimentTrends trend = new SentimentTrends();

             trend.Id = productReviews.First().ProductId;
             trend.ProductName = productReviews.First().ProductName;
             trend.PostDate = DateTime.Now.AddDays(-8).ToString("yyyy-MM-dd");
             trend.PositiveValue = positiveValue;
             trend.NeutralValue = neutralValue;
             trend.NegativeValue = negativeValue;

             trends.Add(trend);
        }
    }

    ViewBag.Trends = trends;
    return reviewList != null ?
            View(reviewList) :
            Problem("Entity set 'DatabaseContext.Reviews'  is null.");
}

This code filters our recent reviews, averages them by the number of reviews received, and creates the list before passing it to the view in the ViewBag. To display this data, update the Index.cshtml file in our Views/Reviews folder with the following code:

HTML
<h2>Seven Day Trend</h2>
<table class="table">
    <thead>
        <tr>
            <th>Product ID</th>
            <th>Product Name</th>
            <th>Positive</th>
            <th>Neutral</th>
            <th>Negative</th>
        </tr>
    </thead>
    <tbody>
        @foreach (SentimentTrends item in ViewBag.trends)
        {
        <tr>
                <td>@item.Id</td>
                <td>@item.ProductName</td>
                <td>@item.PositiveValue</td>
                <td>@item.NeutralValue</td>
                <td>@item.NegativeValue</td>
        </tr>
        }
    </tbody>
</table>

This displays our data in a simple table on our reviews page. If we run our code now and navigate to the reviews page, we’ll see the table at the top of the page. Averaging product sentiments this way offers valuable insights into potential product issues based on real user feedback.

The Index page shows the Seven Day Trend for Apple Laptops reviews, with 0.69 positive, 0.01 Neutral, and 0.3 Negative.

Conclusion

Intelligent Apps can add more data and insights into your applications, opening possibilities for even more functionality.

In this article, we built a simple web application using Azure Container Apps. Then, we incorporated sentiment analysis through Azure AI, extending our application’s capabilities to analyze user feedback. This application architecture on Azure enables seamless scalability for both the application and the AI components. This automatic scalability ensures your application can efficiently meet rising demands and scale back down when that demand subsides.

However, sentiment analysis is just one small component of the entire Azure AI suite. Azure AI includes several AI-driven APIs using pre-built models, such as:

  • Language understanding for translation, question answering, or conversational language comprehension
  • Image processing for image recognition or image and video analysis
  • Speech processing, including speech-to-text, text-to-speech, or speech translation
  • Anomaly detection, offensive content detection, and personalization

Begin your journey into Intelligent Apps with Azure, then delve into part three of this series to learn how to level up your Intelligent Apps.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)