Live Assist and My First Bot!

Live Assist from CaféX is an omnichannel product adding web chat (and more) into Microsoft Dynamics 365. A fairly recent release of Live Assist created a new ability to add bots. In this post I will describe how I created my first bot to work with Live Assist.

I guess some background might be useful. Like what is a Bot and why do we want to use them with Live Assist …..

What is a bot?

As the term “bot” could be used in several ways I turned to Wikipedia for a definition. Amongst other things, Wikipedia said “A bot is a software application that runs automated tasks (scripts) over the internet. Typically, bots perform tasks that are both simple and structurally repetitive …. Some bots communicate with other users of internet-based services via instant messaging ….. These chatterbots may allow people to ask questions in plain English and then formulate a proper response.

This definition describes a bot as software that can chat with users over instant messaging. A bot could actually take many forms, for example, it might be used to collect data or act as a Q&A service. In this post I am going to focus on the idea that a bot can be asked and respond to questions.

At this point I’m going to stress that I am not a software developer! I play around with programming but I am not a hard core coder. Meaning in my quest to create my first bot I haven’t had to resort to any amount of coding. (Just a little bit of cut and paste!) I am sure there are many developers out there who can take the basic template I describe here and extend its capabilities significantly!

Additionally when I refer to bots I specifically mean bots created using the Microsoft Bot Framework. This allows us to create and connect intelligent bots to interact with users naturally. This could be from a website, bespoke app, Cortana, Skype, Facebook Messenger etc. Although for the purposes of this post we are going to concentrate on creating a bot that can work from within Live Assist.

Why use a bot with Live Assist?

So why would I want a bot that works within Live Assist? I guess one answer to this might be cost! Having human agents chatting to visitors to your web site can be a costly business. Often visitors will repeatedly ask common questions like, “How long does delivery take?”, “What are your opening hours?” etc. You probably already have an FAQ section on your website to address common questions like these. But assuming there are many frequently asks questions visitors may find it hard to find the answers they require and will therefore quickly turn to your live agents. Using live agents for these common questions is a costly use of a limited resource.

Bots can therefore be used as a “front” to your live agents. Often the bot will be able to give perfectly reasonable answers to commonly asked questions. From the user point of view the other advantage of bots is the answer would be presented immediately, no waiting for an agent to become available.

You could, of course, create a bot that simply answers questions. But embedding it within Live Assist gives us the capability to escalate to a human agent, maybe when the bot can’t answer a question.

How to Create a Live Assist BOT?

I am going to assume you have a basic understanding of Live Assist! I’ll assume you have it installed and understand how to create a simple web chat campaign to engage with your human agents. Actually, as I’ll explain soon a bot (in Live Assist terms) isn’t that different to a human agent. We effectively end up with “bot users” that have skills, just like a human. And therefore campaigns can be created to trigger chat engagements with skills sets specific to bots just as you would with normal human based chat engagements.

Before we create the Live Assist configuration we’ll need to create a bot. In my example I’m going to create a simple Q&A bot. The scenario being that visitors to my web site will “talk” with my Q&A bot, it might be answering questions commonly found in my knowledge base or FAQs. However my bot can’t know everything! So when asked a question it can’t answer it will offer an option to transfer you to a human operator.

My example will be relatively simple but I hope you’ll be able to use it to understand the basics of creating a BOT. And therefore adapt it for your own purposes.

The steps involved are;

  1. Create a Q&A BOT
  2. Train the BOT
  3. Enable the BOT for use with Live Assist
  4. Configure the BOT in Live Assist
  5. Create a campaign that will trigger the BOT

Step One – Create a BOT

The Microsoft Bot Framework is part of azure, so you will need a subscription on “portal.azure.com”. (Or a trial!) Open portal.azure.com, select “New” and search for “Bot Service”.

Select the “Bot Service” option and then click create.

Next I simply name my bot and click create.

After a short pause my bot service will be provisioned and I can now open it and begin to configure. I have opted to use “NodeJS” for the code that I will cut and paste! And to create a Q&A bot.

