Watson Conversation: condition matching input to context array - watson-conversation

Taking the car dashboard example, I altered the initial #genre node to be #genre:classical. I also added a list to the contex
"choices":["Beethoven","Mahler 9","Brahms 3rd"]
and the Watson response is "I have 3 selections". The condition on the next node is $choices.contains(input.text). The "Found a match" response is just for testing. It looks like this:
When I test this in the api tool and type "Beethoven" both "Found a match" and "Great choice!..." appear. Same for the other two choices, but only if I type the exact choice, e.g., "Mahler 9". Typing "Mahler" or "mahler" doesn't get a match. I read through the SpEL documentation but couldn't see a way in a one-line condition to parse through the list looking for partial matches.
So my question is, is there an condition expression that would match partial user input, e.g., "Mahler"? I'll be using the Java SDK to code the app server, so alternatively I wondered if I could add a temporary #entity just for this sequence instead of using the context list then delete it when the conversation is done? Or is there a way to construct a more complex condition in the MessageRequest and will Watson recognize it? Or is this just not the right way to go about this? Any pointers, examples or docs much appreciated.

So my question is, is there an condition expression that would match partial user input
You can't add temporary entities or intents. As adding them forces Watson to start training itself (even if you could it through code).
You can however create quite complex regular expressions, pass them in as a context variable.
For example your advanced node can have:
{
"output": {
"text": "Please ask me a question."
},
"context": {
"rx": "fish|[0-9]+"
}
}
Then in you condition you would write.
input.text.matches(context.rx)
This will then trigger if the person mentions a number, or the word fish. So you can create your partial user input checking that way.

Related

How to concatenate constant string with jsonpath

I have AWS step machine and one of the step is used to notify failure using SNS service. I want to select some metadata from input json into outgoing message. So i am trying to concatenate constant string with jsonpath like below
"Notify Failure": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"Message.$": "A job submitted through Step Functions failed for document id $.document_id",
"Subject":"Job failed",
"TopicArn": "arn:aws:sns:us-west-2:xxxxxxx:xxxxxxxx"
},
"End": true
}
where document_id is one of the property in input json
However when i try save state machine defination i get error
There is a problem with your ASL definition, please review it and try
again The value for the field 'Message.$' must be a valid JSONPath
I was able to solve a similar issue using:
"Message.$": "States.Format('A job submitted through Step Functions failed for document id {}', $.document_id)",
Described in a AWS News Blog post.
The JSONPath implementation referenced from the AWS Step Functions documentation supports String concatenation via $.concat($..prop) but sadly this does not work when deployed to AWS, suggesting that AWS uses a different implementation.
Therefore there is no way to do string concatenation with JSONPath in AWS.
As the message suggest you need to provide a valid JSONPath.
"Message.$": "$.document_id"
You cannot use any string interpolation as it invalidates the JSONPath format. You will need to construct the message in the preceding state.
I know that this thread is quite old, but I think it might be useful for some people.
It IS actually possible to concatenate strings or JSONPaths in AWS Step Functions thanks to the function States.Format.
The principle is the same as the string format method in Python.
Example with strings
"States.Format('{}<separator_1>{}<separator_2>{}', 'foo', 'bar', 'baz')"
will give you
'foo<separator_1>bar<separator_2>baz'
Example with JSONPaths
"States.Format('{}<separator>{}', $.param_1, $.param_2)"
will give you
'<value of param_1><separator><value of param_2>'
NB: You can also combine strings with JSONPaths.
Hope it helps!

Storing timestamp in joining node value instead of Boolean in Firebase database

Say that I have node user, item and user_items used to join them.
Typically one would(as advised in official documents and videos) use such a structure:
"user_items": {
"$userKey": {
"$itemKey1": true,
"$itemKey2": true,
"$itemKey3": true
}
}
I would like to use the following structure instead:
"user_items": {
"$userKey": {
"$itemKey1": 1494912826601,
"$itemKey2": 1494912826602,
"$itemKey3": 1494912826603
}
}
with values being a timestamp value. So that i can order them by creation date also while being able to tell the associated time. Seems like killing two birds with one stone situation. Or is it?
Any down sides to this approach?
EDIT: Also I'm using this approach for the boolean fields such as: approved_at, seen_at,... etc instead of using two fields like:
"some_message": {
"is_seen": true,
"seen_timestamp": 1494912826602,
}
You can model your database in every way you want, as long as you follow Firebase rules. The most important rule is to have the data as flatten as possible. According to this rule your database is structured correctly. There is no 100% solution to have a perfect database but according to your needs and using one of the following situations, you can consider that is a good practice to do it.
1. "$itemKey1": true,
2. "$itemName1": true,
3. "$itemKey1": 1494912826601,
4. "$itemName1": 1494912826601,
What is the meaning of "$itemKey1": 1494912826601,? Beacause you already have set a timestamp, means that your item was uploaded into your database and is linked to the specific user, which means also in other words true. So is not a bad approach to do something like this.
Hope it helps.
Great minds must think alike, because I do the exact same thing :) In my case, the "items" are posts that the user has upvoted. I use the timestamps with orderBy(), along with limitToLast(50) to get the "last 50 posts that the user has upvoted". And from there they can load more. I see no downsides to doing this.

Why use DELETE/POST instead of PUT for 'unfollowing/following' a user?

