AWS Lex V2 - DailogHook Validation - amazon

Does anyone know how I check what slot I am processing if I do some validation at the slot level? As I have looked at the event payload and there seems to be no reference to the slot you are calling your Lambda function on.

At present the Lex event passed to Lambda functions does not contain any hint as to which slot is presently being ellicted.
However, looking at the slots array in the event, you can determine when to validate based on the current value.
Values that have not yet been elicited are null; whereas values that have been ascertained from the user have a non-null value.
You can validate the non-nulls and assuming you handle the scenarios correctly you should be fine. By that I mean if the value fails validation you will need to issue an ElicitSlot prompt for the same slot; potentially with a useful error message. If the value passes validation you can issue a Delegate response and allow Lex to continue processing accordingly.
Below is a sample event received by my Lambda function for a V2 Lex bot:
"intent": {
"slots": {
"duration": null,
"reason": null,
"quantity": {
"shape": "Scalar",
"value": {
"originalValue": "2",
"resolvedValues": [
"2"
],
"interpretedValue": "2"
}
}
},
"confirmationState": "None",
"name": "MainIntent",
"state": "InProgress"
},
In my example, MainIntent has three slots but only one has a value. My Lambda function will validate the non-nulls and then delegate to Lex for the rest of the processing.

Related

Forge-Get Item Path along with custom attributes in BIM360 document