Next you will need to generate an App ID. Click on “Manage Microsoft App ID and password”. This will generate you a password. You will need to copy the password and paste it into the password field.

Now you can agree the terms of use and select the “Create bot” option.

As we are creating a QnA bot you’ll now be given an option to connect to the Azure QnA maker.

We can select an existing knowledge base, if you have one. Or opt to create a new one. Being my first bot, we’ll need to select “Create a new knowledge base”. After you click “OK”, you will see a message that you bot is being provisioned. These stage could take a few minutes.

After a pause you’ll be presented with a screen like this. We are now ready to configure our bot. (Note: We’ll come back to the QnA maker in a minute!)

Click on “Open online code editor”.

In the online code editor you need to find the app.js file in explorer. (As shown below.)

Initially the code will be for a template that is used for a standard QnA bot. We want our bot to be able to connect with Live Assist and hand chats over to humans when needed. For this you’ll need to make some code alterations.

Below you’ll see the code you’ll need. Simply remove all of the code shown initially and replace it with these details.

const transfer_skill = 'human';
var restify = require('restify');
var builder = require('botbuilder');
var builder_cognitiveservices = require("botbuilder-cognitiveservices");
var path = require('path');
var useEmulator = (process.env.NODE_ENV == 'development');

// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
   console.log('%s listening to %s', server.name, server.url); 
});
  
// Create chat connector for communicating with the Bot Framework Service
var connector = new builder.ChatConnector({
    appId: process.env.MicrosoftAppId,
    appPassword: process.env.MicrosoftAppPassword,
    stateEndpoint: process.env.BotStateEndpoint,
    openIdMetadata: process.env.BotOpenIdMetadata 
});

// Listen for messages from users 
server.post('/api/messages', connector.listen());

/*----------------------------------------------------------------------------------------
* Bot Storage: This is a great spot to register the private state storage for your bot. 
* We provide adapters for Azure Table, CosmosDb, SQL Azure, or you can implement your own!
* For samples and documentation, see: https://github.com/Microsoft/BotBuilder-Azure
* ---------------------------------------------------------------------------------------- */

// Create your bot with a function to receive messages from the user
var bot = new builder.UniversalBot(connector);
bot.localePath(path.join(__dirname, './locale'));


var recognizer = new builder_cognitiveservices.QnAMakerRecognizer({
                knowledgeBaseId: process.env.QnAKnowledgebaseId, 
    subscriptionKey: process.env.QnASubscriptionKey});

var basicQnAMakerDialog = new builder_cognitiveservices.QnAMakerDialog({
    recognizers: [recognizer],
                defaultMessage: 'No match! Try changing the query terms!',
                qnaThreshold: 0.3}
);


basicQnAMakerDialog.invokeAnswer = function (session, recognizeResult, threshold, noMatchMessage) {
        var qnaMakerResult = recognizeResult;
        session.privateConversationData.qnaFeedbackUserQuestion = session.message.text;
        if (qnaMakerResult.score >= threshold && qnaMakerResult.answers.length > 0) {
            if (basicQnAMakerDialog.isConfidentAnswer(qnaMakerResult) || basicQnAMakerDialog.qnaMakerTools == null) {
                basicQnAMakerDialog.respondFromQnAMakerResult(session, qnaMakerResult);
                basicQnAMakerDialog.defaultWaitNextMessage(session, qnaMakerResult);
            }
            else {
                basicQnAMakerDialog.qnaFeedbackStep(session, qnaMakerResult);
            }
        }
        else {
                noMatch(session, noMatchMessage, qnaMakerResult);
        }
    };
    
function noMatch(session, noMatchMessage, qnaMakerResult) {
            session.beginDialog('/offer_transfer');
            
};

bot.dialog('/qna', basicQnAMakerDialog);

bot.dialog('/offer_transfer', [
    function (session)
    {
        builder.Prompts.confirm(session, "I'm afraid I cannot help you with that. Would you like to be transferred to a human agent?");
    },
    function(session, results)
    {
        if (results.response)
        {
            session.send('I will transfer you now.');
            let msg = new builder.Message(session).sourceEvent({directline: {type: "transfer", skill: transfer_skill}});
            session.send(msg);
        }
        else
        {
            session.endDialog('Great! What else can I help you with?');
        }
    }
]);

