├── Diagrams_lex_bookhotel.26784edb7206413e2046d5a00b411589d56a6621.png
├── LICENSE.txt
├── NOTICE.txt
├── README.md
├── src
└── index.js
└── test
└── cafeOrderCoffee_test.json
/Diagrams_lex_bookhotel.26784edb7206413e2046d5a00b411589d56a6621.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/amazon-ai-building-better-bots/f7de6bef60e0a30fb41677a6278626a4e0c7a997/Diagrams_lex_bookhotel.26784edb7206413e2046d5a00b411589d56a6621.png
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Amazon Software License
3 |
4 | 1. Definitions
5 |
6 | “Licensor” means any person or entity that distributes its Work.
7 |
8 | “Software” means the original work of authorship made available under this License.
9 |
10 | “Work” means the Software and any additions to or derivative works of the Software that are made available under this License.
11 |
12 | The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the meaning as provided under U.S. copyright law; provided, however, that for the purposes of this License, derivative works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work.
13 |
14 | Works, including the Software, are “made available” under this License by including in or with the Work either (a) a copyright notice referencing the applicability of this License to the Work, or (b) a copy of this License.
15 | 2. License Grants
16 |
17 | 2.1 Copyright Grant. Subject to the terms and conditions of this License, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free, copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense and distribute its Work and any resulting derivative works in any form.
18 |
19 | 2.2 Patent Grant. Subject to the terms and conditions of this License, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free patent license to make, have made, use, sell, offer for sale, import, and otherwise transfer its Work, in whole or in part. The foregoing license applies only to the patent claims licensable by Licensor that would be infringed by Licensor’s Work (or portion thereof) individually and excluding any combinations with any other materials or technology.
20 | 3. Limitations
21 |
22 | 3.1 Redistribution. You may reproduce or distribute the Work only if (a) you do so under this License, (b) you include a complete copy of this License with your distribution, and (c) you retain without modification any copyright, patent, trademark, or attribution notices that are present in the Work.
23 |
24 | 3.2 Derivative Works. You may specify that additional or different terms apply to the use, reproduction, and distribution of your derivative works of the Work (“Your Terms”) only if (a) Your Terms provide that the use limitation in Section 3.3 applies to your derivative works, and (b) you identify the specific derivative works that are subject to Your Terms. Notwithstanding Your Terms, this License (including the redistribution requirements in Section 3.1) will continue to apply to the Work itself.
25 |
26 | 3.3 Use Limitation. The Work and any derivative works thereof only may be used or intended for use with the web services, computing platforms or applications provided by Amazon.com, Inc. or its affiliates, including Amazon Web Services, Inc.
27 |
28 | 3.4 Patent Claims. If you bring or threaten to bring a patent claim against any Licensor (including any claim, cross-claim or counterclaim in a lawsuit) to enforce any patents that you allege are infringed by any Work, then your rights under this License from such Licensor (including the grants in Sections 2.1 and 2.2) will terminate immediately.
29 |
30 | 3.5 Trademarks. This License does not grant any rights to use any Licensor’s or its affiliates’ names, logos, or trademarks, except as necessary to reproduce the notices described in this License.
31 |
32 | 3.6 Termination. If you violate any term of this License, then your rights under this License (including the grants in Sections 2.1 and 2.2) will terminate immediately.
33 | 4. Disclaimer of Warranty.
34 |
35 | THE WORK IS PROVIDED “AS IS” WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OR CONDITIONS OF M ERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT. YOU BEAR THE RISK OF UNDERTAKING ANY ACTIVITIES UNDER THIS LICENSE. SOME STATES’ CONSUMER LAWS DO NOT ALLOW EXCLUSION OF AN IMPLIED WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO YOU.
36 | 5. Limitation of Liability.
37 |
38 | EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO LEGAL THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE SHALL ANY LICENSOR BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATED TO THIS LICENSE, THE USE OR INABILITY TO USE THE WORK (INCLUDING BUT NOT LIMITED TO LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS OR DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY OTHER COMM ERCIAL DAMAGES OR LOSSES), EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
39 |
40 | Effective Date – April 18, 2008 © 2008 Amazon.com, Inc. or its affiliates. All rights reserved.
41 |
--------------------------------------------------------------------------------
/NOTICE.txt:
--------------------------------------------------------------------------------
1 | amz-ai-building-better-bots
2 | Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | i# amazon-ai-building-better-bots
2 |
3 | Code samples related to [Building Better Bots](https://aws.amazon.com/blogs/ai/building-better-bots-part-2/) published on the AWS ML Blog.
4 |
5 | # CoffeeBot chat bot
6 |
7 | CoffeeBot is a transactional chat bot that can help you order a coffee.
8 |
9 | This tutorial will help you build CoffeeBot using Amazon Lex and Lambda so you can have a conversation like the following:
10 |
11 | > User: May I have a mocha?
12 | > CoffeeBot: What size? small, medium, large?
13 | > User: small
14 | > CoffeeBot: Would you like that iced or hot?
15 | > User: hot
16 | > CoffeeBot: You'd like me to order a small mocha. Is that right?
17 | > User: Make it a large mocha
18 | > CoffeeBot: You'd like me to order a large mocha. Is that right?
19 | > User: yeah
20 | > CoffeeBot: Great! Your mocha will be available for pickup soon. Thanks for using CoffeeBot!
21 |
22 | ## Building an Amazon Lex chat bot
23 |
24 | To build our chat bot, we're going to utilize several new constructs including `intents`, `utterances`, `fulfillment` and `slots`. Each of these constructs serve a different purpose in allowing Lex to understand how to interact with a user.
25 |
26 | The following diagram provides an overview of the main components and how Amazon Lex utilizes them:
27 |
28 |

29 |
30 | Now that we're aware of the components of an Amazon Lex chat bot, lets build one!
31 |
32 | ### 1. Create the bot
33 |
34 | From within the AWS console, navigate to the `Amazon Lex` service console, and click `Create` and then select `Custom bot` to create a new bot. Enter the following settings for your bot:
35 |
36 | Setting | Value
37 | ------- | -----
38 | Bot name | `CoffeeBot`
39 | Output voice | Choose any voice
40 | Session timeout | `5 min`
41 | Sentiment Analysis | `No`
42 | IAM role | `AWSServiceRoleForLexBots`
43 | COPPA | `No`
44 |
45 | Note: If you are sharing an AWS account with others, append your initials to the bot name to make it unique (e.g., `CoffeeBotXXX`)
46 |
47 | ### 2. Create an intent
48 |
49 | Using the left-hand menu under 'Intents' click the `+` button to add a new Intent called `cafeOrderBeverageIntent`, click 'Add' to save the Intent. Once the Intent is created, add the below list of 'utterances' to your newly created Intent by placing them one-at-a-time into the 'Sample utterances' entry box and clicking `+` or pressing 'Enter' to save each.
50 | Note: If you are working in a shared AWS account with others, append your initials to the Intent name so each is unique (e.g., `cafeOrderBeverageIntentXXX`).
51 |
52 | Utterances |
53 | ---------- |
54 | I would like a {BeverageSize} {BeverageType} |
55 | Can I get a {BeverageType} |
56 | May I have a {BeverageSize} {Creamer} {BeverageType} |
57 | Can I get a {BeverageSize} {BeverageTemp} {Creamer} {BeverageType} |
58 | Let me get a {BeverageSize} {Creamer} {BeverageType} |
59 |
60 |
61 | ### 3. Create slot types
62 |
63 | Using the left-hand menu under 'Slot types' click the `+` button to add a new slot type. Select 'Create slot type' in the popup window to create a custom slot type. Enter the 'Slot type name' and then add each value seperately from the 'Values' column of the table below. To add each value to your slot type, click the `+` button next the the value entry box or press 'enter'. When you have entered all the values for the slot type you are working on, click the `Add slot to intent` button. You should have created 4 slot types in total.
64 |
65 | Note: Although they are saved with the AWS Account, Slot Types will not show up in the list until they are associated in the next step.
66 | If you are working in a shared AWS account with others, append your initials to the Slot type name so each is unique.
67 |
68 | Slot type name | Description | Slot resolution | Values (each entry on a separate line)
69 | -------------- | ----------- | --------------- | --------------------------------------
70 | `cafeBeverageType` | *Slot types are shared at the account level so text would help other developers determine if they can reuse this Slot type.*| default | `coffee`
`cappuccino`
`latte`
`mocha`
`chai`
`espresso`
`smoothie`
71 | `cafeBeverageSize` | | default | `kids`
`small`
`medium`
`large`
`extra large`
`six ounce`
`eight ounce`
`twelve ounce`
`sixteen ounce`
`twenty ounce`
72 | `cafeCreamerType` | | default | `two percent`
`skim milk`
`soy`
`almond`
`whole`
`skim`
`half and half`
73 | `cafeBeverageTemp` | | default | `kids`
`hot`
`iced`
74 |
75 | ### 4. Add slots to the intent
76 | Under the 'Slots' section of your CoffeeBot, add the following entries to the list of Slots by choosing the Slot type from the drop down selection, entering a 'Name' and completing the 'Prompt'. Click the `+` button to add the Slot to the Intent.
77 |
78 | Note: You will not see the 'Required' field until you have added the Slot.
79 |
80 | Required | Name | Slot type | Prompt
81 | -------- | --------------- | --------- | -------------
82 | `Yes` | `BeverageType` | `cafeBeverageType` | `What kind of beverage would you like? For example, mocha, chai, etc.`
83 | `Yes` | `BeverageSize` | `cafeBeverageSize` | `What size? small, medium, large?`
84 | | `Creamer` | `cafeCreamerType` | `What kind of milk or creamer?`
85 | | `BeverageTemp` | `cafeBeverageTemp` | `Would you like that iced or hot?`
86 |
87 | ### 5. Set the confirmation prompt
88 |
89 | Expand the 'Confirmation prompt' section and check the box for 'Confirmation prompt'. Add the following confirmation prompts:
90 |
91 | Confirmation type | Description
92 | ----------------- | -----------
93 | Confirm | You'd like me to order a `{BeverageSize}` `{BeverageType}`. Is that right?
94 | Cancel | Okay. Nothing to order this time. See you next time!
95 |
96 | ### 6. Define fulfillment
97 |
98 | Under the `Fulfillment` section, choose `Return parameters to client` for simple testing. This setting will change later.
99 |
100 | ### 7. Define responses
101 |
102 | Expand the `Response` section and select `Add Message` to add the following closing message to the intent.
103 |
104 | #### Response message
105 | ```
106 | Thank you. Your {BeverageType} has been ordered.
107 | ```
108 |
109 | Click the `+` button to add the response. Check the checkbox 'Wait for user reply' and enter the following message, clicking the `+` when you are finished:
110 |
111 | #### Wait for user reply message
112 | ```
113 | OK. Thank you. Have a great day!
114 | ```
115 |
116 | Click the 'Save Intent' button at the bottom of the page.
117 |
118 | ### 8. Review the error handling settings
119 | After saving the Intent, select 'Error Handling' from the left-hand side menu. Make sure the `Clarification prompt` and `Hang-up phrase` are both present and that the 'Maximum number of retries' is set to `2`.
120 |
121 | Error Handling Prompt | Message
122 | --------------------- | -------
123 | Clarification prompts | Sorry, can you please repeat that?
124 | Maximum number of retries | 2
125 | Hang-up phrase | Sorry, I could not understand. Goodbye.
126 |
127 | Click 'Save' when you have confirmed your settings match those above.
128 |
129 | ### 9. Build and test the bot
130 | Build the chatbot by clicking the `Build` button at the top right of the console. Once the build is complete, you'll be able to test the bot with the utterances you've entered above. The 'Test bot' panel on the right-hand side will allow you to chat with your bot in the 'Chat with your bot...' entry box.
131 |
132 | For example, if you say `May I have a chai?`, does Lex correctly map `chai` to the `BeverageType` slot?
133 |
134 | ## Create a Lambda function
135 |
136 | To handle more complex logic, we can link our chat bot to a Lambda function to process the user's interaction with the bot and create action based responses.
137 |
138 | ### Create the function
139 |
140 | 1. Open the 'AWS Lambda' service in a new tab in your browser. It may help to duplicate your existing tab.
141 | 1. From the AWS Lambda console, click the `Create function` button at the top right.
142 | 1. Select `Author from scratch` under the `Create function` page.
143 | 1. Set the following values under the `Basic information` section of the Lambda:
144 | 1. 'Function name' = `cafeOrderCoffee`
145 | 2. 'Runtime' = `Node.js 12.x`
146 | 2. Under the `Permissions` header, expand the `Choose or create an execution role` section.
147 | 3. Under the `Execution role` header, select `Create a new role with basic Lambda permissions`
148 | 4. Click `Create function` at the bottom of the page to create the Lambda.
149 | 5. Once the Lamba editor page has loaded, scroll to the `Function code` and remove all the default code in the editor
150 | 6. Replace the content of the function code [with the example code here](https://github.com/aws-samples/amazon-ai-building-better-bots/blob/master/src/index.js)
151 |
152 | ### Create a test event to validate the function
153 |
154 | 1. Click the dropdown next to the `Test` button with the text 'Select a test event'. Select `Configure test events` from the dropdown.
155 | 2. Enter `cafeOrderTest` as a name for your test event in the `Event Name` field.
156 | 3. Replace the test event JSON with the [sample event JSON](https://github.com/aws-samples/amazon-ai-building-better-bots/blob/master/test/cafeOrderCoffee_test.json)
157 | 4. Click `Create`
158 | 5. Click `Test` to run the function test and review the output in the 'Execution results' in the code editor area.
159 |
160 | ## Update the bot to use the Lambda
161 | Now that we have processing logic in the Lambda, we'll associate the Lambda with the bot so that the code gets executed when we interact with CoffeeBot.
162 |
163 | 1. Navigate to the `Amazon Lex` console adn select the `CoffeeBot` bot from the `Bots` list
164 | 2. Make sure `Latest` is selected from the version drop down next to the `cafeOrderBeverageIntent`
165 | 3. Expand the `Lamda initialization and validation` section and check the `Initialization and validation code hook` checkbox
166 | 4. In the `Lambda function` drop down, select the `cafeOrderCoffee` Lambda function and leave the `Version or alias` as `Latest`
167 | 1. If prompted, allow Amazon Lex to call your new function
168 | 5. Expand the `Fulfillment` section and select the `AWS Lambda function` radio button
169 | 6. Select the `cafeOrderCoffee` Lambda function from the `Lambda function` drop down and leave the `Version or alias` as `Latest`
170 | 7. Click `Save Intent` at the bottom of the screen
171 | 8. Rebuild the Chat bot by clicking the `Build` button at the top of the screen
172 |
173 | Now that the Lambda is connected to the CoffeeBot and is re-built to use the Lambda, test the new responses by chatting with the bot in the `Test bot` dialog on the right hand side of the screen.
174 |
175 | For example, ask the bot for a coffee:
176 |
177 | `Can I get a coffee?`
178 |
179 | Notice that the bot responds differently. It is now referencing the logic in the Lambda function to validate the input and respond back accordingly.
180 |
181 | ## Errors
182 | If you have this error: "The checksum value doesn't match for the resource named..." then a page refresh is required - the build should work as normal after this.
183 |
184 | ## AWS Amplify
185 |
186 | When you're ready, try out [AWS Amplify](https://aws-amplify.github.io/docs/js/interactions) for bringing your chatbot to a mobile or web environment.
187 |
188 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | Licensed under the Amazon Software License (the "License"). You may not use this file except
4 | in compliance with the License. A copy of the License is located at
5 | http://aws.amazon.com/asl/
6 | or in the "LICENSE.txt" file accompanying this file.
7 | This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
8 | express or implied. See the License for the specific language governing permissions and
9 | limitations under the License.
10 | */
11 | /*
12 | * This code sample demonstrates an implementation of the Lex Code Hook Interface
13 | * in order to serve a bot which is used to order coffee.
14 | *
15 | * For instructions on how to set up and test this bot, as well as additional samples,
16 | * visit the Lex Getting Started documentation.
17 | *
18 | * This example is intentionally simplistic for illustration; please consider using
19 | * the Amazon Lex blueprints for your projects.
20 | */
21 | 'use strict';
22 | const todayMenuBeverageType = {
23 | 'mocha':{'size': ['short', 'small', 'medium', 'large']},
24 | 'chai':{'size': ['small', 'short']}
25 | };
26 |
27 | // --------------- Helpers to build responses which match the structure of the necessary dialog actions -----------------------
28 |
29 | function elicitSlot(sessionAttributes, intentName, slots, slotToElicit, message, responseCard) {
30 | return {
31 | sessionAttributes,
32 | dialogAction: {
33 | type: 'ElicitSlot',
34 | intentName,
35 | slots,
36 | slotToElicit,
37 | message,
38 | responseCard,
39 | },
40 | };
41 | }
42 |
43 | function confirmIntent(sessionAttributes, intentName, slots, message, responseCard) {
44 | return {
45 | sessionAttributes,
46 | dialogAction: {
47 | type: 'ConfirmIntent',
48 | intentName,
49 | slots,
50 | message,
51 | responseCard,
52 | },
53 | };
54 | }
55 |
56 | function close(sessionAttributes, fulfillmentState, message, responseCard) {
57 | return {
58 | sessionAttributes,
59 | dialogAction: {
60 | type: 'Close',
61 | fulfillmentState,
62 | message,
63 | responseCard,
64 | },
65 | };
66 | }
67 |
68 | function delegate(sessionAttributes, slots) {
69 | return {
70 | sessionAttributes,
71 | dialogAction: {
72 | type: 'Delegate',
73 | slots,
74 | },
75 | };
76 | }
77 |
78 |
79 |
80 | // ---------------- Helper Functions --------------------------------------------------
81 |
82 | // build a message for Lex responses
83 | function buildMessage(messageContent) {
84 | return {
85 | contentType: 'PlainText',
86 | content: messageContent,
87 | };
88 | }
89 |
90 | // Build a responseCard with a title, subtitle, and an optional set of options which should be displayed as buttons.
91 | function buildResponseCard(title, subTitle, options) {
92 | let buttons = null;
93 | if (options !== null) {
94 | buttons = [];
95 | for (let i = 0; i < Math.min(5, options.length); i++) {
96 | buttons.push(options[i]);
97 | }
98 | }
99 | return {
100 | contentType: 'application/vnd.amazonaws.card.generic',
101 | version: 1,
102 | genericAttachments: [{
103 | title,
104 | subTitle,
105 | buttons,
106 | }],
107 | };
108 | }
109 |
110 | function buildResponseOptions(optionsArray = Array){
111 | var responseOptions = [];
112 | for(var i=0; i {
216 |
217 | console.log(JSON.stringify(event));
218 |
219 | try {
220 | console.log(`event.bot.name=${event.bot.name}`);
221 |
222 | // fail if this function is for a different bot
223 | if(! event.bot.name.startsWith('CoffeeBot')) {
224 | callback('Invalid Bot Name');
225 | }
226 | dispatch(event, (response) => callback(null, response));
227 | } catch (err) {
228 | callback(err);
229 | }
230 | };
231 |
--------------------------------------------------------------------------------
/test/cafeOrderCoffee_test.json:
--------------------------------------------------------------------------------
1 | {
2 | "messageVersion": "1.0",
3 | "invocationSource": "DialogCodeHook",
4 | "userId": "test-1",
5 | "sessionAttributes": {},
6 | "bot": {
7 | "name": "CoffeeBot",
8 | "alias": null,
9 | "version": "$LATEST"
10 | },
11 | "outputDialogMode": "Text",
12 | "currentIntent": {
13 | "name": "cafeOrderBeverageIntent",
14 | "slots": {
15 | "BeverageType": "mocha",
16 | "BeverageStrength": null,
17 | "Creamer": null,
18 | "BeverageSize": null,
19 | "BeverageTemp": null,
20 | "BeverageExtras": null
21 | },
22 | "confirmationStatus": "None"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------