In Bot Framework Composer turn.recognized.Intents contains only one intent - bot-framework-composer

I managed to make Luis return all intents in a query by adding
"predictionOptions":{
"includeAllIntents": true
}
to the recognizerFile: {dialogName}.en-us.lu.dialog
In the emulator I see the json that comes back containing several intents under turn.recognized.Intents. But if I make the bot send a message with the content of that collection then it just sends a collection with a single item, the top scoring intent.
Am I missing some configuration here that makes the deserialization of the Intents property to fail?

Related

Skill host generating new conversation IDs every turn, breaking waterfall dialogs

I'm working on converting some existing bots to skills so that we can create a Skill Host bot that can call multiple "child bots". I used the skills-simple-bot-to-bot sample, and it kind of works. I can call the skill bot from the host and it works...for a single turn. But the host is creating a new conversation ID every turn, clearing the conversation state which makes my multi-turn waterfall dialogs not work. It is also causing any other values stored in conversation state to be cleared (e.g. I capture email address in conversation state so I don't have to reprompt it). The skill bot works fine when invoked directly (i.e. not through the skill host), so it's definitely something with the way the skill host works. I found this issue on GitHub which seems to be the same thing (that's for .NET but there are links to the other SDKs including js), though it seems to have been resolved years ago yet I'm still having the issue so I'm not sure it's the same.
So in short, how do I set up the skill host so that it doesn't generate new conversation IDs every turn?
Not sure this will help as it's almost exactly the same as the sample, but here's a snippet of the code where it appears conversation ID is being generated by the host. It seems maybe I need some way to NOT call createSkillConversationIdWithOptions, but if that's what is required I'm not sure what I need to do to generate the skillConversationId other than what is currently in the sample.
async sendToSkill(context, targetSkill) {
// NOTE: Always SaveChanges() before calling a skill so that any activity generated by the skill
// will have access to current accurate state.
await this.conversationState.saveChanges(context, true);
// Create a conversationId to interact with the skill and send the activity
const skillConversationId = await this.conversationIdFactory.createSkillConversationIdWithOptions({
fromBotOAuthScope: context.turnState.get(context.adapter.OAuthScopeKey),
fromBotId: this.botId,
activity: context.activity,
botFrameworkSkill: this.targetSkill
});
// route the activity to the skill
const response = await this.skillClient.postActivity(this.botId, targetSkill.appId, targetSkill.skillEndpoint, this.skillsConfig.skillHostEndpoint, skillConversationId, context.activity);
// Check response status
if (!(response.status >= 200 && response.status <= 299)) {
throw new Error(`[RootBot]: Error invoking the skill id: "${ targetSkill.id }" at "${ targetSkill.skillEndpoint }" (status is ${ response.status }). \r\n ${ JSON.stringify(response.body) }`);
}
}

In a chatbot conversation using dialogflow, Is there a way to make the bot speak first?

Is it possible to format a conversation so that the bot initiates conversation using dialogflow in a web demo integration?
The objective is to say something like “Hi, I’m a bot, I can do x” to establish that it’s a chatbot rather than a human.
Can anyone suggest any idea for this?
You can set a welcome intent, then send a /query request containing an event parameter. Set the event parameter to WELCOME and your chatbot will respond with whatever conversation opening you set.
More info here: https://dialogflow.com/docs/events
If you are using something other than the API for interacting with your Dialogflow agent (Slack, Facebook Messenger, etc.) you will need to add an appropriate event under "intents" in your console (such as the "Facebook Welcome" event).
For interacting with your Dialogflow agent via the API, see below.
In the API interaction quickstart documentation, Dialogflow gives you the SessionClient's detectIntent method for sharing messages with your bot.
Each language has a different solution. But on an abstract level, you want to change the request object that you send to Dialogflow to include a "Welcome" event (no input message required), as Omegastick described.
For example, in Node.js, your request object would look like this:
// The text query request.
const request = {
session: sessionPath,
queryInput: {
event: {
name: "Welcome",
languageCode: languageCode
}
},
};
This assumes you have an appropriate intent set up in your Dialogflow console to handle Welcome events. One is provided by default that you can observe.
You can also add contexts, so that your agent gives a different greeting message based on some condition.

How can I delegate the LaunchRequest to an IntentRequest using the alexa-sdk from npm

