A new feature was released in IBM Watson Conversations earlier this month called “Slots”. This feature allows the collection of data from users to be configured in a more data driven and succinct manner than was previously possible.
In a previous post, I explained an approach for recursively collecting information that relied on configuring a flow with “Jump To” conditions or “Continue From” as they were called back then.
Using slots is pretty easy once you’ve done it a couple of times and the resulting node structure is very simple even in quite complex use cases. Let’s update my example from previous posts with this new approach.
Download the starter template which contains the basic structure and import it into a Watson Conversations Instance (see here for how to import). The workspace includes a couple of intents (Open and Close Accounts) and two entities (Account and Subscription Type). The basic idea is that we are building an assistant that will help us open an account for which two pieces of information are required.
Once imported use the “Add Node” button at the top of the dialog tab and set the node condition to #Open_Account” as shown below.
Next click on the customise link at the top of the right hand edit panel just above the #Open_Account condition. In the dialog that opens select the first checkbox to enable the Slots feature, ignore the “Prompt for everything” checkbox for now.
Clicking “Apply” will result in an update in the right hand edit panel and the addition of the Slot editor. Let’s add our first Slot, type @Account_Type into the “Check for” field of the first row and something like “You can open a Bronze, Silver or Gold account. Which option would you like?” to the “If not present, ask” field. The “save as” field will be defaulted for you and the default is fine for our purposes.
Next click the “Add slot” link and enter @Subscription_Type into the “Check for” field and something like “Would you like to pay monthly or annually?” into the “If not present, ask” field.
Finally we need to add the response that will be presented to the user when both account type and subscription type have been collected. In the section “Then respond with” add something like “Super. I’ll open your <? $Account_Type ?> account with <? $Subscription_Type ?> billing.”. The placeholders for $Account_Type and $Subscription_Type will be replaced with the values from context, you can see where this context is set by clicking on the cog icon to the right of the slot, then select the hamburger menu
and select the “Open JSON editor” option.
The resulting flow should handle the possible variations of user input in a single dialog node rather than the 5 nodes we needed in my previous example. Try out the following variants:
- I’d like to open and account
- I’d like to open a bronze account
- I’d like to open an account and pay monthly
- I’d like to open a bronze account and pay monthly
Assuming our changes went well the above sentences will work and guide the user toward the endpoint regardless of what information they provide in the first utterance. The completed #Open_Account node should look like the below image, if you have any problems I have included a completed workspace that can be imported to double check against your own.
Although only a basic example I hope you can see just how powerful a feature Slots are within IBM Watson Conversations service. Extending this approach to 5, 6 or 7 pieces of information would be quick and easy to maintain, my only word or warning is that collecting a lot of information will quickly become a arduous task for users and is better handled with traditional forms.
Pingback: Pattern for gathering information in IBM Watson Conversations | Oliver Cox
Pingback: Recursive questions with IBM Watson Conversations | Oliver Cox
Nice one..I tried the same one in my work space..But it worked.It is only giving You can open bronze,silver or gold account.Which one you want me to open? as response .It is not identifying account type entity..What might be the issue?I did exactly the way you mentioned
Typo..It didnt worked
Hi, You mean a typo in mine or yours?
Oh I see what you mean, typo in your comment 🙂
Nice one Olly .Saved my day.Thanks.Its working
Glad it helped!
Olly.Small issue.I had a context variable : users of json array type with few names.Now I added a third slot such that it should check for any of the names from the json array in users input.I tried giving $users[] but it didnt worked..How can we give condition such that atleast one name should match with the name from array…can you help please.
Hi. Can you do something like?
$users.contains(input.text)
This does assume that the text entered by the user will match exactly that of an array item though.
I tried adding $users.contains(input.text) in check for in the next slot but didnt worked..It gave the following error:”error”:”Error when resolving SpEL expression [ context[‘users’].contains ]. Original expression was [ $users.contains ]. (and there is 1 more error in the log)”,”log_messages”:[{“level”:”err”,”msg”:”Error when resolving SpEL expression [ context[‘users’].contains ]. Original expression was [ $users.contains ].”},{“level”:”err”,”msg”:”Error when updating context with context of dialog node id [handler_15_1499356146906]. Dialog Node context is [{\”username\”:\”$users.contains(input.text)\”}]\norg.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field ‘contains’ cannot be found on object of type ‘com.google.gson.JsonArray’ – maybe not public?\n”}]},”context”:{“users”:[“harish”,”varma”]
Any idea?
Screen shot of what Iam trying https://i2.wp.com/harishvarma8055.files.wordpress.com/2017/07/watslot.png?ssl=1&w=450
I’m not sure you can do it with a slot. The way they work is to assign the value in the “check for” field to the “save it as” field. The array.conatins returns true or false so won’t have the value.
Looking at the documentation https://www.ibm.com/watson/developercloud/doc/conversation/dialog-methods.html#arrays there isn’t an option to get by value which what you’d need.
You may have to perform that logic in a separate node.
@harishvarma You’ve probably solved this and moved on but after some information from the Watson team I can confirm that this is possible.
The slot condition needs to be set to context.users.contains(input.text), then in the advanced JSON Editor for that slot you’d need to set the context variable you want to the input.text.
Hi Olly I tried with expression-context[‘rfx_name’].contains( input.text)
but got below error-
Error when resolving SpEL expression: [context[‘rfx_name’].contains( input.text)]. (and there is 1 more error in the log)
Can you share a sample workspace that has the error?
It isn’t something silly like the quotes? context[‘rfx_name’].contains( input.text)
Also i tried with -context.name.contains(input.text)
But getting error-
SpelEvaluationException when evaluating DialogNode Id [handler_2_1502266563828]. Condition [context.name.contains(input.text)] evaluated to FALSE. SpEL evaluation error: EL1011E: Method call: Attempted to call method contains(java.lang.String) on null context object
That sounds like the context variable you are referencing (name in your example) is not populated. I’m happy to have a look for you if you can share an example workspace showing what your doing.
Sorry, I forgot to mentioned that I am creating runtime context variable $name .
Here is the workspace for your reference- https://github.com/ganeshkedari/PublicDataShare/blob/master/KD_Pizza_entity.json
Thanks for the workspace, I’m not sure I understand what you’re trying to do though.
Do you want to pass in the users name if you have it but prompt for the name if you don’t?
No that’s just wordpress replacing them with pretty ones 🙂
Yes,I want to pass in the users name if you have it but prompt for the name if I don’t