Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion workshop/content/building_ml_model/_index.en.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
+++
title = "Building a Machine Learning Model"
chapter = true
weight = 5
weight = 6
+++

Let’s ensure that the data we imported in activity 2 has been imported successfully, and start training a machine learning model that can provide us those personalised product recommendations.
4 changes: 2 additions & 2 deletions workshop/content/building_ml_model/building_ml_model.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
+++
title = "Step by Step"
weight = 3
weight = 2
+++

1. Navigate to the dashboard for your team and ensure all datasets have been uploaded successfully.

2. The next step is to use this data to create a solution. Click **Start** under **Create solutions**.

3. Specify the solution name as product-recommendations-team-#. Leave the recipe selection as Manual, and choose the aws-personalized-ranking solution from the drop down box. This algorithm once trained on the data we imported will allow us to rank an input list of items for a given user. Other algorithms that can be selected to allow recommendations based on other factors included in the data imported, such as demographics.
3. Specify the solution name as {{<copypaste id="tooltiptext0" text="product-recommendations-team-#">}}. Leave the recipe selection as Manual, and choose the **aws-personalized-ranking solution** from the drop down box. This algorithm once trained on the data we imported will allow us to rank an input list of items for a given user. Other algorithms that can be selected to allow recommendations based on other factors included in the data imported, such as demographics.

4. Leave the solution configuration as default. These are optional parameters that can be tuned if required. Click **Next**.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ title = "Step by Step"
weight = 2
+++

1. Navigate to the Alexa developer portal tab in chrome (needs to be logged in beforehand)
1. Navigate to the **Alexa developer portal** tab in chrome (needs to be logged in beforehand)

2. To save time, we’ve pre-created an empty Alexa skill called daily deal team # that we can start to populate with the following:

- Invocation: This is what the customer will say to begin their interaction. The Skill Invocation Name should be prepopulated with your Alexa skill name. i.e. Daily Deals team one. Therefore, the customer begins interacting with your Alexa skill by saying, “Alexa, start Daily Deal team one”.

- Intent: This is an action that fulfills the customer’s request based on provided inputs. Click Add Intent, enter SurpriseMeIntent and click Create custom intent. On the next page, enter what you would expect the customer to say to invoke the intent. You can add multiple utterances, such as:
- Surprise me
- Send me something
- surprise me its {name}
- Its {name} surprise me
- Intent: This is an action that fulfills the customer’s request based on provided inputs. Click **Add Intent**, enter {{<copypaste id="tooltiptext0" text="SurpriseMeIntent">}} and click **Create custom intent**. On the next page, enter what you would expect the customer to say to invoke the intent. You can add multiple utterances, such as:
- {{<copypaste id="tooltiptext1" text="Surprise me">}}
- {{<copypaste id="tooltiptext2" text="Send me something">}}
- {{<copypaste id="tooltiptext3" text="surprise me its {name}">}}
- {{<copypaste id="tooltiptext4" text="Its {name} surprise me">}}

- Slot: You may have noticed in the above examples that name is in curly brackets. This is to indicate that this is a variable value. Obviously, we’re going to need to know the customer’s name, so we can either get that information from their initial utterance, or we can ask them for it. Scroll to the bottom and observe the added Intent slot called name. Set the Slot Type to firstname to ensure the Alexa skill recognises the type of data being provided. Click Edit Dialog, and enable Is this slot required to fulfil the intent. Under Alexa speech prompts, add What is your name and click +. Under User utterances add My name is {name} and click *+*. This ensures your skill is able to collect the user’s name if they haven’t already provided it.
- Slot: You may have noticed in the above examples that name is in curly brackets. This is to indicate that this is a variable value. Obviously, we’re going to need to know the customer’s name, so we can either get that information from their initial utterance, or we can ask them for it. Scroll to the bottom and observe the added Intent slot called name. Set the Slot Type to {{<copypaste id="tooltiptext5" text="firstname">}} to ensure the Alexa skill recognises the type of data being provided. Click **Edit Dialog**, and enable **Is this slot required** to fulfil the intent. Under Alexa speech prompts, add {{<copypaste id="tooltiptext6" text="What is your name ">}} and click **+**. Under User utterances add {{<copypaste id="tooltiptext7" text="My name is {name}">}} and click **+**. This ensures your skill is able to collect the user’s name if they haven’t already provided it.