I am building an Alexa skill in node using the alexa-sdk. I am using a dialog model to handle the user interaction. I am having some trouble passing the flow along to new request types, such as from the launch request to an intent request.
Below is an example of my handlers and what I want ideally. My specific usecase is that I would like to ask some questions of the user and then send them to different intents based on what they answer. In the intents I would like to have access to the request objects, as if they entered that intent originally, so the dialog model can do its work.
const handlers = {
'LaunchRequest': function () {
this.emit('Entry'); // this does not do what I want
},
'Entry': function () {
let request = this.event.request; // this is the launch request object.
// I would like to get the request object for Entry, like if the user started here
// ask some questions, potentially passing the torch to a new intent based on the answers
}
};
So, is there any way to "call" an intent like the user originally made a request to that intent? Sorry if I missed something obvious in the documentation, I searched around pretty thoroughly I think, but there is A LOT of documentation. ps: I could manually construct the request object of course, but I really should not have to I feel.
I am pretty sure there is no way yet to call on an intent as you are asking.
If you go through the syntax description of dialog directieves here, it says:
Note that you cannot change intents when returning a Dialog directive, so the intent name and set of slots must match the intent sent to your skill.
With returning a dialog directive you are able to 'elicit' or 'confirm' slots or intents, or even let a delegate handle your dialog for you, with prompts and reprompts set in the Skill Builder.
As far as i know, the only solution to trigger a specific intent is to make the user invoke it. You can guide the user into saying a specific utternace to trigger your intent.
As for saving older requests, you can use session attributes. Just build a response after your Launch with a session attribute containing the whole LaunchRequest.
"sessionAttributes": {
"oldRequest": this.event.request
}

How to build a slack bot to have multiple conversations?

I am building a slack bot using a third party service to handle responses based on inputs rather than just hard coding them into the bot. This service's API needs a client id & a conversation id to get the response. I found out that each time a slack bot receives a message, it creates a new message object each time so there isn't a way of keeping the clientID and conversation ID within the message object and have slack hold onto it.
rtm.on(RTM_EVENTS.MESSAGE, function(message // <-- new object each time the bot hears a message){
rtm.sendMessage('hello', message.channel);
});
So shortened down, does anyone know of a way to keep a conversation between a single user and the bot while holding onto some type of variable to hold the client and conversation ID?
You can store the message.user ID and track the conversation referring to that specific user. You will need to keep track of all ongoing conversations yourself. Something like this
rtm.on(RTM_EVENTS.MESSAGE, function(message // <-- new object each time the bot hears a message){
if(stored_conversations.indexOf(message.user) > -1){
//customize message depending on history
rtm.sendMessage('I remember you', message.channel);
}
});
Or, you could use Botkit - it manages bot-user conversations for you.

How to detect when bot was added to conversation and other events?

I am testing a bot that I am building using the Bot Framework. The emulator for local testing that Microsoft created has several events that can be provided to the bot to solicit a response.
I looked at the GitHub samples provided for Node.js here, but I can not find any example that responds to the different events within the Bot Framework Emulator.
The states are:
Bot Added to Conversation
Bot Removed from Conversation
User Added to Conversation
User Removed from Conversation
End of Conversation
Ping
Delete User Data
The API also does not make it clear how to achieve any of these actions.
Does anyone have any insight on where I should be looking for a example, or the API entries that I should be using?
In response to one of the answers, I did try code -
.onDefault(function (session) { console.log(session.message.type); }
But it only ever display "message" if a message was sent by the user.
The incoming message.type field will have "BotAddedToConversation" etc.
For the Node SDK, the botConnectorBot is able to trigger custom listeners on events using the on() handler.
Example
var builder = require('botbuilder');
var bot = new builder.BotConnectorBot({ appId: 'APPID', appSecret: 'APPSECRET' });
bot.on('DeleteUserData', function(message) {
// Handle Deleting User Data
});
More information can be found here.
You are also able to configure some standard messages using the configure() method.
Example
bot.configure({
userWelcomeMessage: "Hello... Welcome to the group.",
goodbyeMessage: "Goodbye..."
});
More information on what can be configured through options is located here.
Concerns
This is not part of the question, as the question was to identify how to listen to these events. But as a general concern, the event listener does not return a session object. It is unclear how to act once you handle the event.

Resources