what does `'CreateNote'`represent in this section? - node.js

Referring to this link https://learn.microsoft.com/en-us/bot-framework/nodejs/bot-builder-nodejs-recognize-intent-luis
I took this code section :
// CreateNote dialog
bot.dialog('CreateNote', [
function (session, args, next) {
// Resolve and store any Note.Title entity passed from LUIS.
var intent = args.intent;
var title = builder.EntityRecognizer.findEntity(intent.entities, 'Note.Title');
var note = session.dialogData.note = {
title: title ? title.entity : null,
};
What i don't understand is what does 'CreateNote'represent in this section?
And referring to this line :
var title = builder.EntityRecognizer.findEntity(intent.entities, 'Note.Title');
Assuming my intent name is calendar.add and my entity name calendar.location
will the intent.entities calendar.add.calendar.location create any confusion.

That's the internal identifier of the dialog, and can be referenced where necessary.
Regarding the second part, I don't think it will create confusion, but if you'll get back to this code two weeks later, you will scratch your head thinking why is it named that way, so it's more of a logistics kind of thing, in my opinion.

Taken from the official https://learn.microsoft.com/en-us/bot-framework/nodejs/bot-builder-nodejs-dialog-manage-conversation-flow . The 'CreateNote' is an identifier of your dialog and it can be used like this:
var inMemoryStorage = new builder.MemoryBotStorage();
var bot = new builder.UniversalBot(connector,
function (session) {
session.send("Welcome");
session.beginDialog('perroDialog'); //Use beginDialog with the
//dialog identifier for starting perroDialog
}
).set('storage', inMemoryStorage); // Register in-memory storage
//--------------------------DIALOGS WATERFALL------------------------
bot.dialog('perroDialog',
function (session) {
session.send('You started perroDialog');
session.endDialog(); //Back to / dialog (UniversalBot callback)
});

Related

Add QnA users questions and answers to Insights telemetry in Node JS

I need to send QnA users questions and answers to my Azure bot insights using telemetry. Already tried this tutorial :
https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-telemetry?view=azure-bot-service-4.0&tabs=javascript
And this SO posts:
How to get the Qna Maker "Q" from Analytics Application Insights?
How can I save some custom qna maker data in azure app insights?
Thing is, first it's done for LUIS and gives no additional info to Insights, also nothing for QnA...second ones are written for C#...
I need to send question and answer to customEvents logs on Azure insights using NodeJS but I can't find how, any help ?
Thanks in advance.
///// EDIT:
Here's what I got so far (only posted the code related to the telemetry and QnA that's already working fine):
Index.js
const { ApplicationInsightsTelemetryClient, TelemetryInitializerMiddleware } = require('botbuilder-applicationinsights');
const { TelemetryLoggerMiddleware } = require('botbuilder-core');
function getTelemetryClient(instrumentationKey) {
if (instrumentationKey) {
return new ApplicationInsightsTelemetryClient(instrumentationKey);
}
return new NullTelemetryClient();
}
const server = restify.createServer();
server.use(restify.plugins.bodyParser());
var telemetryClient = getTelemetryClient(process.env.InstrumentationKey);
var telemetryLoggerMiddleware = new TelemetryLoggerMiddleware(telemetryClient);
var initializerMiddleware = new TelemetryInitializerMiddleware(telemetryLoggerMiddleware);
adapter.use(initializerMiddleware);
const mybot = new MYBOT(conversationState,userState, telemetryClient);
mybot.js
class MYBOT extends ActivityHandler {
constructor(conversationState,userState,telemetryClient) {
super();
this.conversationState = conversationState;
this.userState = userState;
this.telemetryClient = telemetryClient;
}
}
//This is how I get my qna result:
console.log(this.telemetryClient);
var result = await this.qnaMaker.getAnswers(context);
As You can see, I pass the telemetryClient to the bot file, and if I console log that item I get the complete telemetry object, but how I pass it the user question and answer so its save on insights customevents ??
Found a way to it, in case people that's looking for one of the possible solutions for Node may need it :
Basically, We use the same telemetry code process described in oficial documentation for instancing telemetry on index.js :
const { ApplicationInsightsTelemetryClient, TelemetryInitializerMiddleware } = require('botbuilder-applicationinsights');
const { TelemetryLoggerMiddleware } = require('botbuilder-core');
function getTelemetryClient(instrumentationKey) {
if (instrumentationKey) {
return new ApplicationInsightsTelemetryClient(instrumentationKey);
}
return new NullTelemetryClient();
}
const server = restify.createServer();
server.use(restify.plugins.bodyParser());
var telemetryClient = getTelemetryClient(process.env.InstrumentationKey);
var telemetryLoggerMiddleware = new TelemetryLoggerMiddleware(telemetryClient);
var initializerMiddleware = new TelemetryInitializerMiddleware(telemetryLoggerMiddleware);
adapter.use(initializerMiddleware);
const mybot = new MYBOT(conversationState,userState, telemetryClient);
Then, we pass it to the bot file (bot.js or the one you´re using):
class MYBOT extends ActivityHandler {
constructor(conversationState,userState,telemetryClient) {
super();
this.conversationState = conversationState;
this.userState = userState;
this.telemetryClient = telemetryClient;
}
}
And later in code, You can use telemetry.trackEvent method (Official docs are only in C#), but basically, it allows you to create a custom event you want to track in specifics events in your code, like when You're bot has an error or doesn´t found an answer to user. Code according to previous lines would be like this:
this.telemetryClient.trackEvent(
{name: "myEvent",
properties: {my_user_question: 'Context activity text here or your captured question',
my_bot_answer: 'bot reply or whatever'}
}
); // name and properties are part of the sintaxys, values inside properties object as you may need.
That way, on Azure insights customEvents model You will see records captured with the event name you used, also, with the properties objects as a dict in customdimensions field.

Use multiple QnA services in one bot

I have multiple QnA services running, each with it's own knowledgeBaseId and subscriptionKey. I want to use them both in a single chatbot and I've written a piece of code which takes the user input and assigns the correct Knowledgebase details. However, I'm unable to get the 2nd QnA service to become active and the bot is linking only to the first service. What might be going wrong here?
Sample code:
var knowledgeId = "FIRST_QNA_SERVICE_KNOWLEDGE_ID";
var subscriptionId = "FIRST_QNA_SERVICE_SUBSCRIPTION_ID";
var bot = new builder.UniversalBot(connector);
var qnarecognizer = new cognitiveservices.QnAMakerRecognizer({
knowledgeBaseId: knowledgeId,
subscriptionKey: subscriptionId,
qnaThreshold:0.3,
top:1});
var intentrecognizer = new builder.IntentDialog();
var intents = new builder.IntentDialog({ recognizers: [intentrecognizer, qnarecognizer] });
bot.dialog('/', intents);
intents.matches('qna', [
function (session, args, next) {
args.entities.forEach(function(element) {
session.send(element.entity);
}, this);
}
]);
intents.matchesAny([/hi/i, /main menu/i], [
function (session) {
builder.Prompts.choice(session, "Hi, What would you like to ask me about?", ["Service1","Service2"],{ listStyle: builder.ListStyle.button});
},
function (session, result) {
var selection = result.response.entity;
switch (selection) {
case "Service1":
knowledgeId = "FIRST_QNA_SERVICE_KNOWLEDGE_ID";
subscriptionId = "FIRST_QNA_SERVICE_SUBSCRIPTION_ID";
session.send('You can now ask me anything about '+selection+'. Type \'main menu\' anytime to choose a different topic.')
session.endConversation();
return
case "Service2":
knowledgeId = "SECOND_QNA_SERVICE_KNOWLEDGE_ID";
subscriptionId = "SECOND_QNA_SERVICE_SUBSCRIPTION_ID";
session.send('You can now ask me anything about '+selection+'. Type \'main menu\' anytime to choose a different topic.')
session.endConversation();
return
}
}
])
You never updated the knowledgeId/subscriptionId on the QnAMakerRecognizer... that's the reason you are always seeing the first QnA service being called.
See if there is a way to update those values in the QnAMakerRecognizer.
Check out if my answer is valid to your purpose on this question:
Multiple QnA Maker services for a single bot
Hope you find it useful.

Microsoft Bot Framework WebChat: Add bot image

How to add image of the bot with some welcome text in the middle in Microsoft Bot Framework Web Chat. Seems like quite common functionality and I see images which indicates that is possible.
Anyone knows how to add it?
you can use the below code and replace your image path to give response from bot to user including text and image.
await context.PostAsync("Here we go with the welcome message\n"+"![AN IMAGE!](Your_Image_URL)");
Another way is, you can also use Card functionality:
private async Task Greeting(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
if (string.IsNullOrEmpty(message.Text))
{
// Hero Card
var cardMsg = context.MakeMessage();
var attachment = BotWelcomeCard("Hello,I am a bot.", "");
cardMsg.Attachments.Add(attachment);
await context.PostAsync(cardMsg);
}
else
{
// else code
}
}
private static Attachment BotWelcomeCard(string responseFromQNAMaker, string userQuery)
{
var heroCard = new HeroCard
{
Title = userQuery,
Subtitle = "",
Text = responseFromQNAMaker,
Images = new List<CardImage> { new CardImage("../img/bot.gif") },
Buttons = new List<CardAction> { new CardAction(ActionTypes.ImBack, "Show Menu", value: "Show Bot Menu") }
};
return heroCard.ToAttachment();
}
ok, here is what we end up doing:
<script>
$(document).ready(function () {
$(".wc-header").append("<div class='wc-header-welcome'><img src='/Images/bot.png'/><div>Hello! I am your bot</div>");
});
</script>
Hope it will help save time to someone else.

newbie node.js bot integration with database lookup (looking for best practice)

OK, new to Node.js and botframework. I built first bot using Azure site and downloaded the code. Chose the Luis integrated bot template.
I understand (finally) the event driven model of node.js and the concept of callbacks.
I have the code snippet below. When Luis finds an intent of "Help" it triggers this function. In turn, I have database calls to lookup the entity. Within the database I have an entity, response (if entity is bottle, answer "Recycle").
I have that code working too.
Below the first block is a function handleHelpRequester which is the callback function, I have that working as well. Where I am a little stuck (best practice) is that in this callback function I want to send something to the session object (session.send toward the bottom of the function).
Since I don't create the session object (directly) I'm not sure on the options.
Should I pass the session object to the database function, then pass it back?
Should I create a global variable and set it to the session object (I'm concerned that if multiple people are using this bot then this approach won't work).
I'm open for suggestions.
Thanks
.matches('Help', (session, args) => {
var entities = args.entities;
var itype = builder.EntityRecognizer.findEntity(args.entities, 'ItemTypes');
var respondToUser = '';
var msg = 'Initialized';
// if there is an entity provided, perform a lookup of the entity.
if (itype.entity !== null) {
//Use session.sendTyping so the user thinks something is happening rather than being ignored while we do the lookup in SharePoint.
session.sendTyping();
//perform lookup
respondToUser = sp.lookupEntity(itype.entity, handleHelpRequest);
};
})
function handleHelpRequest(err, respondToUser) {
var msg = 'uninitialized';
if (err = 'success') {
console.log('Respond to user from matches:'.concat(respondToUser));
//return from lookup
if (respondToUser === 'No match found') {
msg = 'I think you are asking for help, but I don\'t understand what you need help with.';
}
else {
msg = 'I can help you with that, \'%s\'.', respondToUser;
}
console.log(msg);
session.send(msg);
//The following two lines are for debugging
session.send('How may I assist you? ' + JSON.stringify(args));
session.send('Value of entity you said: \'%s\'.', itype.entity);
}
else {
console.log('an error occurred');
}
}
If you want to have access to the session object, then pass it as a parameter to your helper function.
Example:
function handleHelpRequest(session, err, respondToUser) {
// do session stuff
}

Update and add new Firebase child nodes in Firebase web app at the same time

I have been able to push new information and call it on the database but I been looking for several days now and I can't seem to find anything.
I am looking to be able to update a node that already has a value and add a new node if it doesn't. Can anyone help me with this. New to Firebase.
Thanks
code:
function userProfileUpdate(users) {
newUsername = document.getElementById("newUsername");
// Profile Update.
var user = {
username : newUsername.value
};
return firebase.database().ref().update(user);
};
From your comments it seems that you want to store user information in a data structure like this:
users
uid1
userName: "Frank van Puffelen"
To add a specific user in this structure, you'd do:
function userProfileUpdate(users) {
var user = firebase.auth().currentUser;
var root = firebase.database().ref();
newUsername = document.getElementById("newUsername");
var user = {
username : newUsername.value
};
return root.child('users').child(user.uid).set(user);
};
Update
To update a specific property of a specific user:
Map<String, Object> updates = new HashMap<String,Object>();
updates.put("username", newUsername.value);
root.child('users').child(user.uid).updateChildren(user);
Or alternatively:
root.child('users').child(user.uid).child("username").setValue(newUsername.value);
Both will auto-create the location if it doesn't exist yet.
Frank your code took away the entire key but I did figure out with this
var user = firebase.auth().currentUser;
var root = firebase.database().ref();
newUsername = document.getElementById("newUsername");
firebase.database().ref('users/' + user.uid).update({
username: newUsername.value
});
Thanks Frank yours push me in the right direction.

Resources