How to get IBM Watson's intents / dialog nodes to work in tandem with actions - dialog

At a high level, I am trying to build a Watson Assistant that:
(1) Follows a fixed conversation structure (currently containing 25 steps)
(2) At each step, evaluates whether the user is saying anything that might be considered as a safety issue / 'red flag' and, if so, present emergency info and end the conversation, otherwise continue with the next conversation step in the fixed sequence referred to above
I have implemented the fixed conversation structure (item 1 above) using Watson's actions steps. Works well.
I have also defined an intent I call 'RedFlag' and provided 5 examples so far (will be adding more) of what users may say to trigger this. I also have a dialogue node which detects this intent and presents emergency info. Works well.
Issues I am struggling with:
a) I am not sure how to end the conversation once the RedFlag intent is detected and the assistant presents the emergency info
b) I am not able to get the conversation actions sequence to work in parallel with intent detection and activation of the related dialogue node, basically my conversation structure works only if there are no defined intents / dialogue nodes. As soon as I have an intent (in this case the RedFlag one) the assistant ignores the conversation actions / steps and simply waits for the user to say something that matches the defined intent. Its like an either / or situation - either I step through the conversation without any intents or I'm stuck within the intent detection and none of the fixed conversation sequence / steps get activated.
Essentially, I am trying to have a fixed conversation structure while also having a number of 'waiting' intents / dialogue nodes that can be activated at any point during the fixed conversation steps, depending on what the user says.
This is a crucial point for us - I need to keep the fixed conversation flow going and only interrupt it if a specific intent is detected, then either exit (in the case of the RedFlag intent) or activate the appropriate response from the related dialogue / action node and then return to the next question in the fixed sequence.

You should consider adding the Red Flag intent as a Topic change, or in classical Assistant terms a not returnable digression.
See:
https://cloud.ibm.com/docs/watson-assistant?topic=watson-assistant-change-topic

The easiest way to do this is to have your orchestration layer (Dialog) or your pre-webhook (Actions Watson Plus) do the work.
After that two options.
Have the red flags checked directly in the code.
Create an entity of red flags and then check if the entity was triggered in your code.

Related

Can we create a conversation loop in Google Dialogflow

Consider a small task where we ask the user to add fruits to the basket one by one in a loop
I have created a small agent for this task with the following intents
Intent: basket
Intent: basket-yes (follow up)
Intent: basket-no (follow up)
In the intent basket user have to provide a fruit name and quantity. Then
If the user says "no" then basket-no (follow up) intent is triggered and the cart is finished
If the user says "yes" then basket-yes (follow up) intent is triggered which should trigger basket intent to allow the user to add more fruits
I have set the input/output context for intents as per the above requirement but the conversation is not moving towards basket intent. I don't know if it's the correct way to do it or even if it's possible to do it with Dialogflow.
First, remember that the Input and Output Contexts don't indicate which Intents will be triggered, they indicate which Intents can be triggered. Intents are only triggered based on what the user says or does. So you never "trigger" an Intent by changing the Context - you can just evaluate which Intents may be valid at any time.
Intents can only be triggered if all of their Input Contexts are currently valid and the user says something that matches a training phrase. So your "basket" Intent will only be triggered if the basket-repeat Context is currently valid and the user says one of the phrases (which you did not show in your screen shots).
Intents are not like state machines, although the Contexts sometimes help you model them that way.
You can do "loops", of a sort, although the user is ultimately in control of how you advance through those loops. While you can't loop through Intents, you can loop through Contexts or state, which influence which Intents may be acceptable at a given moment. And your prompts should certainly reflect the looping nature of what you expect from the user.
I think what is happening is that the basket-repeat Context is never set in the first place, so the basket Intent can never be matched.

Redirecting from one intent to another in dialogflow

I am trying to transition between intents. I have welcome intent and based on user response, I want to either redirect to Search intent or to CheckInternet intent.
I have given output context as search and interconnection in Welcome intent and then given them as input context in relevant intents. But still not able to chain them together.
Unfortunately, I don't have knowledge of Dialogflow yet, as using this for hackathon first time to check its capabilities. Any help would be great
Intents in Dialogflow aren't nodes in a state machine. You don't "transition" between them. Intents reflect what the user says or does.
So, to give your example:
When they start the agent, the welcome Intent is triggered based on the welcome event.
If, at any point, they say "search", then the training phrases in the Search Intent might match, so the webhook or responses for it would be triggered.
Or, if they said "check", then the training phrases in the CheckIntent Intent might match, so the webhook or responses for it would be triggered instead.
If you need to limit under what circumstances these phrases would be accepted by an Intent, you can add a Context and make sure that Context is valid. But you usually only want to add that once you get it responding in the more general case.
You would have to add both Search and CheckInternet as "Follow-up Intents". To do so, create two new Intents and assign the contexts search and interconnection to them respectively as Input Context.
When the user says something that should lead to Search, set search as output context and for the next utterance Search Intent will be considered (if sample utterance match).
I hope that's clear enough, I'm happy to explain that in detail, too. This way I configured a nicely working Chatbot with 20+ Intents once :)

