Jason
Jason

Reputation: 557

AWS lex bot calling a Lambda function boto3 always returns "Intent FindWeather is fulfilled" Lambda works fine

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

Answers (1)

Reegz
Reegz

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

Related Questions