Reputation: 557
I created a simple bot to find the weather in a city. I have a lambda that calls an API and gets the weather of a city. I tested the lambda and it works fine. I configured the lex bot to call the lambda. I am going to post the lambda code, bot screeen shots and testing put that I used to test my lambda
from urllib.request import Request, urlopen
import json
from pprint import pprint
import urllib3
def lambda_handler(event, context):
pprint('received request: ' + str(event))
city = event['currentIntent']['slots']['city']
#print(city)
citytemperature = get_city_temperature(city)
#print('city temp is ' + str(citytemperature))
response = {
"dialogAction": {
"type": "Close",
"fulfillmentState": "Fulfilled",
"message": {
"contentType": "SSML",
"content": format(citytemperature)
},
}
}
#print('result = ' + str(response))
return response
def get_city_temperature(city):
print('weather of the city , city = ' + str(city))
api_key = 'myapikeyjkjkjkj'
base_url = 'http://api.openweathermap.org/data/2.5/weather?'
finalurl = base_url + 'appid=' + api_key + '&q=' + city
#print(finalurl)
httprequest = urllib3.PoolManager()
response = httprequest.request('GET',finalurl)
weather_status = json.loads(response.data.decode('utf-8'))
return weather_status["main"]["temp"]
This is the test data I used to test the lambda and it works fine when I run the lambda by itself. When I call this lambda from the lex bot, I don't see it being invoked at all. In the cloud watch logs I see this error:
[ERROR] KeyError: 'currentIntent'
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 8, in lambda_handler
city = event['currentIntent']['slots']['city']
[ERROR] KeyError: 'currentIntent' Traceback (most recent call last): File
"/var/task/lambda_function.py", line 8, in lambda_handler city =
event['currentIntent']['slots']['city']
This is the documentation that says what should be sent as an input into Lambda and what should the response from lambda to the bot should look like.
https://docs.aws.amazon.com/lex/latest/dg/lambda-input-response-format.html
This is the test data to test the bot in lambda. Lambda works fine. If you change city name to something, it finds the temperature of the city
{
"messageVersion": "1.0",
"invocationSource": "FulfillmentCodeHook",
"userId": "AROAVNZMIA3MR7EYI4M7O",
"sessionAttributes": {},
"requestAttributes": "None",
"bot": {
"name": "Weather",
"alias": "$LATEST",
"version": "$LATEST"
},
"outputDialogMode": "Text",
"currentIntent": {
"name": "FindWeather",
"slots": {
"city": "pomona"
},
"slotDetails": {
"city": {
"resolutions": [],
"originalValue": "pomona"
}
},
"confirmationStatus": "None"
},
"inputTranscript": "whats the temperature in pomona?"
}
[![enter image description here][1]][1]
Upvotes: 0
Views: 831
Reputation: 579
I believe your issue is a simple one. You have coded your Lambda function against Version 1 of Lex lambda schema.
The input and output message formats for Lex V2 are considerably different. You'll find the sample request and response formats here: https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html#lambda-input-format
In particular, you will find the currentIntent
equivalent within sessionState
in the V2 input payload. So, your code to retrieve the users value for city
should look like this:
city = event['sessionState']['intent']['slots']['city']['interpretedValue']
Also, you will need to change your response message to ensure it matches with what Lex V2 expects. It should look something like this:
event['sessionState']['intent']['state'] = 'Fulfilled'
return {
'sessionState': {
'sessionAttributes': session_attributes,
'dialogAction': {
'type': 'Close'
},
'intent': event['sessionState']['intent']
},
'messages': [message],
'sessionId': event['sessionId'],
'requestAttributes': event['requestAttributes'] if 'requestAttributes' in event else None
}
Here's the guide for the output format for V2: https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html#lambda-response-format
Upvotes: 1