Getting the output context from the fallback intent in fulfillment

I've got a few intents. They all just use a single fallback intent and this fallback intent has the webhook enabled.
In the fallback function what I was hoping to do is switch on the output context and then determine what should happen next depending on which intent the fallback came from.
But the line
var context = request.body.queryResult.outputContexts;
When debugged to the console gets output:
[ { name: 'projects/xxxxproj-xxxx/agent/sessions/xxxxxx-xxxxxx-xxxxx-xxxxx/contexts/xxxxxxx-context' } ]
For the switch statement i just want the last bit with the xxxxx-context. Am I going to have to split that up to get the output context?
In the "Diagnostic Info" section I am a bit surprised there is no reference to the intent from which the fallback came and the only way to work it out seems to be using the outputcontext but as show above that is quite a long string.
Thanks
Yes, the context name is just the last part of that path. Most libraries will take care of that for you, but if you're working with the JSON directly, you need to do this yourself.
There is no reference to "the Intent from which the fallback came" because this isn't quite the model of what an Intent is. Intents represent what the user has said or done, not the current state of the conversation or where you are in the conversation. That current state is represented by Contexts, should you choose to set them.
In that sense, how you use the contexts can vary. They can store parameters, so are a good way to keep information between rounds of a conversation, and you can use them the way you are - to see what state the conversation is in general. But they also take on additional uses when defining Intents.
In an Intent definition, the Intent will only be triggered if all the Contexts listed in the Input Context field are set (ie - have a lifespan greater than 0). Dialogflow uses this when it makes followup Intents, for example, and it is common so you can do things such as have "help" trigger different Intents based on Context. In an Output Context, it will automatically capture all of the parameters specified in the Intent, including those filled in by the user's response, so this can be an easy way to remember what the user has said from round to round.
To answer your question in the comments - it doesn't specifically say which Intents were previously triggered, or which most recently, although if you're consistent in how you use your Output Contexts and what lifespan you give them, you can use it this way. What it does say is in what state your conversation is in, which is generally much better anyway.
Remember - Intents represent what a user has said or done. It doesn't represent anything else about the conversation. Only the state of the system represents that, and one tool we have to control that state is through Contexts.

Intent with required parameter showing the count of items

