As LUIS Language Understanding enters end-of-life, I've been getting some requests for guidance on how to smoothly migrate to the new CLU (Conversational Language Understanding), the spiritual successor to LUIS and part of the new Azure Cognitive Service for Language product.
While this might seem daunting at first, it doesn't have to be a major headache if you know a few tips and tricks to make this migration smoother.
For this example, I'm going to start with a default template for Bot Composer using LUIS, which contains a set of pre-configured intents and utterances, and show you how to migrate from that to a solution using CLU.
After configuring Bot Composer with the LUIS authoring key and region, we can publish directly from the app and build and train a model based on the pre-configured intents, which in this case are 'Cancel' and 'Help', and the default 'None' intent.
The LUIS portal (www.luis.ai) allows us to export the model as a .json file. We will use this feature to export our model so we can then import it in the Azure Language Studio portal. If you don't know this one, it's where we will manage our Conversational Language Understanding model. It should feel at least somewhat familiar, as many of the concepts are the same.
Let's start by exporting the model. On the LUIS portal, open your conversation app and go to the "MANAGE" menu.
Then, on the left side menu, open the "Versions" page, select the latest version of your model, click Export, and select "Export as JSON".
You should now have a .json file containing all your intents, the utterances used to train the model and some other metadata.
Now let's open Language Studio and import our model.
After you've signed in, the portal will ask you to create (or select) a new Language service in your Azure subscription. I had already created mine, so I just selected it.
Now find Conversational Language Understanding under "Understand questions and conversational language" and click "Open Conversational language understanding".
Once you open the page, you'll see the option to import the .json we previously exported to create a new project.
Select your exported .json file and click import.
You'll then be taken to a screen that looks very similar to the one in the LUIS portal, and if everything went according to plan you'll see your imported intents and utterances.
Now we need to train the model to make it available for publishing.
On the left side menu, select "Training jobs" and then select "Start a training job".
We will need to fill out a name for our model and select the training mode. For this example my model will only be interpreting English, so I will choose standard training. I will also use the default split for the testing set. Once you've made your selections click "Train" in the bottom left of the page.
Once you get notified that the training is complete, it's now time to publish the model. This exposes an HTTP endpoint which we will then use to send user utterances. Go to the menu on the left and select "Deploying a model". Then, click "Add deployment".
Choose a name for your deployment and select the model we've trained previously and click "Deploy".
Once it's done, select your model on the screen and click "Get prediction URL".
Copy the prediction URL and the Sample Request. We'll use them in Bot Composer.
We're now done with the migration of the model from LUIS to CLU and have a working endpoint to send user utterances.
Now let's look at what changes we need to make in our Bot Composer project to accomodate these changes.
You can explore my own setup by cloning this repo.
Here you can see how my LUIS Bot Composer project looks like:
I'm using the Unknown Intent as my entry point for language recognition. Since CLU isn't officially supported as a feature in Bot Composer, you won't be able to take advantage of deep integration like you have with LUIS. Therefore, we are using the HTTP request action to POST to the endpoint we gathered from the Language Studio and parsing the response to capture the detected intent. We are then branching on the intent by using a switch action.
Let's look at it step by step, starting with the HTTP request.
As you can see, we are posting to the CLU endpoint, passing the Ocp-Apim-Subscription-Key as a header value. You can get this from the Sample Request you copied from the Language Studio.
Here's what the body looks like:
{
"kind": "Conversation",
"analysisInput": {
"conversationItem": {
"id": "${turn.activity.from.id}",
"text": "${turn.activity.text}",
"modality": "text",
"language": "en-us",
"participantId": "${participantId}"
}
},
"parameters": {
"projectName": "<Language studio project name>",
"verbose": true,
"deploymentName": "<Language studio deployment name>",
"stringIndexType": "TextElement_V8"
}
}
Essentially, we are passing the activity id, the text captured from the user and the participant Id in the conversation item object. and the Language studio project name and deployment name in the parameters.
We are also saving the CLU result in a variable called 'turn.cluResponse'.
Next we are parsing the response from CLU and collecting the top intent to save it in a conversation variable.
And finally, we are branching the conversation based on the value of this variable and calling the new dialog using the "Begin new dialog" action.
My first idea was to use the Begin new dialog and pass it the variable as a parameter to avoid the switch statement and have a cleaner solution. There is a problem in that approach, however. There is an unresolved bug in the Bot Composer, related to how it handles the array of available dialogs in each context. There already is a bug filed but no estimation or even guarantee that it will be fixed, as development is now being concentrated on Power Virtual Agents. Although it is not elegant, the presented approach should be sufficient unless you have a huge list of dialogs to branch to from your conversation entry point.
This approach also works inside one of the subsequent dialogs, as you can simply use the "Prompt for question" action to continue collecting text to send to CLU.
Let me know what you think!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.