Referencing this API tutorial/explanation:
https://thinkster.io/tutorials/design-a-robust-json-api/getting-and-setting-user-data
The tutorial explains that to 'follow a user', you would use:
POST /api/profiles/:username/follow.
In order to 'unfollow a user', you would use:
DELETE /api/profiles/:username/follow.
The user Profile initially possesses the field "following": false.
I don't understand why the "following" field is being created/deleted (POST/DELETE) instead of updated from true to false. I feel as though I'm not grasping what's actually going on - are we not simply toggling the value of "following" between true and false?
Thanks!
I think that the database layer have to be implemented in a slightly more complex way than just having a boolean column for "following".
Given that you have three users, what would it mean that one of the users has "following": true? Is that user following something? That alone cannot mean that the user is following all other users, right?
The database layer probably consists of (at least) two different concepts: users and followings; users contain information about the user, and followings specify what users follow one another.
Say that we have two users:
[
{"username": "jake"},
{"username": "jane"}
]
And we want to say that Jane is following Jake, but not the other way around.
Then we need something to represent that concept. Let's call that a following:
{"follower": "jane", "followee": "jake"}
When the API talks about creating or deleting followings, this is probably what they imagine is getting created. That is why they use POST/DELETE instead of just PUT. They don't modify the user object, they create other objects that represent followings.
The reason they have a "following": true/false part in their JSON API response is because when you ask for information about a specific user, as one of the other users, you want to know if you as a user follows that specific user.
So, given the example above, when jane would ask for information about jake, at GET /api/profiles/jake, she would receive something like this:
{
"profile": {
"username": "jake",
"bio": "...",
"image": "...",
"following": true
}
}
However, when jake would ask for the profile information about jane, he would instead get this response:
{
"profile": {
"username": "jane",
"bio": "...",
"image": "...",
"following": false
}
}
So, the info they list as the API response is not what is actually stored in the database about this specific user, it also contains some information that is calculated based on who asked the question.
Using a microPUT would certainly be a reasonable alternative. I don't think anybody is going to be able to tell you why a random API tutorial made certain design decisions. It may be that they just needed a contrived example to use POST/DELETE.
Unless the author sees this question, I expect it's unanswerable. It's conceivable that they want to store meta information, such as the timestamp of the follow state change, but that would be unaffected by POST/DELETE vs. PUT.

failed to keep user on the same prompt when they enter the wrong nunber?

we'd like to keep user on the same prompt when they enter the wrong number, we have tried anything_else, and "true", "jump to", but it messed up, please take a look at the attached to reproduce it, Thanks
pleae enter "how much"
if you enter 6, it will lock the prompt(I assign 1 to 5 to different identification), this behavior is correct .
then enter 2, we will get messed up...
please import this json to reproduce it, thanks
https://drive.google.com/file/d/0B1YdUMoS4l7ub1BZdUg1c1dQeG8/view?usp=sharing
The better form is use the entitie pre-defined by IBM, #sys-number to get numbers from the user input. And you can use use with conditions and to get the number with context variable too, check the JSON example:
{
"context": {
"number": "<? #sys-number ?>"
},
"output": {
"text": {
"values": [
"Now is $hora. Sector please?"
],
"selection_policy": "sequential"
}
}
}
If user type two or 2, the entitie recognize!
You can use regex expression to obtain only the numbers you have pre-defined too!
How to active: -> Entities -> System Entities -> sys-number = ON:
Obs.: Waiting Watson TRAINNING after you active this entitie.
Example, with sys-number add in your node condition:
#sys-number:1
Check the image:
If user type the number correct:
Check the dialog if user dont type the correct number with true condition:
I did the example for you understand what I do for that:
Download the JSON for verify how to do it with REGEX here.
Download the JSON for verify how to do it with SYS-NUMBER here.
EDIT:
Refer your questions
In this case you can use regex, and use the context variable for make conditions in other node. My workspace with regex can help you with numbers. And, the variable $number you can use in the next node to verify if the user typed correctly the number.
And, the other case is to use the Jump to inside conversation. And use true if the user dont type the number correctly again.
Check my image:
Download the new workspace here.
Study more about conditions here.

APIGEE querying data that DOESN'T match condition

I need to fetch from BaaS data store all records that doesn't match condition
I use query string like:
https://api.usergrid.com/<org>/<app>/<collection>?ql=location within 10 of 30.494697,50.463509 and Partnership eq 'Reject'
that works right (i don't url encode string after ql).
But any attempt to put "not" in this query cause "The query cannot be parsed".
Also i try to use <>, !=, NE, and some variation of "not"
How to configure query to fetch all records in the range but Partnership NOT Equal 'Reject' ?
Not operations are supported, but are not performant because it requires a full scan. When coupled with a geolocation call, it could be quite slow. We are working on improving this in the Usergrid core.
Having said that, in general, it is much better to inverse the call if possible. For example, instead of adding the property when the case is true, always write the property to every new entity (even when false), then edit the property when the case is true.
Instead of doing this:
POST
{
'name':'fred'
}
PUT
{
'name':'fred'
'had_cactus_cooler':true
}
Do this:
POST
{
'name':'fred'
'had_cactus_cooler':'no'
}
PUT
{
'name':'fred'
'had_cactus_cooler':'yes'
}
In general, try to put your data in the way you want to get it out. Since you know upfront that you want to query on whether this property exists, simply add it, but with a negative value. The update it when the condition becomes true.
You should be able to use this syntax:
https://api.usergrid.com/<org>/<app>/<collection>?ql=location within 10 of 30.494697,50.463509 and not Partnership eq 'Reject'
Notice that the not operator comes before the expression (as indicated in the docs).

Resources