Azure Functions - Integrating LUIS Application With Azure Function Apps To Predict Intent In User Utterances

Introduction

Any business that makes transactions online needs to provide some kind of chat support for the issues related to their business. This can be done by developing chat applications where the consumers directly chat with the agent of the business who then solves their problems. A new alternative to answering frequently asked questions is the use of the ChatBot which is intelligent enough to understand the questions raised by the user and determine the solutions to them on a real-time basis. Or in the case of an administrator, if they are managing a lot of operative tasks or a lot of source code bases, then an intelligent bot is of great help.

For the bot to become intelligent, the important step is that the bot should understand the language in which humans communicate with the bot (e.g English, French, Hindi etc.). To facilitate this understanding Microsoft has provided developers with a powerful feature called Language Understanding (LUIS). This feature can be used to understand the language by comparing the uttered sentence against the intents and the entities defined while creating the LUIS application.

When the bot is being developed, the LUIS app can be consumed from the Azure functions using the LUIS API or it can be consumed to get the predictions by calling the LUIS app from the logic app. This article will discuss the consumption of the LUIS app from an Azure Function App.

What are Azure Functions?

As per Microsoft,

"Azure Functions is an event-driven, compute-on-demand experience that extends the existing Azure application platform with capabilities to implement code triggered by events occurring in Azure or third party service as well as on-premises systems. Azure Functions allows developers to take action by connecting to data sources or messaging solutions thus making it easy to process and react to events. Developers can leverage Azure Functions to build HTTP-based API endpoints accessible by a wide range of applications, mobile, and IoT devices. Azure Functions is scale-based and on-demand, so you pay only for the resources you consume."

What is LUIS?

As per Microsoft,

"Language Understanding (LUIS) allows your application to understand what a person wants in their own words. LUIS uses machine learning to allow developers to build applications that can receive user input in natural language and extract meaning from it. A client application that converses with the user can pass user input to a LUIS app and receive relevant, detailed information back."

Key Concepts In LUIS

  1. Utterance
    This is the actual command spoken/written by the User /APP

  2. Intents
    Intents describe the actual intention behind the command given by the user. When the User says "Find me all the Pushes made on the PublicWorks Repository", what the user wants is the list of the Pushes made on the PublicWorks repository, hence Pushes made is the intent here.

  3. Entity
    This is extra information that is present in the utterance which helps the LUIS to understand the utterance more. In the above example, PublicWorks is the name of the repository and hence is the entity which gives the name of the repository on which the Push is to be queried.

Scope

This article focuses on creating a LUIS app which understands the various functions that can be performed on the repository. Once the intent to identify the action on the repository is created and the LUIS app is trained and published, the LUIS app will be consumed from the Azure Function App which will pass the utterance to the LUIS app and get the prediction form the LUIS app.

Design - LUIS App