Two Requirements are needed:
Get item path of the document in a BIM360 document management.
Get all custom attributes for that item.
For Req. 1, an api exists to fetch and for getting custom attributes, another api exists and data can be retrived.
Is there a way to get both the requirements in a single api call instead of using two.
In case of large number of records, api to retrieve item path is taking more than an hour for fetching 19000+ records and token gets expired though refesh token is used, while custom attribute api processes data in batches of 50, which completes it in 5 minutes only.
Please suggest.
Batch-Get Custom Attributes is for the additional attributes of Document Management specific. While path in project is a general information with Data Management.
The Data Management API provides some endpoints in a format of command, which can ask the backend to process the data for bunch of items.
https://forge.autodesk.com/en/docs/data/v2/reference/http/ListItems/
This command will retrieve metadata for up to 50 specified items one time. It also supports the flag includePathInProject, but the usage is tricky and API document does not indicate it. In the response, it will tell the pathInProject of these items. It may save more time than iteration.
{
"jsonapi": {
"version": "1.0"
},
"data": {
"type": "commands",
"attributes": {
"extension": {
"type": "commands:autodesk.core:ListItems",
"version": "1.0.0" ,
"data":{
"includePathInProject":true
}
}
},
"relationships": {
"resources": {
"data": [
{
"type": "items",
"id": "urn:adsk.wipprod:dm.lineage:vkLfPabPTealtEYoXU6m7w"
},
{
"type": "items",
"id": "urn:adsk.wipprod:dm.lineage:bcg7gqZ6RfG4BoipBe3VEQ"
}
]
}
}
}
}
Get item path of the document in a BIM360 document management.
Is this question about getting the hiarchy of the item? e.g. rootfolder>>subfolder>>item ? With the endpoint, by specifying the query param includePathInProject=true, it will return the relative path of the item (pathInProject) in the folder structure.
https://forge.autodesk.com/en/docs/data/v2/reference/http/projects-project_id-items-item_id-GET/
"data": {
"type": "items",
"id": "urn:adsk.wipprod:dm.lineage:xxx",
"attributes": {
"displayName": "my-issue-att.png",
"createTime": "2021-03-12T04:51:01.0000000Z",
"createUserId": "xxx",
"createUserName": "Xiaodong Liang",
"lastModifiedTime": "2021-03-12T04:51:02.0000000Z",
"lastModifiedUserId": "200902260532621",
"lastModifiedUserName": "Xiaodong Liang",
"hidden": false,
"reserved": false,
"extension": {
"type": "items:autodesk.bim360:File",
"version": "1.0",
"schema": {
"href": "https://developer.api.autodesk.com/schema/v1/versions/items:autodesk.bim360:File-1.0"
},
"data": {
"sourceFileName": "my-issue-att.png"
}
},
"pathInProject": "/Project Files"
}
or if you may iterate by the data of parent
"parent": {
"data": {
"type": "folders",
"id": "urn:adsk.wipprod:fs.folder:co.sdfedf8wef"
},
"links": {
"related": {
"href": "https://developer.api.autodesk.com/data/v1/projects/b.project.id.xyz/items/urn:adsk.wipprod:dm.lineage:hC6k4hndRWaeIVhIjvHu8w/parent"
}
}
},
Get all custom attributes for that item. For Req. 1, an api exists to fetch and for getting custom attributes, another api exists and data can be retrived. Is there a way to get both the requirements in a single api call instead of using two. In case of large number of records, api to retrieve item path is taking more than an hour for fetching 19000+ records and token gets expired though refesh token is used, while custom attribute api processes data in batches of 50, which completes it in 5 minutes only. Please suggest.*
Let me try to understand the question better. Firstly, two things: Custom Attributes Definitions, and Custom Attributes Values(with the documents). Could you clarify what are they with 19000+ records?
If Custom Attributes Definitions, the API to fetch them is
https://forge.autodesk.com/en/docs/bim360/v1/reference/http/document-management-custom-attribute-definitions-GET/
It supports to set limit of each call. i.e. the max limit of one call is 200, which means you can fetch 19000+ records by 95 times, while each time calling should be quick (with my experience < 10 seconds). Totally around 15 minutes, instead of more than 1 hour..
Or at your side, each call with 200 records will take much time?
If Custom Attributes Values, the API to fetch them is
https://forge.autodesk.com/en/docs/bim360/v1/reference/http/document-management-versionsbatch-get-POST/
as you know, 50 records each time. And it seems it is pretty quick at your side with 5 minutes only if fetch the values of 19000+ records?

Dialogflow Fulfillment URLnot sending any data

I am building a bot for google assistant. I have enabled fulfillment section for some intents. Dialog flow sends the request to the fulfillment url. The url is executed and a hard coded response is returned. I can see the response in the assistant simulator. Everything works fine except one thing. The request is empty.I can't access fields that are supposed to be present in the request.
I have accessed the same url using post request from a python code and it displays the parameters. So, there are no issues in the code. I think I am missing some configuration option.
I was expecting the post body in the following format:
POST body:
{
"responseId": "ea3d77e8-ae27-41a4-9e1d-174bd461b68c",
"session": "projects/your-agents-project-id/agent/sessions/88d13aa8-2999-4f71-b233-39cbf3a824a0",
"queryResult": {
"queryText": "user's original query to your agent",
"parameters": {
"param": "param value"
},
"allRequiredParamsPresent": true,
"fulfillmentText": "Text defined in Dialogflow's console for the intent that was matched",
"fulfillmentMessages": [
{
"text": {
"text": [
"Text defined in Dialogflow's console for the intent that was matched"
]
}
}
],
"outputContexts": [
{
"name": "projects/your-agents-project-id/agent/sessions/88d13aa8-2999-4f71-b233-39cbf3a824a0/contexts/generic",
"lifespanCount": 5,
"parameters": {
"param": "param value"
}
}
],
"intent": {
"name": "projects/your-agents-project-id/agent/intents/29bcd7f8-f717-4261-a8fd-2d3e451b8af8",
"displayName": "Matched Intent Name"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {},
"languageCode": "en"
},
"originalDetectIntentRequest": {}
}
But when I print the post data using print(request.POST), the actual post request shown is
One more thing: Does dialog flow append the action at the end of the fulfillment url? If so, I will have to handle the logic separately. I have done it without considering the action name. But a lot of my stuff is hacked, so I just want to be sure.
On another note, is dialogflow good enough? It has worked fine on a few examples similar to what it was trained on. How many training samples does it need to work properly? What is the underlying algorithm used in dialogflow? Or should I use the fulfillment url and handle everything on my own? I am inclined towards the later. I do not have too much faith in the existing chatbots.
Any help is appreciated.
If the Fallback Intent is the one being triggered, then you wouldn't get any parameters since this means that nothing else matched.
Got it. Used request.body. This solves the problem. Then parsed it using json.loads and accessed the parameters.

Dialogflow Not able to use Parameter in response

I am trying to use Dialogflow, and following their guide building-your-first-agent to create an intent with response
However, if I use the parameter inside the response, it will return 'not available' from default response. Does anyone know why it is happening?
From the picture, it will response the correct sentence without parameter. the response is not available when using parameter.
Diagnostic info
without parameter
{
"id": "aa316e0a-7f41-46cb-a03c-03c13d80ae6b",
"timestamp": "2018-05-16T18:31:11.858Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "turn on asdkasjd",
"action": "",
"actionIncomplete": false,
"parameters": {
"cameraName": ""
},
"contexts": [],
"metadata": {
"intentId": "41b046bc-65ea-425b-8a33-9e37c44dddf4",
"webhookUsed": "false",
"webhookForSlotFillingUsed": "false",
"intentName": "opencamera"
},
"fulfillment": {
"speech": "Sorry I don't know",
"messages": [
{
"type": 0,
"speech": "OK. I will try to turn on"
}
]
},
"score": 0.9300000071525574
},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "e488d71a-a21e-4cf0-bfcb-13b4a36fd811"
}
The problem is that you're using the #sys:given-name parameter in an attempt to match "camera" or "camera two", but neither of these are a "given name", which is meant to match the name given to a person (as opposed to their family name), not the name given to a device.
In these cases, it is using some rough matching and determining that "turn on" matches enough of the sample phrase to match the Intent, but that there is no value that matches the name part of it. Since that parameter isn't required, the Intent matches without a value for the parameter.
There are a few things you can do to remedy this, depending on your exact needs:
You may wish to mark the parameter as required. (This doesn't solve the name issue, but will make sure it is either matched or the user is prompted for the value.)
You can use the #sys:any entity type. This should match anything the user includes for the parameter.
If you have some defined names, you can define your own entity type.
First, I think you have not added any phrases in 'Training Phrases' section above 'Action and Parameters' section. Please add those to train your agent to detect 'cameraName' parameter from phrases. Secondly, if you see your json, result->parameters->cameraName is empty. And if the parameter is empty, it cannot respond with a response that requires the parameter 'cameraName'. Try adding a third response under responses with parameters that does not uses parameter and see the result, it will return the third response and when it will detect the parameter, it will start showing response with the parameter.

Parse a CloudWatch alert in AWS Lambda Python function

I'm working on Lambda function that will perform several actions based on CloudWatch alerts.
The JSON format of the alerts is:
{
'SignatureVersion': '1',
'Timestamp': '2018-03-08T16: 06: 27.163Z',
'MessageId': 'df82d564-1651-5dc6-a37a-867f779226ec',
'Message': '{
"AlarmName": "awsec2-i-08c38bb8af7962797-CPU-Utilization",
"AlarmDescription": "Created from EC2 Console",
"AWSAccountId": "111111111111",
"NewStateValue": "ALARM",
"NewStateReason": "Threshold Crossed: 1 datapoint [1.49999999999939 (08/03/18 16:04:00)] was greater than or equal to the threshold (1.0).",
"StateChangeTime": "2018-03-08T16:06:27.124+0000",
"Region": "EU (Ireland)",
"OldStateValue": "OK",
"Trigger": {
"MetricName": "CPUUtilization",
"Namespace": "AWS/EC2",
"StatisticType": "Statistic",
"Statistic": "AVERAGE",
"Unit": null,
"Dimensions": [
{
"name": "InstanceId",
"value": "i-08c38bb8af7962797"
}
],
"Period": 60,
"EvaluationPeriods": 1,
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
"Threshold": 1.0,
"TreatMissingData": "",
"EvaluateLowSampleCountPercentile": ""
}
}',
'Type': 'Notification',
'TopicArn': 'arn:aws:sns:eu-west-1: 11111111111:test',
'Subject': 'ALARM: "awsec2-i-08c38bb8af7962797-CPU-Utilization" in EU (Ireland)'
}
What I need to understand is how I tell my function to extract only the InstanceId value and use it as variable for the rest of the function.
The Message is JSON provided as a string. To access the contents of the string, you'll need to use the json.loads() function:
import json
alert = ... (from CloudWatch)
message = json.loads(alert['Message'])
[msg['value'] for msg in message['Trigger']['Dimensions'] if msg['name']=='InstanceId']
However, please note that this will merely output the InstanceId that was provided as the Dimension for the alarm. It is not specifically saying that this instance caused the alarm (but that is true).
For example, you could create an alarm based on a group of EC2 instances. If the average CPU went above a threshold, the alarm would be triggered. However, the dimension would relate to the group, not a specific instance.
Think of it as saying "The Alarm with a filter of Instance i-xxx has been triggered", as opposed to saying "Instance i-xxx triggered the alarm".
As long as your alarm is always based on a single instance, then the Dimension will be what you expect.

Identifying numbers correctly

I have an intent where I might say 'Transfer 4 to Bob' and it identifies this as 'Transfer for to Bob'
Also I might say 'Transfer 10 to Bob and it identifies this as 'Transfer 102 Bob' treating to word to as 2 on the end of the previous number.
What is the best way to get API.AI to recognise these parts correctly so 4 is not for and to is not 2?
You mentioned that you're using the Actions on Google platform. This means that speech recognition - the process of translating what the user says into text - is happening before the data gets to API.AI.
The problem you're experiencing is that Actions on Google is misrecognizing some numbers as words, e.g. four becomes for.
Because this happens before - and separately from - API.AI, you won't be able to fix the misrecognition.
Below, I'll explain how you can work around this issue in API.AI. However, it's also worth thinking about how you could make your conversation design as robust as possible so that issues like this are less likely to cause problems.
One way you could increase robustness would be to mark the number as a required parameter in API.AI so the user is prompted if it isn't detected due to a recognition error. In that case, the dialog would go like this:
User: Give me four lattes.
App: Sure, four lattes coming up.
User: Give me for lattes.
App: How many do you want?
User: Four.
App: Sure, four lattes coming up.
Regardless, here's a workaround you can use to help recover from misrecognition:
In your intent, provide examples of these commonly misrecognized values. Highlight and mark them as numbers.
Test out your intent out in the console and you'll see that "for" is now matched as a "number" entity with value "for".
In your fulfillment webhook, check the parameter for this value and convert it to the appropriate number using a dictionary. Here's the JSON for the above query:
{
"id": "994c4e39-be49-4eae-94b0-077700ef87a3",
"timestamp": "2017-08-03T19:50:26.314Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "Get me for lattes",
"action": "",
"actionIncomplete": false,
"parameters": {
"drink": "lattes",
"number": "for" // NOTE: Convert this to "4" in your webhook
},
"contexts": [],
"metadata": {
"intentId": "0e1b0e72-78ba-4c61-a4fd-a73788034de1",
"webhookUsed": "false",
"webhookForSlotFillingUsed": "false",
"intentName": "get drink"
},
"fulfillment": {
"speech": "",
"messages": [
{
"type": 0,
"speech": ""
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "8b0891c1-50c8-43c6-99c4-8f77261acf86"
}

Resources