How can i get Alexa Slot Value in ASK-SDK lambda function? - python-2.7

I want to access the slot value '{cityName}' in my Lambda Function. I am using ASK-SDK. What is the python code or syntax to do so?

If the WeatherApiCallIntent is triggered with a CityName slot value, the request JSON will look like this:
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.xxxxx-xxx-xxx-xx-xxxxxxx",
"timestamp": "2018-09-12T13:35:25Z",
"locale": "en-US",
"intent": {
"name": "WeatherApiCallIntent",
"confirmationStatus": "NONE",
"slots": {
"CityName ": {
"name": "CityName",
"value": "Kochi",
...
In you WeatherApiCallIntent handler you can use
print("Slot: " + intent_request['intent']['slots']['CityName']['value'])

The above method is correct but it did not work for me.
Another answer to the above question is as follows:
item, is_resolved = util.get_intent_(slots=handler_input.request_envelope.request.intent.slots)
and then define function get_intent_ as follows:
import random
import six
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_request_type
def get_intent_(slots):
item = []
resolved_item = None
for _,slot in six.iteritems(slots):
if slot.value is not None:
resolved_item = slot.value
if resolved_item is not None:
return resolved_item, True
else:
return resolved_item, False
This method looks complicated but it is a good practice to define a function and call it.

Related

Django loop through json object

How to loop through a JSON object in Django template?
JSON:
"data": {
"node-A": {
"test1A": "val1A",
"test2A": "val2A",
"progress": {
"conf": "conf123A"
"loc": "loc123A"
},
"test3A": "val3A"
},
"node-B": {
"test1B": "val1B",
"test2B": "val2B",
"progress": {
"conf": "conf123B"
"loc": "loc123B"
},
"test3B": "val3B"
}
}
I am having trouble accessing the nested values "conf" and "lock" inside "progress". How can I access them in Django template if the data is passed as context i.e. return (request, 'monitor.html', {"data_context": json_data['data']})?
they way you have it set up, your data is in a dictionary called 'data_context'. To access what you need in the template it would be {{data_context.test1A}}.
to not have to use 'data_context.' try this instead,
return (request, 'monitor.html', json_data['data'].to_dict())
Dictionary lookup, attribute lookup and list-index lookups are implemented with a dot notation:
{{ my_dict.key.key_nested }}
As the JSON format behaves like a dictionary in Python, the data stored with the specified keys conf and loc should be accessible with the python notation for dictionaries. Since the provided JSON can be seen as a nested dictionary, you need to "concat" the keys respectively to get your desired data.
Your return statement returns a dictionary which I will call ret so the structure should be:
{"data_context": {
"node-A": {
"test1": "val1A",
"test2": "val2A",
"progress": {
"conf": "conf123A",
"loc": "loc123A"
},
"test3": "val3A"
},
"node-B": {
"test1B": "val1B",
"test2B": "val2B",
"progress": {
"conf": "conf123B",
"loc": "loc123B"
},
"test3": "val3B"
}
}
}
Therefor to access conf and loc:
ret["data_context"]["node-A"]["progress"]["conf"]
will get you the value stored at conf in node-A

Django rest framework - serializer for dictionary structured payload

I'm trying to create a Serializer for a payload that looks something like this -
{
"2fd08845-9b21-4972-87ed-2e7fd03448c5": {
"operation": "Create",
"operationId": "356f6501-a117-4c8d-98ce-dcb4344d481b",
"user": "superuser",
"immediate": "true"
},
"fe6d0c85-0021-431e-9955-e8e1b1ebc414": {
"operation": "Create",
"operationId": "adcedb2f-c751-441f-8108-2c29667ea9cf",
"user": "employee",
"immediate": "false"
}
}
I thought of using DictField, but my problem is that there isn't a field name. it's only a dictionary of keys and values.
I tried something like:
class UserOperationSerializer(serializers.Serializer):
operation = serializers.ChoiceField(choices=["Create", "Delete"])
operationId = serializers.UUIDField()
user = serializers.CharField()
immediate = serializers.BooleanField()
class UserOperationsSerializer(serializers.Serializer):
test = serializers.DictField(child=RelationshipAuthorizeObjectSerializer())
But again, there isn't a 'test' field.
I think your easiest path forward would be to flatten the payload to the following format:
[
{
"request_id": "2fd08845-9b21-4972-87ed-2e7fd03448c5",
"operation": "Create",
"operationId": "356f6501-a117-4c8d-98ce-dcb4344d481b",
"user": "superuser",
"immediate": "true"
},
{
"request_id": "fe6d0c85-0021-431e-9955-e8e1b1ebc414",
"operation": "Create",
"operationId": "adcedb2f-c751-441f-8108-2c29667ea9cf",
"user": "employee",
"immediate": "false"
}
]
And then serialize it. Otherwise, you'd be creating custom fields/serializers which is not pretty.
The way I finally solved it was to add a dynamic 'body' field that contains the real payload of the request.
class UserOperationSerializer(serializers.Serializer):
operation = serializers.ChoiceField(choices=["Create", "Delete"])
operationId = serializers.UUIDField()
user = serializers.CharField()
immediate = serializers.BooleanField()
class UserOperationsSerializer(serializers.Serializer):
body = serializers.DictField(child=UserOperationSerializer())
def __init__(self, *args, **kwargs):
kwargs['data'] = {'body': kwargs['data']}
super().__init__(*args, **kwargs)
Then, in the View, I will use that data as serializer.validated_data['body']
That did the work for me.

Alexa conversational skill Error

I'm creating a skill in Alexa that does the following.
User : Hi
Alexa, hello please give me your name
User : John
Alexa : Hi John, good to meet you. How old are you
User : 25
Below are my intents
{
"intents": [
{
"intent": "StartTheFlow",
"slots": [
{
"name": "custName",
"type": "list_of_userNames"
},
{
"name": "age",
"type": "AMAZON.NUMBER"
}
]
},
{
"intent": "AMAZON.HelpIntent"
},{
"intent": "Welcome"
},
{
"intent": "AMAZON.StopIntent"
},
{
"intent": "AMAZON.CancelIntent"
}
]
}
And below are my utterances
StartTheFlow Hi
StartTheFlow {custName}
StartTheFlow {age}
Below is my onIntent()
#Override
public SpeechletResponse onIntent(final IntentRequest request, final Session session) throws SpeechletException {
log.info("onIntent requestId={}, sessionId={}", request.getRequestId(), session.getSessionId());
Intent intent = request.getIntent();
String intentName = (intent != null) ? intent.getName() : null;
if ("StartTheFlow".equals(intentName)) {
return getTheFlow(intent, session);
} else if ("AMAZON.HelpIntent".equals(intentName)) {
return getHelpResponse();
} else if ("WelcomeChubb".equals(intentName)) {
return getWelcomeResponse();
} else {
throw new SpeechletException("Invalid Intent");
}
}
And I'm trying to handle this as below
private SpeechletResponse getTheFlow(Intent intent, Session session) {
boolean isAskResponse = true;
String responseText = "";
String nameFromSession = (String) session.getAttribute("name");
if (StringUtils.isNullOrEmpty(nameFromSession)) {
responseText = "please give me your name";
getTheNameText(intent, session);
} else {
System.out.println(session.getAttribute("nameFromSession"));
responseText = "please give me your date of birth";
}
return getSpeechletResponse(responseText, "", isAskResponse);
}
private String getTheNameText(Intent intent, Session session) {
String userNameFrmIntent = getNameFromSlot(intent).toString();
session.setAttribute("nameFromSession", userNameFrmIntent);
return getNameFromSlot(intent).toString();
}
private String getNameFromSlot(Intent intent) {
Slot userName = intent.getSlot(Slot_Name);
return userName.getValue();
}
Also, I've defined a slot in the top as below.
private static final String Slot_Name = "custName";
But here when I type Hi, Instead of asking me my name, it is giving me an error in logs it shows Java NullPointer Exception. the response that I get when I type Hi is as below.
{
"session": {
"sessionId": "SessionId.a2740ca4-73ff-4a15-856d-6461b3c7b2e1",
"application": {
"applicationId": "amzn1.ask.skill.e3dfb30e-0089-423c-a325-30ad28dd2e2b"
},
"attributes": {},
"user": {
"userId": "amzn1.ask.account.AEQYTT5HFHEGGDSUCT3NW45HKR7O3FBL5YCBSZIS7P5LNP5BXFEMUR7AUYOZVKC2FT5V6RKJC7RNA5VMZVREBAXAQP3NFNTQSFSSKSEXIYT4FQYMS5JCI2CCAOPUF4FN4C6DHEU6ONNY3D6GN5AWK75KOQNJH2IWROIIXTPNXSNI6FLQYRBBMP7TRSOWVNCY73WJUT2VLHDACWA"
},
"new": true
},
"request": {
"type": "IntentRequest",
"requestId": "EdwRequestId.cf686fc0-cbfd-4496-bb09-c41714563507",
"locale": "en-US",
"timestamp": "2017-02-15T20:12:44Z",
"intent": {
"name": "StartTheFlow",
"slots": {
"custName": {
"name": "custName",
"value": "hi"
}
}
}
},
"version": "1.0"
}
Can someone please let me know where am I going wrong and how can I fix this, I've quite a number of questions to be linked, like 25, can Someone please let me know if there is a better way to do this in java.
Thanks
I would recommend creating a separate intent for each thing that the user says. So for example, HelloIntent, NameIntent, and AgeIntent.
Then be sure to pass those bits of information forward to all following intents in the session. So each intent could use a common function at the beginning to read each string from the session (if exists), add the new slot data to it, and then write all the strings back to the response session before finishing.
Since you'll then have separate intents, and the user could conceivably say them out of order, you may want to check that all the needed strings have been entered, or else prompt the user for any missing strings.
The problem with saving data in the session is that the data will be gone the next time the user starts the skill. To resolve this, you could use a database to hold the users data, saving it keyed to the userId. There are lots of examples on how to do that. Be careful that some databases are essentially free, but others will charge you depending on how many times it is used each month.

change json structure in Django

I've never had to change json structure before using Django models, so I may have made a completely stupid question.
I have some data in my database and want to parse it in a json format.
My view.py (a bit simplified) is:
def get_json(request):
pos = Pos.objects.filter(id=1).values('lat', 'lon','id')
return JsonResponse ({'position': list(pos)})
As a result I get this json object:
{ "position": [{"lat": "21", "id": 1, "lon": "21"}, {"lat": "22", "id": 1, "lon": "22"}, {"lat": "23", "id": 1, "lon": "23"}]}
In order to reduce the volume of unusefull data, I need to get a json structure like this:
{"id":"1", "position":{"lats":[21,22,23], "longs":[21,22,22]} }
I would be gratefull if sombody could help me
You'll need to process the data; you can do whatever you like within the view function.
pos = Pos.objects.filter(id=1).values('lat', 'lon','id')
data = {"lats": [], "longs": []}
for p in pos:
data["lats"].append(p['lat'])
data["longs"].append(p['long'])
return JsonResponse({'position': data})

Search for a mix of numbers and chars with haystack (elasticsearch)

I am using Django Haystack with Elasticsearch. I have a string field called 'code' in this type of format:
76-010
I would like to be able to search
76-
And get as a result
76-111
76-110
76-210
...
and so on.
but I don't want to get these results:
11-760
11-076
...
I already have a custom elastic search backend but I am not sure how should i indexing it to get the desired behavior.
class ConfigurableElasticBackend(ElasticsearchSearchBackend):
def __init__(self, connection_alias, **connection_options):
# see http://stackoverflow.com/questions/13636419/elasticsearch-edgengrams-and-numbers
self.DEFAULT_SETTINGS['settings']['analysis']['analyzer']['edgengram_analyzer']['tokenizer'] = 'standard'
self.DEFAULT_SETTINGS['settings']['analysis']['analyzer']['edgengram_analyzer']['filter'].append('lowercase')
super(ConfigurableElasticBackend, self).__init__(connection_alias, **connection_options)
The idea is to use an edgeNGram tokenizer in order to index every prefix of your code field. For instance, we would like 76-111 to be indexed as 7, 76, 76-, 76-1, 76-11 and 76-111. That way you will find 766-11 by searching for any of its prefixes.
Note that this article provides a full-fledge solution to your problem. The index settings for your case would look like this in Django code. You can then follow that article to wrap it up, but this should get you started.
class ConfigurableElasticBackend(ElasticsearchSearchBackend):
DEFAULT_SETTINGS = {
"settings": {
"analysis": {
"analyzer": {
"edgengram_analyzer": {
"tokenizer": "edgengram_tokenizer",
"filter": [ "lowercase" ]
}
},
"tokenizer": {
"edgengram_tokenizer": {
"type": "edgeNGram",
"min_gram": "1",
"max_gram": "25"
}
}
}
},
"mappings": {
"your_type": {
"properties": {
"code": {
"type": "string",
"analyzer": "edgengram_analyzer"
}
}
}
}
}
def __init__(self, connection_alias, **connection_options):
super(ConfigurableElasticBackend, self).__init__(connection_alias, **connection_options)
self.conn = pyelasticsearch.ElasticSearch(connection_options['URL'], timeout=self.timeout)
self.index_name = connection_options['INDEX_NAME']
# create the index with the above settings
self.conn.create_index(self.index_name, self.DEFAULT_SETTINGS)