- Switch to the Validation tab and choose Accept only Slot Type’s values and synonyms, then press *+*. In the text box below, type sorry I didnt catch that whats your name
- Switch to the **Validation tab** and choose **Accept only Slot Type’s values and synonyms**, then press **+**. In the text box below, type {{<copypaste id="tooltiptext8" text="sorry I didnt catch that whats your name">}} then press **+**.

![activity-3-01](/images/activity-3-01.png)

- Scroll back to the top and select **Build Model**.

3. We’ve now created the basic construct of our Chabot that’s going to interact with the user and collect information required for us to determine a suitable product and deliver it to them. Let’s now go back to AWS Personalize and complete the building of our machine learning model.
3. We’ve now created the basic construct of our Chabot that’s going to interact with the user and collect information required for us to determine a suitable product and deliver it to them. Let’s now glue everything together before finishing our AWS Personalize machine learning model.
8 changes: 4 additions & 4 deletions workshop/content/data_exploration/data_exploration.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ title = "Step by Step"
weight = 2
+++

1. Navigate to the S3 service and look at the subfolders under processed/instacart in the codingforexecs bucket. Notice that the data is in files, rather than in a database running on a server. It’s going to be fairly difficult to analyse these files without knowing their structure. We can solve this problem by using AWS Glue!
1. Navigate to the **Amazon S3** service and look at the subfolders under **processed/instacart** in the **codingforexecs** bucket. Notice that the data is in files, rather than in a database running on a server. It’s going to be fairly difficult to analyse these files without knowing their structure. We can solve this problem by using AWS Glue!

2. Navigate to AWS Glue and look at the orders crawler. Note the S3 locations it crawls through, and note how it’s discovered the tables and determined the columns for the data files in S3.
2. Navigate to **AWS Glue** and look at the **orders** crawler. Note the S3 locations it crawls through, and note how it’s discovered the tables and determined the columns for the data files in S3.

3. We now need to determine the top 8 ordered products by our customers across all departments as these are the products we’d like to provide to our most loyal customers (generous, I know!). To determine this let’s navigate to AWS Athena, and run a SQL query on the Datalake database that determines the top products in each department:
3. We now need to determine the top 8 ordered products by our customers across all departments as these are the products we’d like to provide to our most loyal customers (generous, I know!). To determine this let’s navigate to **AWS Athena**, and run a SQL query on the **Datalake** database that determines the top products in each department:

SELECT
"product_id"
Expand Down Expand Up @@ -64,7 +64,7 @@ weight = 2

5. Excellent! Not sure I want recycled paper towels, dropped out of the sky as a loyalty gift, but let’s go with it. Rather than writing down the top 8 products, let’s save the search as a Saved query so we can run it on demand later.

6. Click on Save as and name the statement most_ordered_products-team#
6. Click on **Save as** and name the statement {{<copypaste id="tooltiptext0" text="most_ordered_products-team#">}}

## Added Challenge!

Expand Down
4 changes: 2 additions & 2 deletions workshop/content/glueing_all_together/_index.en.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
+++
title = "Gluing it all Together"
chapter = true
weight = 6
weight = 5
+++

So we’ve analysed our data, built a Machine Learning model, and built the basic constructs of our Chatbot. But how does this all glue together? We need to pass the name collected from our Chatbot to our machine learning model to provide us with a personalised recommendation. We then need to pass that information to the drones for delivery. We need some glue to put all this business logic together.
So we’ve analysed our data, started building our Machine Learning model, and built the basic constructs of our Chatbot. But how does this all glue together? We need to pass the name collected from our Chatbot to our machine learning model to provide us with a personalised recommendation. We then need to pass that information to the drones for delivery. We need some glue to put all this business logic together.

Traditionally, applications would be developed and run on servers in a data centre to facilitate these processes and communication. With AWS Lambda, we’re able to take a more event driven approach, where we execute code on demand that represents business logic, and only pay a fraction of a cent for the seconds that code executes. Let’s create our Lambda function that ties all this together.

14 changes: 7 additions & 7 deletions workshop/content/glueing_all_together/glueing_all_together.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ title = "Step by Step"
weight = 2
+++

1. Navigate to the AWS Lambda service in the console
1. Navigate to the **AWS Lambda** service in the console.

2. Click Create function and specify the following:
2. Click **Create function** and specify the following:

- Function name: orderLambda-team#
- Function name: {{<copypaste id="tooltiptext0" text="orderLambda-team#">}}

