- [Jon] In week one, I told you about Lex. We had some fun in the console with a simple BookTrip bot. There are a few components that I did not discuss during that lecture, and most of it had to do with the Lambda integration. Now that you know about Lambda, it's time to discuss the interaction between Lex and Lambda. Let's take a look at our BookTrip bot again. It has two intents: BookCar and BookHotel. We're going to go in BookHotel. When the user enters a utterance, Lex chooses the right intent and then uses prompts to ask questions to the user to fill every slot of the intent so it can be fulfilled. So we can see, many slots are at the bottom in here. As I mentioned, in the Lambda integration wasn't discussed, this includes the Lambda initialization and validation, as well as the fulfillment. The reason to use Lambda for fulfillment is the same reason as to why you would use Lambda to replace servers. You only pay while your Lambda function is running, and it's serverless, which means you don't need to manage the components behind Lambda, and you can concentrate on your backend code. In this bot example, I will want the Lambda function to include the pricing for the hotel booking and car booking, add the fulfillment on. Let's first look at validation, though. When the intent in configured to invoke a Lambda function as initialization and validation code hook, Amazon Lex invokes the specified Lambda function on each user input after Amazon Lex understands the intent. If the intent is not clear, Amazon Lex can't invoke the Lambda function. Why would we want a Lambda function invoked for every single utterance or prompt? Validation, of course! But don't we already do validations in the case where we select Restrict to Slot values and Synonyms in a slot type? As an example right here - restrict to slot types. Well, yes, but sometimes we don't control the slot because it's a built-in slot. As you can see, the slots down here, the Amazon ones. Let's take the Location slot of the BookHotel intent as an example. What if we only had hotels in a very specific list of cities? We can't change the Amazon.US_CITY slot type, to include only the values that we want. It's a built-in slot type. That's where Lambda comes to our rescue. It allows us to extend the capabilities of the bot. Let me show you what happens when I book a hotel in Moscow right now. As you can see, it prompts me back to supply a city. Let's supply Moscow. It continued on. As you can see, this city's accepted. However, what if it wasn't one of the city we had hotels in? Well, there's no validation here. Of course, it will let me go. We will need to fix that. Let's finish this iteration with the bot to refresh your memory of what happens across this entire bot. So in here: "What day do you want to check in?" I'll answer: tomorrow. "How many nights will you be staying?" Five. Then finally: "What type of room would you like, queen, king, or deluxe?" Queen is good for me. I get a confirmation prompt: "Okay, I have you down "for a 5 night stay in Moscow starting on 2019-02-21. Shall I book the reservation?" Yes. And I get back the normal fulfillment that you have seen in the past. To add validation, we first need to create a Lambda function. I will be using a blueprint, as the Lex team was nice enough to give us a template for the Lex sample bot that we all need to use. From the Lambda console, I'll click Create function. I'll select Blueprints and then search for Lex. I can see that the lex-book-trip-python blueprint isn't here, and that's the one I will use. I'll click Configure at the bottom of the page, and I'll need to supply a name for it. I'll give it a name like lex-book-trip. And then I will have to choose a role for my Lambda function to be able to send logs to CloudWatch Logs. Let's not look at the code yet, though. I'll create the function. Let's go back to the Lex console to modify our bot to send this traffic towards this Lambda function. In the Lex console, I will modify both intents to use this Lambda function for initialization and validation, as well as fulfillment. So in the BookHotel, I am going to go to the section of Lambda initialization and validation, select that check box, select our lex-book-trip function, and I'll get this popup. That is asking me to allow Lex to call our Lambda function, else Lex won't be able to send that request to it. I'll click OK here. Let's do the same with the BookCar intent, as well as the fulfillment in there. I'm starting to build now, for my chain should take effect. With the power of recording, I will skip ahead for the build to finish. Okay, it's ready for testing. Let's try the same example as earlier. Book a hotel. "What city will you be staying in?" Moscow. And I get this prompt, "We currently do not support Moscow as a valid destination. Can you try a different city?" It doesn't seem to want to let me go forward with the city. That is normal, as Lambda is now doing the validation and only allows a specific set of cities where we have hotels. You are welcome to look at the Lambda code if you feel comfortable with Python. It will explain a few things that are in here. However, instead of looking at the code itself, I will explain to you the flow of the data passed back and forth between the client, Lex, and Lambda. Let me explain it to you in a diagram now. As you can see in this picture, I have a user on the left-hand side, Lex in the middle, and Lambda on the right. The user inputs, "Book a hotel." That is a sent as a utterance towards Amazon Lex. Amazon Lex will parse the data and send it as an input JSON to Lambda. Lambda will do its validation and then return some output JSON statement towards Lex. And Lex will finally send some of that response back towards the user, which will probably prompt for "In which city," by that point. The user can now enter Moscow at that time. Now, remember that the first step is the data sent from the client into Lex. If I roll back a little, I have "Book a hotel," the data gets sent into Lex. Let me restart this test that I have here by clicking on Clear chat history. I'll book a hotel. Let's see what is sent into Lex in this case. Because remember, I have the utterance that is now sent into Lex. Let's take a look at that JSON payload. This is the data that is being sent. You can see that there is the client sending a POST towards our BookTrip in the alias LATEST and for a very specific user. I will come back to this user a little bit later in this lecture. I also can see the inputText data: book a hotel. That is what will be sent towards Lex. The next step is for Lex to send the data to Lambda and input JSON. Let me switch back towards the input that was sent, and then this is it. A lot of information is here, but let's take a look. The invocation source is set to - so, invocationSource - to DialogCodeHook. This is how the Lambda function knows that it's supposed to do validation of the entries and not do fulfillment, as that will be the other option that we will see later. We can see the bot name, BookTrip, in there, in case that the same Lambda function was used for more than one bot. The currentIntent name is pretty important though, because I'm reusing that same Lambda function for BookHotel and BookCar. It's currently set to BookHotel, which means Lex was able to figure out that we wanted to book a hotel from the text that was sent. That didn't seem that difficult. All of the slot types are currently set to null, as you can see. So Lambda doesn't need to do much validation at that point. So to itself, it doesn't really do anything there. However, it will need to send some data back towards Lex. Now that Lambda has done that processing, which means that it's essentially nothing this time around, as it's only the initialization, it will send data back to Lex. Let's take a look at it. This is how our response looks like. It needs to be a dialogAction type. I will have a dialogAction of type: Delegate. This means - or that directs Amazon Lex to choose the next course of action based on the bot configuration. That next course of action is to prompt for the first launch, which is the city, right? If we look at our configuration of our bot, we can see that the first slot is the Location. So it needs to say, "What city will you be staying in?" The data will be sent as a Lex response back towards the user. Let's take a look at what that looks like. What I get is "What city will you be staying in?" sent back towards the user as you saw inside of the console. I will now go back into my Lex console and write Moscow. Let's go back to our diagram now. What did I just do? Well, I just sent a prompt into Lex. I just fulfilled a slot. It is the exact same four steps that will need to happen again here. Let's take a look at all of those four interactions' payload and then we're not going to really come back into this diagram now. So the next section is the client sends Moscow. As you remember, the inputText is set to Moscow. Next, Lex needs to send that data into Lambda. So, the data that is now going to be sent is towards the currentIntent, name: BookHotel. And then the location is now going to be set to Moscow. Lambda can now process the city and validate it against its list of cities where there are available hotels. In this case, Moscow isn't part of it. Here is what Lambda sends back. It will say dialogAction type, of type ElicitSlot, which informs Lex that the user is expected to provide a slot value in the response. The intentName is specified - BookHotel - and the Location is now set back to null, as it wasn't valid, and the slotToElicit is now set to Location, which is the important one. We now tell Lex which slot to prompt back the user for. However, instead of using a built-in message, we also supply a message to the user. "We currently do not support Moscow as a valid destination. Can you try a different city?" That is what will be sent towards the user. That data is now sent back to the client. Here's what Lex sent. "We currently do not support Moscow as a valid destination. Can you please try a different city?" This time around, the client is ready to choose a different city. Let me pick another one, Chicago. Oh, it seems it let me through. Let's go and take a look at what happened there. The client sent Chicago - inputText: Chicago. Lex sends the data into Lambda. This time around, currentIntent, name: BookHotel. And then the Location: Chicago. Nothing really has changed in this case. Now Lambda will need to validate this city. Chicago is a city where we have a hotel, so this passes the validation. This is what Lambda replies. DialogAction, type: Delegate. A Delegate type, as we want Lex to continue its processing to the next slot. As you can see, Lex is now asking for the check-in date. "What day do you want to check in?" Yes, it's the next one in the order. If you remember well, I have the Location, and then the number two is CheckInDate. So that's why I used that prompt. We've now seen how validation works between Lex and Lambda. In our next video, I'll go over how to do fulfillment with Lambda and the usage of session attributes. I'll see you there.