Connecting LUIS to Microsoft Bot Framework - node.js

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?

Related

Discord.js SetNickname Function Is Not Working

I am trying to make a bot that gives a role and sets nickname of it's user.
My goal is if someone types " -verify SomeNickname " on the text channel the bot will set their nickname as SomeNickname and give them a certain role.
mem.AddRole is working without any errors but .setNickname function is not working with anything.
The error is TypeError: mem.setNickname is not a function
This duplicate thread did not work for me: Change user nickname with discord.js
I also tried:
message.member.setNickname & message.author.setNickname &
client.on('message', message => {
if (message.content.startsWith('-verify')) {
message.author.setNickname({
nick: message.content.replace('-verify ', '')
});
}
});
so far.
My code is:
module.exports = bot => bot.registerCommand('verify', (message, args) => {
message.delete();
var title = args.join(' ');
var mem = message.member;
mem.addRole('560564037583241227').catch(console.error);
mem.setNickname(title);
}
The bot is giving the role without any problems but its not setting a nickname to the user.
Additional Info: Bot has every permission and im not trying to change server owner's nickname.
The message.member object looks like this:
As determined through the chat, your current code is using discord.io, not discord.js. These libraries are different, so that's the source of your various issues.
I'd recommend using discord.js from now on, but you may have to restructure your code a little bit. Documentation can be found here for future reference.
If you'd like to continue using discord.io, you can edit your question to be clearer, although from our conversation you don't intend to.

How can i set default answer in Q&A Azure bot

I want change Default Answer in Q&A Maker Azure Framework Bot, but I cant find field that respond this value. I'm reading documentation (but it looks like it uses an older interface), and I'm trying to find this field but with result.
Here's my current configuration screen:
I'm assuming that you're referring to these docs: QnaMaker - Change Default Answer
They're a little confusing, but they key part is:
You can override this default response in the bot or application code
calling the endpoint.
Where the docs have this image:
What they actually mean is that in the QnAMaker Test Console, you can edit the default answer from your Application Settings. Be sure to Save, Train, and Publish your app or the setting may not show.
There's also kind of a way that you can use this setting for your default answer in a bot:
In Node/JS, your bot will not receive that DefaultAnswer at all. It receives nothing if there isn't a match, so you have to hard code it with something like:
const qnaResults = await this.qnaMaker.getAnswers(context);
// If an answer was received from QnA Maker, send the answer back to the user.
if (qnaResults[0]) {
await context.sendActivity(qnaResults[0].answer);
// If no answers were returned from QnA Maker, show this reply.
// Note: .getAnswers() does NOT return the default answer from the App Service's Application Settings
} else {
const defaultAnswer = 'No QnA Maker answers were found. This example uses a QnA Maker Knowledge Base that focuses on smart light bulbs. To see QnA Maker in action, ask the bot questions like "Why won\'t it turn on?" or "I need help."'
await context.sendActivity(defaultAnswer);
}
When creating an Azure Web Bot, one of the default Web Chat clients is a fork of microsoft's BotBuilder-Samples project, specifically 49 - QnAMaker All Features
The source code for Dialog/QnAMakerBaseDialog.cs defines the constant DefaultNoAnswer:
public const string DefaultNoAnswer = "No QnAMaker answers found.";
And then uses that value when returning a response from GetQnAResponseOptionsAsync:
protected async override Task<QnADialogResponseOptions> GetQnAResponseOptionsAsync(DialogContext dc)
{
var noAnswer = (Activity)Activity.CreateMessageActivity();
noAnswer.Text = DefaultNoAnswer; // <- used right here
var cardNoMatchResponse = (Activity)MessageFactory.Text(DefaultCardNoMatchResponse);
var responseOptions = new QnADialogResponseOptions
{
ActiveLearningCardTitle = DefaultCardTitle,
CardNoMatchText = DefaultCardNoMatchText,
NoAnswer = noAnswer,
CardNoMatchResponse = cardNoMatchResponse,
};
return responseOptions;
}
This particular sample repo doesn't appear to leverage the DefaultAnswer configuration key anywhere.
You can opt to include it when available by updating the noAnswer.Text like this:
- noAnswer.Text = DefaultNoAnswer;
+ noAnswer.Text = this._configuration["DefaultAnswer"] ?? DefaultNoAnswer;
You'll also have to pass in the configuration object through the dependency management system. See this commit for a full example.
Change the line in qamakerBaseDialog.js as below
var noAnswer = ActivityFactory.DefaultNoAnswer;
Remove ActivityFactory. and rebuild the code.
constructor(knowledgebaseId, authkey, host) {
//ActivityFactory.
var noAnswer = DefaultNoAnswer;
var filters = [];
super(knowledgebaseId, authkey, host, noAnswer, DefaultThreshold, DefaultCardTitle, DefaultCardNoMatchText,
DefaultTopN, ActivityFactory.cardNoMatchResponse, filters, QNAMAKER_BASE_DIALOG);
this.id = QNAMAKER_BASE_DIALOG;
}

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 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

How can I properly get my Luis chatbot working?

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.

Resources