How to recognize name of sub-list within list entity? - botframework

I have a chatbot powered by Microsoft Bot Framework which is using LUIS service for natural language recognition. One of the supported use cases is to allow users to list their tickets. Since there can multiple different types of tickets, one of the feature requests is to support filtering of these tickets by their type, for example - orders, incidents, etc.
Within LUIS, I have created list entity called ticketType with sub-lists representing individual ticket types and their synonyms:
Next up, I have created intent called listTickets, where I provided following sample utterances:
Finally, I have also created patterns for the listTickets intent to strengthen the recognition:
Now, after training and testing out my model, everything works just fine. Well, almost... The ticketType entity is correctly recognized, but I have no way to distinguish between individual ticket types based on my sub-lists as seen in the test results here:
Question
How do I correctly train my LUIS model and properly create ticketType entity, so that LUIS correctly recognizes also the sub-list? Something like ticketType::order and ticketType::incident?
I have also read about entity roles, however this does not seem to be suitable for my scenario, because:
According to example it is more suitable in situations, when same entity is used multiple times in utterance and roles are used to differentiate between individual entities based on their positions.
In theory I could use roles, but then I would have to train my listTickets intent with every possible sub-list combination to have everything correctly labeled. Would patterns still make sense in this scenario?

I would suggest you test this in Web Chat or whichever channel you will be using. I created a LUIS model based off of yours and, when run thru Web Chat, the information you are seeking is readily available.
In my test, I passed "Display my request" as an utterance to the bot in a previous step. As you can see, "request" is a synonym of "order" which is found in "ticketType" (following your design). I'm able to extract the specific entity from the recognizerResult as well as the normalized values (i.e "sublists").
Hope of help!
const recognizerResult = await this.recognizer.recognize(stepContext.context);
let intent = await LuisRecognizer.topIntent( recognizerResult );
console.log('1', intent )
console.log('2', recognizerResult.entities );
console.log('3', recognizerResult.entities.ticketType );
console.log('4', recognizerResult.luisResult.entities );
1 listTicket
2 { '$instance': { ticketType: [ [Object] ] },
ticketType: [ [ 'order' ] ] }
3 [ [ 'order' ] ]
4 [ { entity: 'request',
type: 'ticketType',
startIndex: 11,
endIndex: 17,
resolution: { values: [Array] } } ]

Related

Is there a way to GET lists of course work for ALL courses in one request (Method: courses.courseWork.list Google Classroom API)

