I have the following intent passed to my handler:
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.3af5c8c3-1d1f-4169-8ce8-fde1a99a7c8d",
"timestamp": "2019-04-03T04:08:06Z",
"locale": "en-US",
"intent": {
"name": "get_speeds",
"confirmationStatus": "NONE",
"slots": {
"direction": {
"name": "direction",
"value": "inbound",
"resolutions": {
"resolutionsPerAuthority": [
{
"authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.e76bf13b-71ac-4a90-94d4-597aa597ae87.direction",
"status": {
"code": "ER_SUCCESS_MATCH"
},
"values": [
{
"value": {
"name": "inbound",
"id": "a8e6fe5b9e68f30a146cefebaa7edcc3"
}
}
]
}
]
},
"confirmationStatus": "NONE",
"source": "USER"
}
}
},
"dialogState": "COMPLETED"
}
I want to extract the actual value, not the utterance, e.g., the value name, in this case, "inbound". I've tried this and various similar iterations (the prints are for debugging):
slots = handler_input.request_envelope.request.intent.slots
resolutions = slots["direction"].resolutions
print(resolutions)
print(resolutions["resolutions_per_authority"])
direction = resolutions["resolutions_per_authority"][0]["values"][0]["value"]["name"]
session_attr = handler_input.attributes_manager.session_attributes
I've also tried the same with "resolutionsPerAuthority" which is the JSON that is passed, but apparently not what comes out to my program, as the log has:
04:08:07
{'resolutions_per_authority': [{'authority': 'amzn1.er-authority.echo-sdk.amzn1.ask.skill.e76bf13b-71ac-4a90-94d4-597aa597ae87.direction',
04:08:07
'status': {'code': 'ER_SUCCESS_MATCH'},
04:08:07
'values': [{'value': {'id': 'a8e6fe5b9e68f30a146cefebaa7edcc3',
04:08:07
'name': 'inbound'}}]}]}
04:08:07
'Resolutions' object is not subscriptable
This is the error I keep getting with all my approaches: 'Resolutions' object is not subscriptable. Can someone help me with how to extract the canonical slot values? I need to do the same thing for several other intents, but I figure if I can get this one working, it will be a model for the others.
As you already pointed out, your problem was that you treated the resolution object as it was subscriptable, accessing it via
resolutions.resolutions_per_authority[0].values[0].value
is the right way to obtain it.
It may be helpful to point out that, in case of multiple matches, Alexa will return the resolutions in the order of the most likely to match the user intent.
This code snippet iterates the slots and return a python dictionary with just the keys to know if it was validated and the id of the matched value:
from ask_sdk_model.slu.entityresolution import StatusCode
@staticmethod
def get_slot_values(filled_slots):
"""Return slot values with additional info."""
slot_values = {}
logger.info("Filled slots: {}".format(filled_slots).replace("\n", "\r"))
for key, slot_item in six.iteritems(filled_slots):
name = slot_item.name
try:
status_code = slot_item.resolutions.resolutions_per_authority[0].status.code
if status_code == StatusCode.ER_SUCCESS_MATCH:
slot_values[name] = {
"synonym": slot_item.value,
"resolved": slot_item.resolutions.resolutions_per_authority[0].values[0].value.__dict__, # to make it JSON serializable
"is_validated": True,
}
elif status_code == StatusCode.ER_SUCCESS_NO_MATCH:
slot_values[name] = {
"synonym": slot_item.value,
"resolved": slot_item.value,
"is_validated": False,
}
else:
pass
except (AttributeError, ValueError, KeyError, IndexError, TypeError) as e:
# for BUILT-IN intents, there are no resolutions, but the value is specified
if slot_item.value is not None and slot_item.value != 'NONE':
slot_values[name] = {
"synonym": slot_item.value,
"resolved": slot_item.value,
"is_validated": True,
}
else:
logger.info("SLOT {} UNRESOLVED".format(name))
slot_values[name] = {
"synonym": slot_item.value,
"resolved": slot_item.value,
"is_validated": False,
}
return slot_values
where filled_slots = handler_input.request_envelope.request.intent.slots