- Runtime: Python 3.7 – This is the language we’ll be writing our business logic in
- Runtime: **Python 3.8** – This is the language we’ll be writing our business logic in

- Execution role: Use an existing role: LambdaOrdersRole – This provides our Lambda function programmatic access to our machine learning model and IoT drones for delivery
- Execution role: Use an existing role: **LambdaOrdersRole** – This provides our Lambda function programmatic access to our machine learning model and IoT drones for delivery

3. Select **Create function**.

Expand Down Expand Up @@ -220,6 +220,6 @@ weight = 2
*See if you can spot the location in the code where we feed in the top 8 products. If you had the chance in Activity 1 to determine the least ordered products, replace the list of items with the bottom 8 products*
{{% /expand %}}

5. The final thing left to do is add a required Python library, and ensure the Alexa skill invokes the Lambda function once it’s collected the user’s details. To do this, expand the Designer window, click on Layers and add the Boto3layer. Select version 3 and click Add. Click Add trigger, the select Alexa Skills Kit. Select Disable for the Skill ID verification and select Add. Click Save. Copy the ARN which is a resource identifier for the Lambda function in the top right hand corner.
5. The final thing left to do is ensure the Alexa skill invokes the Lambda function once it’s collected the user’s details. To do this, expand the Designer window, click **Add trigger**, the select **Alexa Skills Kit**. Select **Disable** for the Skill ID verification and select **Add**. Click **Save**. Copy the ARN which is a resource identifier for the Lambda function in the top right hand corner.

6. Go back to your Alexa developer console and select Endpoint, then choose AWS Lambda ARN, and paste the ARN copied in the previous step, in Default Region. Click Save Endpoints. Select the Invocation tab, then select Build Model.
6. Go back to your Alexa developer console and select **Endpoint**, then choose **AWS Lambda ARN**, and paste the ARN copied in the previous step, in Default Region. Click **Save Endpoints**. Select the **Invocation tab**, then select **Build Model**.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ title = "Step by Step"
weight = 2
+++

1. To begin, navigate to AWS Personalize and start by creating a Dataset group named **orders-team#**
1. To begin, navigate to **AWS Personalize** and start by creating a Dataset group named {{<copypaste id="tooltiptext0" text="orders-team#">}}
2. Once the dataset group is created, we need to upload 3 sets of data in CSV format, which the Octank data team has prepared:

- User-item interaction data located in **s3://codingforexecs/extract/personalize/items-by-user/**. This is the purchase history for each user. Call the dataset **user-purchase-history-team#** and leave the schema details as is. The schema details dictate what the structure of your data file looks like. After clicking Next, call the dataset import name import-purchase-history-team# and specify the S3 location specified above in the Data Location. Leave the IAM Service Role as default and select Finish.
- Purchase history for each user. Call the dataset {{<copypaste id="tooltiptext1" text="user-purchase-history-team#">}} and leave the schema details as is. The schema details dictate what the structure of your data file looks like. After clicking **Next**, call the dataset import name {{<copypaste id="tooltiptext2" text="import-purchase-history-team#">}} and specify the S3 location as {{<copypaste id="tooltiptext3" text="s3://codingforexecs/extract/personalize/items-by-user/">}}. Leave the IAM Service Role as default and select **Finish**.

- User data located in **s3://codingforexecs/extract/personalize/users/**. Click on import for user data. This is user information, including optional demographic information. Call the dataset **users-team#** and leave the schema details as is. The schema details dictate what the structure of your data file looks like. After clicking Next, call the dataset import name **import-users-team#** and specify the S3 location specified above in the Data Location. Leave the IAM Service Role as default and select Finish.
- User information, including optional demographic information. Call the dataset {{<copypaste id="tooltiptext4" text="users-team#">}} and leave the schema details as is. After clicking **Next**, call the dataset import name {{<copypaste id="tooltiptext5" text="import-users-team#">}} and specify the S3 location {{<copypaste id="tooltiptext6" text="s3://codingforexecs/extract/personalize/users/">}}. Leave the IAM Service Role as default and select **Finish**.