Following are the steps that need to be performed to create a LUIS app.

  1. Log on to the LUIS portal (https://www.LUIS.ai) using the Azure credentials.
  2. Create a LUIS application. Refer to the sample screenshot below.

    Azure

  3. Create New Simple Entities RepoName and ActionAskedAbout as per the sample below.

    Azure

    Azure

  4. Create a composite Entity RepoAction which will encapsulate the entities created above. Refer to the following screen shot.

    Azure

  5. Create an intent ActionsOnRepo to understand that the intent behind the utterance is to do/query a certain action on a certain repository.

    Azure

  6. The list of utterances used to train the app is as follows.

    Azure

  7. Map the Composite entity created above to the Utterances entered above.
  8. Trains the LUIS app using the Train button in the portal. Once the App is trained, it can be tested using sample inputs.

LUIS Cognitive Service Account

In order to consume the LUIS app from the logic apps, the LUIS app must be published to the Resource group so that logic app connectors can use it, in order to do so, a LUIS cognitive services account need to be set up in the Azure. Refer to the following steps to set up the account.

  1. Select the Cognitive Services blade.

    Azure

  2. Create the Account.

    Azure

Publish LUIS App

Once an account for LUIS is created, the publication of the app becomes very easy. Navigate to the Publish Tab in the LUIS portal and select the environment (Production/Staging) and the time zone.

Azure

Select the region where the LUIS app needs to be Hosted and click Add Keys, this will allow the LUIS portal to link the LUIS app to the LUIS account created above

Azure

Once done, click on the publish button, this will publish the LUIS app into the LUIS account created earlier.

The LUIS app is now available to be consumed by the Azure Function App.

Azure Function App

There are some steps that need to be undertaken to create the Azure function to consume the LUIS app. Following are the steps that should be undertaken to create the Azure Function.

  1. Select the Azure Functions from the Compute Section and Provide the details like the app name, resource group, consumption plan, and storage account details.

    Azure

    Azure
     
  2. Add a new function called as ConsumeLUISApplication. Refer to the below screenshots for sample.

    Azure

    Azure

    Azure
  3. In order to access the LUIS application from the Azure Function App, LUIS application id, LUIS subscription key, and the LUIS endpoint are required. The LUIS application Id and the LUIS URL can be obtained from the Publish section of the LUIS app that was created earlier. These values are stored in the app settings of the Azure Function app and accessed in the code later on. The following set of screenshots depicts how to add the app settings keys.

    Azure

    Azure

This completes the basic set up for the Azure Function App. Once this is completed, the next step is to set up the code for the Azure Function App. Following is the code used in the function app.

  1. #r "System.Web"  
  2. using System.Net;  
  3. using System.Configuration;  
  4. using System.Web;  
  5. using System.Threading.Tasks;  
  6. public static async Task < HttpResponseMessage > Run(HttpRequestMessage req, TraceWriter log) {  
  7.     log.Info("C# HTTP trigger function processed a request.");  
  8.     //Read the utterance from the Request.  
  9.     string utteredText = req.GetQueryNameValuePairs().FirstOrDefault(q => string.Compare(q.Key, "Utterance"true) == 0).Value;  
  10.     if (utteredText == null) {  
  11.         dynamic data = await req.Content.ReadAsAsync < object > ();  
  12.         utteredText = data ? .Utterance;  
  13.     }  
  14.     log.Info("Uttered Text is :" + utteredText);  
  15.     string luisPrediction = string.Empty;  
  16.     luisPrediction = await GetPredictions(utteredText, log);  
  17.     if (String.IsNullOrEmpty(luisPrediction)) {  
  18.         luisPrediction = "Unable to Fetch the LUIS prediction at the Moment. Please try again";  
  19.     }  
  20.     return utteredText == null ? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a utterance on the query string or in the request body") : req.CreateResponse(HttpStatusCode.OK, luisPrediction);  
  21. }  
  22. private static async Task < string > GetPredictions(string utteredText, TraceWriter log) {  
  23.     string luisPrediction;  
  24.     try {  
  25.         string LUISAppId = ConfigurationManager.AppSettings["LUISAppId"];  
  26.         string LUISSubscriptionKey = ConfigurationManager.AppSettings["LUISSubscriptionKey"];  
  27.         string LUISUri = ConfigurationManager.AppSettings["LUISUri"];  
  28.         var client = new HttpClient();  
  29.         var queryString = System.Web.HttpUtility.ParseQueryString(string.Empty);  
  30.         client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", LUISSubscriptionKey);  
  31.         queryString["q"] = utteredText;  
  32.         queryString["timezoneOffset"] = "0";  
  33.         queryString["verbose"] = "false";  
  34.         queryString["spellCheck"] = "false";  
  35.         queryString["staging"] = "false";  
  36.         var uri = LUISUri + LUISAppId + "?" + queryString;  
  37.         log.Info("Calling the LUIS app to Get the Predections");  
  38.         var response = await client.GetAsync(uri);  
  39.         luisPrediction = await response.Content.ReadAsStringAsync();  
  40.         log.Info(luisPrediction);  
  41.     } catch (Exception ex) {  
  42.         luisPrediction = string.Empty;  
  43.         log.Info("Exception Caught while calling LUIS");  
  44.     }  
  45.     return luisPrediction;  
  46. }  

The above code makes use of the asynchronous programming in C# and the concepts of C# script which are used in writing Azure Functions. (Refer to the See Also section). The code is self explanatory and easy to understand.Copy the code into the function editor and save the code. The online editor will show errors, if any, that occur while compiling the code.

Testing

Once the Azure Function created above is saved, it can be tested using a tool like POSTMAN or SOAPUI. Url  function can be obtained from the "Get Function Url" which is next to the Run button in the online editor.

Following are the requests and the responses that were fed to the Azure app.

Request

{

}

Response

"Please pass an utterance on the query string or in the request body"

Request

  1. {  
  2.    "Utterance""Please bring me all the pulls done on the PublicWorks repository"  
  3. }  

Response

  1. "{\r\n \"query\": \"Please bring me all the pulls done on the PublicWorks repository\",\r\n \"topScoringIntent\": {\r\n \"intent\": \"ActionsOnRepo\",\r\n \"score\": 0.9880099\r\n },\r\n \"entities\": [\r\n {\r\n \"entity\": \"pulls\",\r\n \"type\": \"ActionAskedAbout\",\r\n \"startIndex\": 24,\r\n \"endIndex\": 28,\r\n \"score\": 0.9956364\r\n },\r\n {\r\n \"entity\": \"pulls\",\r\n \"type\": \"RepoAction\",\r\n \"startIndex\": 24,\r\n \"endIndex\": 28,\r\n \"score\": 0.9969615\r\n },\r\n {\r\n \"entity\": \"publicworks\",\r\n \"type\": \"RepoAction\",\r\n \"startIndex\": 42,\r\n \"endIndex\": 52,\r\n \"score\": 0.84949106\r\n },\r\n {\r\n \"entity\": \"publicworks\",\r\n \"type\": \"RepoName\",\r\n \"startIndex\": 42,\r\n \"endIndex\": 52,\r\n \"score\": 0.73795265\r\n }\r\n ],\r\n \"compositeEntities\": [\r\n {\r\n \"parentType\": \"RepoAction\",\r\n \"value\": \"pulls\",\r\n \"children\": [\r\n {\r\n \"type\": \"ActionAskedAbout\",\r\n \"value\": \"pulls\"\r\n }\r\n ]\r\n },\r\n {\r\n \"parentType\": \"RepoAction\",\r\n \"value\": \"publicworks\",\r\n \"children\": [\r\n {\r\n \"type\": \"RepoName\",\r\n \"value\": \"publicworks\"\r\n }\r\n ]\r\n }\r\n ]\r\n}"  

The response can now be serialized into other classes or json objects as required.

Conclusion

The request and responses generated by the Azure function show that it is very easy to integrate the LUIS application in an Azure function.

See Also

Refer to the following links to read more about the topics discussed in this article

References

The following articles were referenced while writing this article.