trying to make an Intent for my first Conversational Assistant with a couple of parameters. Everything is build in Dialogflow and for some of my functionality I use fulfillment.
The easiest way to describe my assistant is as a cinema tickets booking.
I need to store #number_of_tickets, #cinema, #movie. The last two (#cinema and #movie) are very easy to solve with entities, however struggle a lot with #number_of_tickets. All of this parameters should be mandatory.
My goal is to allow such kind of functionality:
Book me a ticket for Star Wars in IMax (ticket = 1 = #number_of_tickets, Star Wars = #movie, IMax = #cinema)
Book me 2 tickets for Star Wars in IMax(2 tickets = 2 = #number_of_tickets, Star Wars = #movie, IMax = #cinema)
Book me tickets for Star Wars in IMax -> How many tickets you want to book?
I tried with composite Entities but it doesn't work as I'm expecting.
How I can enable such kind of functionality in Dialogflow?
Is there a way to require #number_of_tickets to be between 1 and 5?
Above question can be achieved by following below steps:
Solution:
Step 1:
Create Entities for movie and cinema:
Cinema:
Movie:
Step 2:
Create an intent with three parameters:
(If you want alow only from 1 to 5 then you can create an entity like cinema and movies with entries from 1 to 5 and map the number of tickets parameter with the same)
Step 3:
Make all the parameter Mandatory and define prompts for all as below:
Movie Prompts:
Cinema Prompts:
Number of tickets prompts:
Result:
It may not be obvious, but the answer to both of your questions can be addressed by remembering that Intents capture what the user says, and not what you do with what they say. You can have multiple Intents to capture different phrases, and handle them in mostly the same way in your fulfillment. (And these do require that you have some kind of fulfillment webhook behind the scenes.)
How can I assume a default of 1 ticket?
There are a couple of approaches.
The first is that you can setup an Intent to capture phrases that suggest a single ticket and a different Intent that explicitly requires a number. So perhaps one Intent (possibly book.single) with
I'd like to get a ticket for Star Wars in IMax
How about the IMax showing for Star Wars
Let me see the Star Wars for IMax
and so forth. While you'd also have a different Intent (possibly book.multiple) with
I'd like 2 tickets for Star Wars in IMax
2 tickets please for the IMax Star Wars
etc.
In your fulfillment, you might have some function that takes three parameters
bookTickets( num, movie, cinema );
In your Intent handler for book.single, you'd call this with
bookTickets( 1, movieParameter, cinemaParameter );
while in the Intent handler for book.multiple, this would be done with
bookTickets( countParameter, movieParameter, cinemaParameter );
In each case, the fulfillment still ends up calling the same function to do the actual work, but the handler sets the values as appropriate.
How can I limit how many tickets get ordered?
This goes to something that you didn't address - what do you want to happen if they try to order more? Do you want to direct them to a group order conversation? Reject it outright? Whatever you want - make sure you've planned out this path of a conversation before you try to implement it.
In this case, this isn't something you want to enforce in the Dialogflow Intent. Handling it in your fulfillment is easiest. There, you would apply any logic for the various parameters and return a message, prompting them about their next reply.
Logic is best handled in the fulfillment.
There are actually a couple of places this is important in your example. In the first, how would you handle more than 5 tickets requested? In your handler for book.multiple, you would check how many are requested. If between 1 and 5 inclusive, you'd call the book function above. But if not, you might want to just send back a replying saying "I'm sorry, you can only reserve 5 tickets maximum. How many tickets do you want?"
You would also need a new Intent to capture the reply. It could be as simple as just taking a number, but to make sure it only gets applied when you send back this prompt, you may want to set an Output Context indicating you're prompting for the number of tickets and then set this as an Input Context for the Intent that collects a number.
Are there other cases where you might want to apply logic before booking tickets? Plenty - and in each case you will probably want to make sure there is a new Intent that can capture what they want. For example, what if the movie they want to book isn't showing in that cinema? What if you already know that movie is sold out?
But what about Followup Intents?
Followup Intents are generally best avoided in general for exactly the same reason - Intents represent what the user says, and shouldn't try to model your code logic. There is nothing special about a Followup Intent - you can create an Intent at the top level that works the same way, but will be valid only if you prompt for certain things. How? Contexts again!
So if you prompt with possible showtimes ("Do you want the 2:00, 4:00, or 6:00 show?") you could also include a context (say "promptTime", for example) and then have an Intent that expects this as an Input Context and matches the times.
Conclusion
Intents represent what the user says
Your fulfillment code does something with what they've said
You can prompt them for more or different information in your fulfillment
Contexts can shape what replies you expect
Multiple Intent Handlers can call the same functions to do the work

Dialogflow - Google Assistant: #sys.any entity not catching sequence of digits

I have created an Intent, which outputs a context with a given parameter name, let's say $myParam. The goal of this Intent is to catch a long sequence of numbers. I know there is a #sys.number-sequence entity but, I'm using Italian language and this kind of entity is not available. There is only #sys.number, but the numbers I'm expecting from the user are out of its range.
Under these restrictions, I choosed #sys.any as entity for my parameter $myParam.
Problem
When the user enters the digits, in a real device, the Assistant might add some white spaces between them (while the user says them).
When the Assistant gets the sequence 111 222, the Intent is triggered and everything goes OK.
But, when the Assistant gets the sequence 111222 (note the missing of the white space) it doesn't work.
I was expecting that #sys.any entity catches all inputs but it doesn't look like that.
Do you know how to deal with this case?
My goal is to trigger the intent even when the Assistant catches the sequence of digits without space between, before or after the sequence.
Image:
https://ibb.co/ngBzGtx
I faced this problem in the recent days and it was really annoying. Suddenly, for some reason that I don't know, Assistant's #sys.any entity was not working any more for catching numbers.
My use case is pretty much as yours, I have a parent Intent where I ask the user to enter a code (10-15 digits), and I have created a follow-up intent to handle user's input. I'm using a language different from english, and the only entity that the system offers for catching long numbers is #sys.any.
But it stopped working! I came around to find a way to somehow force the assistant to enter in a specific intent, because not only the follow-up intent isn't triggered now, but the fallback intent either. Assistant just holds on in the parent intent and goes to crash.
After I spent some hours finding nothing useful, I tried this trick which worked for me.
When creating an intent, by default it has a Normal priority. Changing the priority of the follow-up intent, that I want to be triggered with the parameter of entity type #sys.any holding the user's input, to High solved my issue. Now it's working correctly as it used to work before.
The #sys.any entity generally shouldn't be used to cover everything in the phrase. For cases like this, you should be able to use a Fallback Intent and then process the entire input from the user.

Resources