bot.dialog('/force_transfer', function(session){
    session.send('I am going to transfer you to a human agent that can assist you better.');
    let msg = new builder.Message(session).sourceEvent({directline: {type: "transfer", skill: session.message.text}});
    session.send(msg);
});

bot.dialog('/', function (session) {
    switch(session.message.sourceEvent.type)
    {
        case "visitorContextData":
            //this is the first message type received and marks the start of a chat conversation
            let hi = 'Hi';
            if (session.message.sourceEvent.firstName)
            {
               hi += ' ' + session.message.sourceEvent.firstName;
            }
            
//            session.send('firstName = %s', session.message.sourceEvent.firstName);
//            session.send('lastName = %s', session.message.sourceEvent.lastName);
//            session.send('email = %s', session.message.sourceEvent.email);
            session.send('%s, I am the resident bot.', hi);
            session.send('If I am unable to answer your question, I will transfer you to our human department!');
            //session.send('How can I help you today?');
            break;

        case "systemMessage":
            //I am not interested in any system messages that are generated
            break;

        case "transferFailed":
            session.send('I am sorry, but I am unable to transfer you at the moment: '+session.message.sourceEvent.reason);
            break;

        case "otherAgentMessage":
            //If this is an internal message, then I will use it as a trigger to transfer to the skill group specified.
            if (session.message.sourceEvent.isInternal)
            {
                session.beginDialog('/force_transfer');
            }
            break;

        case "visitorMessage":
            session.send(new builder.Message(session).sourceEvent({directline: {type: "typing"}}));
            session.beginDialog('/qna');
            break;

        default:
            session.beginDialog('/qna');
    }
});

if (useEmulator) {
    var restify = require('restify');
    var server = restify.createServer();
    server.listen(3978, function() {
        console.log('test bot endpont at http://localhost:3978/api/messages');
    });
    server.post('/api/messages', connector.listen());    
} else {
    module.exports = { default: connector.listen() }
}

Note: This is a simple example. In a production version you may need to revise some of this code. But hopefully you can use this bot as a template.

To explain, when a bot hands over to a human this is done by skill set. In my simple example, my bot has a skill called “NeilsFirstBot”. All of my human agents have a skill called “Human”. This way campaigns / engagements can be targeted at my bot or a human. In a production version of this approach no doubt your humans would have more skills! I am using just two skills to support this simple demo.

Step Two – Train the BOT

Before we look at how to include our newly created bot into Live Assist, we’ll want to educate it! The bot needs to know what the possible questions and answers could be. Additionally we might need to train it to help ensure its answers are accurate.

You can access the QnA maker here …. https://qnamaker.ai/

When you first load it you’ll see a screen like this. Simply click “My Services” to see you QnA services.

Under my services I have two, one named “Basic QnA KB-2017 etc”. This was created when we created out bot. The other one called “SuperHeros” was one I created earlier.

Tip:
Initially your QnA service will have this strange looking name. Later you can use the settings option to rename it into something more meaningful.

Having clicked the “pencil” icon we are presented with a screen like the one below. Use the “Add new QnA pair” option to enter questions and answers.

Tip:
You can use the settings option to upload questions / answers from files if required. That might be a more efficient approach if you have loads of pre-prepared FAQs.

Before publishing our question / answer pairs it is often useful to test them out and train the bot. See below that in test mode I can see the question and possible answers. Initially when I asked about “phone” it gave me an incorrect answer, it wrong guessed that I needed to know my address. I assume this was because in my QnA pair I used the work “telephone” rather than the phrase “phone number”. To train the bot I corrected its answer and then clicked “save and retrain”.

Before I published my bot, I used the settings option to change the service name.

FYI: It is also in this settings option that you could upload files containing questions/answers. Or even give a url to you FAQ page, assuming you have one already.