- Item data located in **s3://codingforexecs/extract/personalize/items/**. Click on import for item data. Call the dataset **items-team#** and leave the schema details as is. The schema details dictate what the structure of your data file looks like. After clicking Next, call the dataset import name **import-items-team#** and specify the S3 location specified above in the Data Location. Leave the IAM Service Role as default and select Finish.
- Item data. Call the dataset {{<copypaste id="tooltiptext7" text="items-team#">}} and leave the schema details as is. After clicking **Next**, call the dataset import name {{<copypaste id="tooltiptext8" text="import-items-team#">}} and specify the S3 location {{<copypaste id="tooltiptext9" text="s3://codingforexecs/extract/personalize/items/">}}. Leave the IAM Service Role as default and select **Finish**.

3. The data is now being imported and prepared to train your machine learning model, as per the screenshot below. This is going to take a bit of time, so let’s come back to it after we’ve created our voice interface.

Expand Down
2 changes: 1 addition & 1 deletion workshop/content/introduction/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ To run this workshop, you’ll need the following:
</li>
<br>
<li>
(Optional) Crazyflie indoor explorer bundle plus extra drones and 4 lighting stands: [From here](https://store.bitcraze.io/products/indoor-explorer-bundle)
(Optional) Crazyflie indoor explorer bundle plus extra drones and 4 lighting stands: <a href="https://store.bitcraze.io/products/indoor-explorer-bundle">https://store.bitcraze.io/products/indoor-explorer-bundle</a>
</li>
</ol>
1 change: 1 addition & 0 deletions workshop/layout/partials/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
{{with .Site.Params.themeVariant}}
<link href="{{(printf "css/theme-%s.css" .) | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
{{end}}
<link href="{{"css/clipboard.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">

<script src="{{"js/jquery-3.3.1.min.js"| relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}"></script>

Expand Down
2 changes: 1 addition & 1 deletion workshop/themes/learn/layouts/partials/footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
<script src="{{"js/modernizr.custom-3.6.0.js" | relURL}}{{ if not .Site.Params.disableAssetsBusting }}?{{ now.Unix }}{{ end }}"></script>
<script src="{{"js/learn.js" | relURL}}{{ if not .Site.Params.disableAssetsBusting }}?{{ now.Unix }}{{ end }}"></script>
<script src="{{"js/hugo-learn.js" | relURL}}{{ if not .Site.Params.disableAssetsBusting }}?{{ now.Unix }}{{ end }}"></script>

<script src="{{"js/copypaste.js" | relURL}}{{ if not .Site.Params.disableAssetsBusting }}?{{ now.Unix }}{{ end }}"></script>
<link href="{{"mermaid/mermaid.css" | relURL}}{{ if not .Site.Params.disableAssetsBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet" />
<script src="{{"mermaid/mermaid.js" | relURL}}{{ if not .Site.Params.disableAssetsBusting }}?{{ now.Unix }}{{ end }}"></script>
<script>
Expand Down
1 change: 1 addition & 0 deletions workshop/themes/learn/layouts/partials/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<title>{{ .Title }} :: {{ .Site.Title }}</title>

{{ $assetBusting := not .Site.Params.disableAssetsBusting }}
<link href="{{"css/clipboard.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
<link href="{{"css/nucleus.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
<link href="{{"css/fontawesome-all.min.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
<link href="{{"css/hybrid.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
Expand Down
1 change: 1 addition & 0 deletions workshop/themes/learn/layouts/shortcodes/copypaste.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<span onClick="copyText(this)" onmouseout="resetToolTip(this)" class="tooltip">{{ .Get "text" }}<span id={{ .Get "id" }} class="tooltiptext">Click to copy</span></span>
48 changes: 48 additions & 0 deletions workshop/themes/learn/static/css/clipboard.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* Tooltip container */
.tooltip {
position: relative;
display: inline;
font-weight: bold;
border-bottom: 1px dotted black;
cursor: pointer !important;
}

/* Tooltip text */
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: #555;
color: #fff;
text-align: center;
padding: 5px 0;
border-radius: 6px;

/* Position the tooltip text */
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -60px;

/* Fade in tooltip */
opacity: 0;
transition: opacity 0.3s;
}

/* Tooltip arrow */
.tooltip .tooltiptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}

/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
14 changes: 14 additions & 0 deletions workshop/themes/learn/static/js/copypaste.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function copyText(el){
var textArea = document.createElement("textarea");
textArea.value = el.childNodes[0].textContent
document.body.appendChild(textArea);
textArea.select();
textArea.setSelectionRange(0, 99999);
document.execCommand("copy");
textArea.remove();
el.childNodes[1].textContent = "Copied!"
}

function resetToolTip(el){
el.childNodes[1].textContent = "Click to copy"
}