How can I properly get my Luis chatbot working? - node.js

I have to connect Luis to node.js and create my first chatbot that, as a first stage should handle simple requests.
I have checked the following links :
https://learn.microsoft.com/en-us/bot-framework/nodejs/bot-builder-nodejs-recognize-intent-luis
https://github.com/Microsoft/BotBuilder-Samples/tree/master/Node/intelligence-LUIS
but getting started has proven to be difficult, what I've done as a first stage is:
var restify = require('restify');
var builder = require('botbuilder');
var http = require('http');
var recognizer = require ('recognizer');
// 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: MY_APP_ID,
appPassword:MY_PASSWORD
});
var bot = new builder.UniversalBot(connector, function (session,args) {
}
});
var recognizer = new builder.LuisRecognizer(LUIS_ENDPOINT_URL);
bot.recognizer(recognizer);
and not sure how to move forward from here.
What I have in a Luis intent is: calendar.add
what I have as entities is: calendar.location and calendar.subject
what I want the user to say in the bot framework channel emulator:
add a business meeting schedule in Paris.
What the bot should say: Understood the location is Paris and subject is business meeting.

It seems that the utterance add a business meeting schedule in Paris. doesn't match the Calendar.Add intent. So you can try to manually add this utterance in the intent in your LUIS application.
Go to your LUIS application, click Intents list, click Calendar.Add into the edit page.
Type the utterance add a business meeting schedule in Paris. in the box, type enter add the utterance into the list.
Click the business and meeting letters into a big square brackets, select Calendar.Subject in dropdown list, the same click Paris and select Calendar.Location. Finishing the actions, it should looks like:
Click Save to save the edition. Then Train and publish your LUIS application.
Then your bot should match the utterance.

Related

Pass User to Conversation