Is there a way to GET lists of course work for ALL courses in one request (Method: courses.courseWork.list Google Classroom API).
Right now, it works only by one single courseId per request
Thank you
function execute() {
return gapi.client.classroom.courses.courseWork.list({
"courseId": "7777777777777",
"courseWorkStates": [
"PUBLISHED"
]
})
It is not possible, it needs the 'courseId' parameter to return the data. A workaround would be listing all the courses with 'Method: courses.list' [1], get the Id's for all courses and create a cycle so it gets the course work for all courses.
[1] https://developers.google.com/classroom/reference/rest/v1/courses/list

Perform graphQL query with result from another graphQL query [duplicate]

Hullo everyone,
This has been discussed a bit before, but it's one of those things where there is so much scattered discussion resulting in various proposed "hacks" that I'm having a hard time determining what I should do.
I would like to use the result of a query as an argument for another nested query.
query {
allStudents {
nodes {
courseAssessmentInfoByCourse(courseId: "2b0df865-d7c6-4c96-9f10-992cd409dedb") {
weightedMarkAverage
// getting result for specific course is easy enough
}
coursesByStudentCourseStudentIdAndCourseId {
nodes {
name
// would like to be able to do something like this
// to get a list of all the courses and their respective
// assessment infos
assessmentInfoByStudentId (studentId: student_node.studentId) {
weightedMarkAverage
}
}
}
}
}
}
Is there a way of doing this that is considered to be best practice?
Is there a standard way to do it built into GraphQL now?
Thanks for any help!
The only means to substitute values in a GraphQL document is through variables, and these must be declared in your operation definition and then included alongside your document as part of your request. There is no inherent way to reference previously resolved values within the same document.
If you get to a point where you think you need this functionality, it's generally a symptom of poor schema design in the first place. What follows are some suggestions for improving your schema, assuming you have control over that.
For example, minimally, you could eliminate the studentId argument on assessmentInfoByStudentId altogether. coursesByStudentCourseStudentIdAndCourseId is a field on the student node, so its resolver can already access the student's id. It can pass this information down to each course node, which can then be used by assessmentInfoByStudentId.
That said, you're probably better off totally rethinking how you've got your connections set up. I don't know what your underlying storage layer looks like, or the shape your client needs the data to be in, so it's hard to make any specific recommendations. However, for the sake of example, let's assume we have three types -- Course, Student and AssessmentInfo. A Course has many Students, a Student has many Courses, and an AssessmentInfo has a single Student and a single Course.
We might expose all three entities as root level queries:
query {
allStudents {
# fields
}
allCourses {
# fields
}
allAssessmentInfos {
# fields
}
}
Each node could have a connection to the other two types:
query {
allStudents {
courses {
edges {
node {
id
}
}
}
assessmentInfos {
edges {
node {
id
}
}
}
}
}
If we want to fetch all students, and for each student know what courses s/he is taking and his/her weighted mark average for that course, we can then write a query like:
query {
allStudents {
assessmentInfos {
edges {
node {
id
course {
id
name
}
}
}
}
}
}
Again, this exact schema might not work for your specific use case but it should give you an idea around how you can approach your problem from a different angle. A couple more tips when designing a schema:
Add filter arguments on connection fields, instead of creating separate fields for each scenario you need to cover. A single courses field on a Student type can have a variety of arguments like semester, campus or isPassing -- this is cleaner and more flexible than creating different fields like coursesBySemester, coursesByCampus, etc.
If you're dealing with aggregate values like average, min, max, etc. it might make sense to expose those values as fields on each connection type, in the same way a count field is sometimes available alongside the nodes field. There's a (proposal)[https://github.com/prisma/prisma/issues/1312] for Prisma that illustrates one fairly neat way to do handle these aggregate values. Doing something like this would mean if you already have, for example, an Assessment type, a connection field might be sufficient to expose aggregate data about that type (like grade averages) without needing to expose a separate AssessmentInfo type.
Filtering is relatively straightforward, grouping is a bit tougher. If you do find that you need the nodes of a connection grouped by a particular field, again this may be best done by exposing an additional field on the connection itself, (like Gatsby does it)[https://www.gatsbyjs.org/docs/graphql-reference/#group].

Group queries in GraphQL (not "group by")

in my app there are many entities which get exposed by GraphQL. All that entities get Resolvers and those have many methods (I think they are called "fields" in GraphQl). Since there is only one Query type allowed, I get an "endless" list of fields which belong to many different contexts, i.E.:
query {
newsRss (...)
newsCurrent (...)
userById(...)
weatherCurrent (...)
weatherForecast(...)
# ... many more
}
As you can see, there are still 3 different contexts here: news, users and weather. Now I can go on and prefix all fields ([contextName]FieldName), as I did in the example, but the list gets longer and longer.
Is there a way to "group" some of them together, if they relate to the same context? Like so, in case of the weather context:
query {
weather {
current(...)
forecast(...)
}
}
Thanks in advance!
If you want to group them together , you need to have a type which contain all fields under the same context . Take weather as an example , you need to have a type which contain currentWeather and forecastWeather field. Does this concept make sense to your application such that you can name it easily and users will not feel strange about it ? If yes , you can change the schema to achieve your purpose.
On the other hand, if all fields of the same context actually return the same type but they just filtering different things, you can consider to define arguments in the root query field to specify the condition that you want to filter , something like :
query {
weather(type:CURRENT){}
}
and
query {
weather(type:FORECAST){}
}
to query the current weather and forecast weather respectively.
So it is a question about how you design the schema.

How to get normalized value for List type Entity from Microsoft.Bot.Builder.RecognizerResult?

We're trying to leverage LUIS to get normalized value for a given synonyms from the user input.
In BF V3, we have the EntityRecommendation, and it has the Resolution property we can use for this purpose, like below.
But how do we archive the same goal in V4? the Microsoft.Bot.Builder.RecognizerResult does not contain the Resolution property while when we directly query LUIS Rest API, the response has it.
EntityRecommendation serviceNameEntityRecommendation;
if (luisResult.TryFindEntity("ServiceNames", out serviceNameEntityRecommendation))
{
if (serviceNameEntityRecommendation != null)
{
var resolutions = serviceNameEntityRecommendation.GetResolutions();
You'll need to know what entity type is being returned. For example, I created a LUIS App with nothing by the "number" pre-built entity.
I then used the NLP with LUIS Sample
If I type "one thousand", I can retrieve the normalized, "1000" in recognizerResult.Entities["number"][0].
Here's everything that RecognizerResult returns:

Designing a Firebase based scalable feed model

Question :
How to design a social network "feed" with Firebase as backend, that scales ?
Possible answers :
"MVP" solution is to design a feeds root child, one for each user, and append any new post from the followed user in every follower's feeds.
users
user1
name: bob
user2
name: alice
follows:
user1: true
posts
post1
author: user1
text: 'Hi there'
feeds
user2
post1: true
This works well, and is demoed in the Firefeed project. But it does not scale well : if Katy Perry wants to post something, her mobile phone will have to write to millions of feed.
Hence the solution reported in this SO question to delegate this operation to a server based process.
My problem is, Firebase is a "no-backend" solution, and this is the main reason why I use it, so I'd like to make sure there is absolutely no chance of implementing this feature without a server.
What if the feeds child is removed in the above schema ?
Then do this :
baseRef.child('posts')
.orderBy('author')
.whereIn(baseRef.child('users/user2/follows').keys())
Unfortunately, whereIn does not exists in Firebase API, nor subqueries :(
Any other model structure possible without the need of a server ?
Thanks
Firebase guys kinda replied on their blog : https://www.firebase.com/blog/2015-10-07-how-to-keep-your-data-consistent.html
The post is about "Data fanning" (spreading items across many nodes in one atomic write operation).
The technique greatly addresses the feed model of the original question
The post actually contains example code for implementing it :
Function for creating the fannout object (actually a simple object with keys being API endpoints to be written)
function fanoutPost({ uid, followersSnaphot, post }) {
// Turn the hash of followers to an array of each id as the string
var followers = Object.keys(followersSnaphot.val());
var fanoutObj = {};
// write to each follower's timeline
followers.forEach((key) => fanoutObj['/timeline/' + key] = post);
return fanoutObj;
}
And the logic using this function :
var followersRef = new Firebase('https://<YOUR-FIREBASE-APP>.firebaseio.com/followers');
var followers = {};
followersRef.on('value', (snap) => followers = snap.val());
var btnAddPost = document.getElementById('btnAddPost');
var txtPostTitle = document.getElementById('txtPostTitle');
btnAddPost.addEventListener(() => {
// make post
var post = { title: txtPostTitle.value };
// make fanout-object
var fanoutObj = fanoutPost({
uid: followersRef.getAuth().uid,
followers: followers,
post: post
});
// Send the object to the Firebase db for fan-out
rootRef.update(fanoutObj);
});
Note: this is way more scalable than a loop writing each time in one follower feed. However, it could nevertheless be insufficient for millions of followers. In that case, it would be safer to trust a server operation making several writes. I think client-side can be used for up to a few hundreds followers, which is the average number of followers on social media. (This needs to be verified by testing though)

Resources