Once I am happy with my bot I click the publish button to make it live. (Once you have this working …. you can of course come back and edit / add more questions publish again.)

Step Three – Enable the BOT for use with Live Assist

I now want to add my bot into Live Assist. But before I do one additional test is a wise step. Return to Microsoft Azure and quickly use the test option to prove that the bot will respond with the expected answers to your questions. You can see below that my bot gave sensible answers to “Hi” and “What is your phone number”.

Confident my bot is working I now want to enable it on a direct channel. This will allow us to then add it into Live Assist. Select the channels option and then the direct channel icon.

Selecting the direct line channel will provide a screen like this. You have two secret keys, you’ll need to copy one of them for use in Live Assist. Then click “Done” to enable the direct channel.

Tip:
To copy the key click show and then select / copy the key. (aka Control A to select and Control C to copy!)

Once you have done this you should see the health of the direct line channel change to “Running”.

Step Four – Configure the BOT in Live Assist

Our bot is now ready to build into Live Assist. I mentioned earlier that the bot is essentially like a user. Therefore it should come as no surprise that when you open the admin portal for Live Assist you will find the “Bots” option under users.

In the Bots option simply click Add to create the bot. See I have a couple of other bots already created.

When we create a bot, firstly give it a nickname. Keep in mind that this name maybe seen by visitors to yoru website.

Next enter the number of licenses you want the bot to consume. Bots are like users! So that consume Live Assist user licenses. But for each license assigned you bot can handle 3 concurrent chats. So 1 license for 3 chats, 2 license for 6 chats, 5 licenses for 15 chats etc.

Next you will need to paste the secret key you copied when creating the direct line channel into the connect key field.

Once the bot has been saved you will see it as a user in the engagement hub of Live Assist. Here you can open the bot and assign one or more skills.

In my simple example I have given my bot a skill of “NeilsFirstBot”. Simply to separate it from my human agents. Who all have a skill of “Human”!

Step Five – Create a campaign that will trigger the BOT

Now my bot is ready to be included in a campaign / engagement. This process is the same as for any engagement in Live Assist. You will simply need to ensure the engagement is linked to the required skill.

In my example I did fairly minimal customizations, although I did alter the chat dialog to make it obvious the customer will be chatting with a bot.

Having created my engagement I published my campaign. Notice that the skill is “NeilsFirstBot”.

At this point I probably would have needed to take time to configure the engagement window, location of the chat dialog and visitor behaviours. But for my simple example I accepted the defaults and enabled my chat on the entire website.

Running my bot

With all the steps complete I can now run my bot. For the purpose of a demo I stuck with the CaféX demo site. But this same approach can easily be applied to any website. See that the page visitor is offer webchat. But rather than being with a human I am offering a bot chat.

After a short pause my bot kicks in and asks the web site visitor how “he/she” can help.

Entering comment questions results in the bot responding with sensible answers.

Notice that I entered a question of “When do you open” but in the QnA maker the question was “What are your opening hours?”. The Microsoft Bot Framework has been able to “guess” at the best answer and still responds with a useful response.

All is well until the bot is asked a more complex question. Like “Do you have stock of my favourite product?”. The bot obviously doesn’t know what my favourite product is. Unable to help it can then offer the support of a human agent. Typing “Yes” would transfer you to the first available human. Typing no would allow the visitor to continue questioning the bot.

As I entered “yes” the chat is transferred to the first available human agent. You can see below that “Neil” has now taken over from the bot.

Live Assist is integrated with Dynamics 365. Obviously! Below you can see that I have opened the chat in Dynamics 365. Importantly the human agent can see the conversation history with the bot. Meaning the customer will hopefully not have to repeat themselves.

Obviously this has been a simple example but I hope you can see that creating a bot to work with Live Assist and Dynamics 365 is relatively straight forward.

One final comment would be that I have shown a user picking up the transferred chat within the Dynamics 365 web client. This works perfectly well. But within a contact centre it will be common for each agent to need to juggle multiple webchat conversations. In that scenario I would advocate the use of Unified Service Desk (USD).

I hope this post has been informative and that you find “playing” with bots fun.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s