I want to have someone say to a bot in slack:
#Bot setup #usertosetup
This should then start a conversation with that user to be setup. If I'm right and I've read correctly, the one that starts the conversation with the bot will be the one it listens to?
So the flow would be to bring the new user, an admin and the bot into their own room on slack, then start the conversation. Ideally, would be if you could say in the main chat window that phrase and it starts a private message with the user to set up, but I don't think that's possible due to the channel not existing yet?
I'm using Botkit to get this done.
Solved it.
controller.hears('setup','direct_mention', function(bot,message) {
var x = message.text.indexOf("#");
var usr = message.text.substr(x - 2, message.text.length);
usr = usr.substring(3, usr.length - 1);
bot.api.im.open({user: usr}, function(err, response) {
bot.startConversation({
user:usr,
channel: response.channel.id
}, "Hello");
});
So, it finds the index of the message sent to the bot with the # symbol, pulls it out and does some substring fun to reduce it. Then, launches the conversation by the channel.

How to add Get Started button in the typing bar using bot builder sdk for node.js

I am using bot builder sdk for node.js to create a chatbot. Also connected it to facebook channel. I am using the following code to greet the user:
var bot = new builder.UniversalBot(connector, [
(session, result, next) => {
let text = '';
switch(session.message.address.channelId) {
case 'facebook':
text = 'Hi ' + session.message.user.name + ' !';
break;
default:
text = 'Hi !';
}
session.sendTyping();
session.say(text);
next();
},
(session, say) => {
}
]);
The above code works fine, but I want to add "Get Started" button in the typing bar to invoke the above code. Note that this button appears only once. Please find image of the typing bar below:
Is there a way to achieve this using bot builder sdk for node.js ?
Thanks
Although one can certainly add a button to start any activity with the bot, but that will limit the bots potential to only one customizable channel, i.e. WebChat.
I think there are better 2 alternative ways to get the desired functionality which will work across many channels.
First
I would suggest to add a conversation update event. Code goes in the botbuilder's middleware. Here is a sample code from the docs.
bot.on('conversationUpdate', function (message) {
if (message.membersAdded && message.membersAdded.length > 0) {
// Say hello
var txt = "Send me a Hi";
var reply = new builder.Message()
.address(message.address)
.text(txt);
bot.send(reply);
});
What this will do is make the bot send a message Send me a Hi to the user, if it determines this is a first time visitor. This will give the visitor enough cue to send the bot Hi by typing it. Although he can enter whatever he wants, but this will result in the invocation of the 1st dialog configured which in this case is the will be the dialog which you have posted in question.
Second
You can mark some dialog to be invoked automatically if your bot has never encountered this visitor. Here is the sample code...
var bot = new builder.UniversalBot(connector);
bot.dialog('firstRun', function (session) {
session.userData.firstRun = true;
session.send("Hello...").endDialog();
}).triggerAction({
onFindAction: function (context, callback) {
// Only trigger if we've never seen user before
if (!context.userData.firstRun) {
// Return a score of 1.1 to ensure the first run dialog wins
callback(null, 1.1);
} else {
callback(null, 0.0);
}
}
});
Here we have split the bot creation and dialog registration in 2 steps. And while registering the firstRun dialog, we have provided it the triggerAction that if the visitor is new, then trigger this dialog.
Both of these approaches do not use adding some extra buttons and it is up to the bot either to educate him on sending some message which in turn will start the 1st dialog or directly start some dialog.
For more info on conversationEvent you can refer to this page
I tried the above options, but they didn't seem to be working for facebook messenger. But I found a solution to add the Get Started button into the typing bar of the messenger. For that we need to use the Facebook Graph API and not the bot builder sdk.
https://graph.facebook.com/v2.6/me/messenger_profile?access_token=<PAGE_ACCESS_TOKEN>
{
"get_started":{
"payload":"Get Started"
}
}
The above API call will add the button for you to get the conversation started.
Thanks all for the help!!

How to catch conversation ending event?

Using Microsoft BotBuilder, I want to catch event when user close or terminate a conversation with my bot. Here is the code of my bot:
const builder = require('botbuilder');
const connector = new builder.ChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
const inMemoryStorage = new builder.MemoryBotStorage();
const bot = new builder.UniversalBot(connector).set('storage', inMemoryStorage);
initialize(bot);
function initialize(bot) {
bot.on('conversationUpdate', function(data) {
});
}
From the block of code above, I want to add an event that will handle ending conversation. Here is my example code:
function initialize(bot) {
bot.on('conversationEnd', function(data) {
var user = data.user,
address = data.address,
conversationId = data.address.conversation.id;
});
}
So, is there an event of conversationEnd like above code? I want to know if botBuilder can handle an ending conversation?
There is no event like converstaionEnd. Think of it in this way. If you are chatting with someone, you can just opt to not reply anymore. To a human user, it will seem that conversation has ended, but bot will not have any clue. It will keep on waiting. Unless you provide the intelligence to bot, to wait for a certain amount of time before considering that conversation has ended.
That said there are some other things you can handle:
You can handle conversationUpdate event. This event is triggered when any member joins/leaves a converstaion. Example
You can use a certain keyword (like goodbye, exit, etc.) as conversation ending keyword, which can trigger endConversationActionExample

How to integrate LUIS and QnA Maker services in single Node.js bot?

I'm developing a chatbot using Microsoft Bot Framework with Node.js SDK. I've integrated LUIS and QnA maker but I want to create this scenario if it's possible. Taking in example the following link and in particular this section:
There are a few ways that a bot may implement a hybrid of LUIS and QnA Maker:
Call LUIS first, and if no intent meets a specific threshold score, i.e., "None" intent is triggered, then call QnA Maker. Alternatively, create a LUIS intent for QnA Maker, feeding your LUIS model with example QnA questions that map to "QnAIntent."
Just an example:
I have my QnA KB in which I have a pair : " who are you?" / "Hi I'm your bot! " . Then I have my Luis app that recognize this intent called "common" .
So, if I write to my bot: " who are you?" it will answer "Hi I'm your bot! "
Instead, if I write " tell me who you are" it recognize the LUIS intent related to the question but it will not answer "Hi I'm your bot! " like I imagine.
So what I imagine is: I ask the question "Tell me who you are" --> the bot triggers the intent common (LUIS) --> then I want that the bot will answer me looking into the QnA KB --> "Hi I'm your bot! "
Is it possible?
Hope this code could help:
var intents = new builder.IntentDialog({ recognizers[luisRecognizer,qnarecognizer] });
bot.dialog('/', intents);
intents.matches('common_question', [
function (session, args, next) {
session.send('Intent common');
qnarecognizer.recognize(session, function (error, result) {
session.send('answerEntity.entity');
});
}
]);
You will have to forward the user message to QnaMaker from the method/dialog associated to the intent detected by LUIS. Take a look to this article (https://blog.botframework.com/2017/11/17/qna-maker-node-js-bots/) to find how implement QnAMaker in Node.js
Something like:
var recognizer = new cognitiveservices.QnAMakerRecognizer({
knowledgeBaseId: 'set your kbid here',
subscriptionKey: 'set your subscription key here'});
var context = session.toRecognizeContext();
recognizer.recognize(context, function (error, result) { // your code... }
You should explore the samples also and try to understand how everything works: https://github.com/Microsoft/BotBuilder-CognitiveServices/tree/master/Node/samples/QnAMaker
If you vary a lot your question; could be possible that QnA won't detect the question you expected and in that case you will have to train your KB more (like you do in LUIS with the utterances/intents)
I wrote this because I want more practice with node and this was an excuse to use node, but what Ezequiel is telling you is completely correct. I'll also post on your GitHub issue. This is a functioning node app that does what you need
var builder = require('botbuilder');
var restify = require('restify');
var cog = require('botbuilder-cognitiveservices');
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function() {
console.log('%s listening to %s', server.name, server.url);
});
var connector = new builder.ChatConnector({
appId: "APP ID",
appPassword: "APP PASSWORD"
});
server.post('/api/messages', connector.listen());
var bot = new builder.UniversalBot(connector, function(session) {
session.send('Sorry, I did not understand \'%s\'. Type \'help\' if you need assistance.', session.message.text);
});
var recognizer = new builder.LuisRecognizer("https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/{LUIS APP ID}?subscription-key={LUIS KEY}&verbose=true&timezoneOffset=0&q=");
bot.recognizer(recognizer);
var qnaRecognizer = new cog.QnAMakerRecognizer({
knowledgeBaseId: 'QNA APP ID',
subscriptionKey: 'QNA SUBSCRIPTION KEY'
});
bot.dialog('Common', function(session) {
var query = session.message.text;
cog.QnAMakerRecognizer.recognize(query, 'https://westus.api.cognitive.microsoft.com/qnamaker/v2.0/knowledgebases/{QNA APP ID}}/generateAnswer', '{QNA SUBSCRIPTION KEY}', 1, 'intentName', (error, results) => {
session.send(results.answers[0].answer)
})
}).triggerAction({
matches: 'Common'
});
As of 2018 (BotBuilder V4)
You can now use the Dispatch Command Line tool to dispatch intent across multiple bot modules such as LUIS models and QnA.
So first you will get to LUIS app that will decide based on the score to redirect to another LUIS app or to a QnA.
Dispatch Tool
Example using LUIS as dispatch service

Connecting LUIS to Microsoft Bot Framework

Over the holiday weekend, I've been trying to get a bot working using the Microsoft Bot Framework. I'm using version 3.9.1 of the botbuilder package for Node.js.
I've created an app and model at www.luis.ai. I have been able to successfully test my intents via the "Train & Test" feature. Then, in my actual Node code, I have the following:
let connector = new BotBuilder.ChatConnector({
appId: 'myId',
appPassword: 'myAppSecret'
});
let bot = new BotBuilder.UniversalBot(connector);
let luis = new BotBuilder.LuisRecognizer('myLuisAppUrl');
let intent = new BotBuilder.IntentDialog({ });
intent.recognizer(luis);
intent.matches('Intent.1', '/execute-report');
intent.matches('Intent.2', '/execute-batch-job');
intent.onDefault('/unknown');
bot.dialog('/', intent);
bot.dialog('/execute-report', [function(session, args, next) {
var result = ((Date.now() % 2) === 0) ? 'Report Ran!' : 'Failed';
session.send(result);
}]);
bot.dialog('/execute-batch-job', [function(session, args, next) {
var result = ((Date.now() % 2) === 0) ? 'Batch Job Ran!' : 'Unable to run Batch Job';
session.send(result);
}]);
bot.dialog('/unknown', [function(session, args, next) {
session.send('What did you ask for?');
}]);
When interacting with my bot, I always get "What did you ask for?". In other words, at this point, I know that:
I can successfully interact with my bot. However, the /unknown dialog is always being called, which is not the correct interaction.
My model in LUIS looks correct:
a. If I enter "Run Report" in the LUIS.ai Test app, the top scoring intent is "Intent.1"
b. If I enter "Execute Batch Job" in the LUIS.ai Test app, the top scoring intent is "Intent.2"
However, my bot is not sending the appropriate response. The /execute-report and /execute-batch-job dialogs are never used, even though they should be. I don't understand what I'm doing wrong. To me, I believe I've setup my bot correctly. I don't see what I'm doing wrong. Can someone please tell me what I'm doing wrong? Is there a way to see the response returned from LUIS in my Node code similar to what's seen in the "Test" app at LUIS.ai
If you go to line 89 of the LuisRecognizer and add the following on a new line: console.log(result); you will see the LUIS response object that your bot has received.
Your code looks correct to me, so the issue might be on the LUIS side. Have you published your app?

Resources