Skip to content

Commit

Permalink
Evidently server side integration and workshop (#353)
Browse files Browse the repository at this point in the history
* Evidently resources and deps

* Evidently initial integration

* Fixes and metrics

* Evidently workshop WIP

* IAM permissions

* Cold user feature and experiment cleanup on delete

* Skip generator flag/optimization

* Explicit timestamp for experiment outcomes

* Default value for timestamp

* Update architecture diagram

* Fix for None timestamp

* All timestamp to be passed in

* Evidently workshop

* Local dev doc improvement

* Evidently IAM changes

* Evidently workshop improvements

* Evidently workshop improvements

* Built-in experiment compatibility

* Add link to Evidently workshop

* Add cold user feature to list of features

* Add troubleshooting/FAQ section

* Remove deleted entry point
  • Loading branch information
james-jory authored Apr 27, 2022
1 parent 34965ba commit f32e193
Show file tree
Hide file tree
Showing 46 changed files with 1,781 additions and 277 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ AWS Service | Workshops Overview | Workshop Links | Level | Duration
![Amazon Elasticsearch](./workshop/images/Amazon-Elasticsearch-Service_64.png) Amazon Elasticsearch | In this workshop, you will create a new Elasticsearch Index and index the Retail Demo Store product data so that users can search for products.| [Product Search](./workshop/0-StartHere/Search.ipynb) | 200 | 20 minutes
![Amazon Location Services](./workshop/images/Amazon-Location-Services_64.png) Amazon Location Services | Create a geofence for customers approaching your physical store and send them timely pickup notifications and offers. | [Geofencing](./workshop/7-LocationServices/7.1-LocationServices.ipynb) | 300 | 2 hours
![Amazon Alexa](./workshop/images/Amazon-Alexa_64.png) Amazon Alexa | Incorporating Location Service, Personalize and Retail Demo Store into a hands-free ordering experience. | [Alexa skill deployment](./workshop/5-Conversational/5.2-AlexaHandsfree.md) | 300 | 60 minutes
Experimentation | In this module we are going to add experimentation to the Retail Demo Store. This will allow us to experiment with different personalization approaches in the user interface. Through notebooks in this module we will demonstrate how to implement three experimentation techniques. | [Overview](./workshop/3-Experimentation/3.1-Overview.ipynb) <br/><br/> [A/B](./workshop/3-Experimentation/3.2-AB-Experiment.ipynb) <br/><br/> [Interleaving](./workshop/3-Experimentation/3.3-Interleaving-Experiment.ipynb) <br/><br/> [Multi-Armed Bandit](./workshop/3-Experimentation/3.4-Multi-Armed-Bandit-Experiment.ipynb) | 400 | 1.5 hours
Experimentation | In this module we are going to add experimentation to the Retail Demo Store. This will allow us to experiment with different personalization approaches in the user interface. Through notebooks in this module we will demonstrate how to implement three experimentation techniques as well as how to use [Amazon CloudWatch Evidently](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Evidently.html) for A/B tests. | [Overview](./workshop/3-Experimentation/3.1-Overview.ipynb) <br/><br/> [A/B](./workshop/3-Experimentation/3.2-AB-Experiment.ipynb) (400)<br/><br/> [Interleaving](./workshop/3-Experimentation/3.3-Interleaving-Experiment.ipynb) (400)<br/><br/> [Multi-Armed Bandit](./workshop/3-Experimentation/3.4-Multi-Armed-Bandit-Experiment.ipynb) (400)<br/><br/> [CloudWatch Evidently](./workshop/3-Experimentation/3.7-CloudWatch-Evidently-AB-Experiment.ipynb) (200)| 200/400 | 1.5 hours

## Partner Integrations

Expand Down Expand Up @@ -81,7 +81,7 @@ Europe (Ireland) | eu-west-1 | [![Launch Stack](https://cdn.rawgit.com/buildkite
Asia Pacific (Tokyo) | ap-northeast-1 | [![Launch Stack](https://cdn.rawgit.com/buildkite/cloudformation-launch-stack-button-svg/master/launch-stack.svg)](https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/create/review?templateURL=https://s3.amazonaws.com/retail-demo-store-ap-northeast-1/cloudformation-templates/template.yaml&stackName=retaildemostore&param_ResourceBucket=retail-demo-store-ap-northeast-1&param_SourceDeploymentType=CodeCommit)
Asia Pacific (Sydney) | ap-southeast-2 | [![Launch Stack](https://cdn.rawgit.com/buildkite/cloudformation-launch-stack-button-svg/master/launch-stack.svg)](https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-2#/stacks/create/review?templateURL=https://s3.amazonaws.com/retail-demo-store-ap-southeast-2/cloudformation-templates/template.yaml&stackName=retaildemostore&param_ResourceBucket=retail-demo-store-ap-southeast-2&param_SourceDeploymentType=CodeCommit)

The CloudFormation deployment will take 20-30 minutes to complete.
The CloudFormation deployment will take approximately 40 minutes to complete.

### Notes:

Expand Down Expand Up @@ -151,6 +151,19 @@ The intent of the Retail Demo Store is to 1) provide a tool to demonstrate the c
* Currently only tested in the AWS regions provided in the deployment instructions above. The only limitation for deploying into other regions is [availability of all required services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/).
- Amazon IVS is currently only supported in the N. Virginia (us-east-1), Oregon (us-west-2), and Ireland (eu-west-1) regions. Therefore, to deploy the Retail Demo Store in a region that does not support IVS, be sure to select to use the Default IVS Streams CloudFormation template parameter.

# Troubleshooting / FAQs

***Q: When accessing the Retail Demo Store web application after deploying the project, a CloudFront error is displayed. What's wrong?***

***A:*** Sign in to the AWS account/region where the project was deployed and browse to CodePipeline. Verify that the pipeline with "WebUIPipeline" in the name has successfully been built. If it failed, inspect the details of the Build stage to diagnose the root cause.

***Q: When accessing the Retail Demo Store web application after deploying the project, the home page shows spinning icons and products are never loaded. What's wrong?***

***A:*** The most likely cause is an error building or deploying one or more of the microservices. Sign in to the AWS account/region where the project was deployed and browse to CodePipeline. Verify that all of the Retail Demo Store pipelines have completed successfully. Inspect the details for any that have failed to determine the root cause. Sometimes just manually triggering a build/deploy will resolve the issue. If all pipelines were successful, make sure you're accessing the web application over HTTP and _not_ HTTPS.

***Q: This project is expensive to run (or keep running). How can I reduce the running cost of a deployment?***

***A:*** The most costly service in the project for an idle deployment is Amazon Personalize. You can eliminate Personalize idle costs by stopping all Amazon Personalize recommenders and deleting all campaigns in the Retail Demo Store dataset group for Personalize. This just shuts down the real-time inference endpoints; the datasets and ML models will remain. You should also change all of the recommender and campaign ARN parameter values in the AWS Systems Manager Parameter Store to `NONE`, leaving the parameter values for filters and the event tracker alone. These parameter names start with `/retaildemostore/personalize/` (e.g., `/retaildemostore/personalize/recommended-for-you-arn`). Once you complete these steps, the storefront will fall back to default behavior for recommending products from the catalog. To reactive Personalize, start the recommenders and create campaigns and then set the recommender and/or campaign ARNs back in the Systems Manager Parameter Store. The storefront will automatically start showing recommendations from Personalize again.
# Reporting Bugs

If you encounter a bug, please create a new issue with as much detail as possible and steps for reproducing the bug. See the [Contributing Guidelines](./CONTRIBUTING.md) for more details.
Expand Down
13 changes: 13 additions & 0 deletions aws/cloudformation-templates/base/_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ Resources:
PinpointAppId: !GetAtt Pinpoint.Outputs.PinpointAppId
GitHubUser: !Ref GitHubUser
GitHubBranch: !Ref GitHubBranch
EvidentlyProjectName: !GetAtt Evidently.Outputs.EvidentlyProjectName

# Tables
Tables:
Expand Down Expand Up @@ -309,6 +310,14 @@ Resources:
Uid: !Sub ${ParentStackName}-${AWS::Region}
StackBucketName: !GetAtt Buckets.Outputs.StackBucketName

# Evidently
Evidently:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub https://s3.amazonaws.com/${ResourceBucket}/${ResourceBucketRelativePath}cloudformation-templates/base/evidently.yaml
Parameters:
Uid: !Sub ${ParentStackName}-${AWS::Region}

Outputs:
UserPoolId:
Description: Authentication Cognito User Pool Id.
Expand Down Expand Up @@ -437,3 +446,7 @@ Outputs:
SwaggerUICDNURL:
Description: The URL for the web application
Value: !GetAtt CloudFront.Outputs.SwaggerUICDNURL

EvidentlyProjectName:
Description: Evidently project name
Value: !GetAtt Evidently.Outputs.EvidentlyProjectName
217 changes: 217 additions & 0 deletions aws/cloudformation-templates/base/evidently.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
---
AWSTemplateFormatVersion: 2010-09-09

Description: >
This template deploys the Retail Demo Store Evidently project and features.
Parameters:
Uid:
Type: String

Resources:
EvidentlyProject:
Type: AWS::Evidently::Project
Properties:
Name: !Ref Uid
Description: Retail Demo Store features and experiments

FeatureHomeProductRecs:
Type: AWS::Evidently::Feature
Properties:
DefaultVariation: Personalize-UserPersonalization
Description: Home page product recommendations
EvaluationStrategy: ALL_RULES
Name: home_product_recs
Project: !Ref EvidentlyProject
Variations:
- VariationName: FeaturedProducts
StringValue: '{"type":"product"}'
- VariationName: Personalize-UserPersonalization
StringValue: !Sub '{"type":"personalize-recommendations","arn":"arn:${AWS::Partition}:personalize:${AWS::Region}:${AWS::AccountId}:recommender/retaildemostore-recommended-for-you"}'

FeatureHomeProductRecsCold:
Type: AWS::Evidently::Feature
Properties:
DefaultVariation: Personalize-PopularItems
Description: Home page product recommendations for new/cold users
EvaluationStrategy: ALL_RULES
Name: home_product_recs_cold
Project: !Ref EvidentlyProject
Variations:
- VariationName: FeaturedProducts
StringValue: '{"type":"product"}'
- VariationName: Personalize-PopularItems
StringValue: !Sub '{"type":"personalize-recommendations","arn":"arn:${AWS::Partition}:personalize:${AWS::Region}:${AWS::AccountId}:recommender/retaildemostore-popular-items"}'

FeatureHomeFeaturedRerank:
Type: AWS::Evidently::Feature
Properties:
DefaultVariation: Personalize-PersonalizedRanking
Description: Home page featured products carousel
EvaluationStrategy: ALL_RULES
Name: home_featured_rerank
Project: !Ref EvidentlyProject
Variations:
- VariationName: RankingNoOp
StringValue: '{"type":"ranking-no-op"}'
- VariationName: Personalize-PersonalizedRanking
StringValue: !Sub '{"type":"personalize-ranking","arn":"arn:${AWS::Partition}:personalize:${AWS::Region}:${AWS::AccountId}:campaign/retaildemostore-personalized-ranking"}'

FeatureProductDetailRelated:
Type: AWS::Evidently::Feature
Properties:
DefaultVariation: Personalize-Similar-Items
Description: Product detail related products carousel
EvaluationStrategy: ALL_RULES
Name: product_detail_related
Project: !Ref EvidentlyProject
Variations:
- VariationName: ProductsInSameCategory
StringValue: '{"type":"product"}'
- VariationName: OpenSearchMoreLikeThis
StringValue: '{"type":"similar"}'
- VariationName: Personalize-Similar-Items
StringValue: !Sub '{"type":"personalize-recommendations","arn":"arn:${AWS::Partition}:personalize:${AWS::Region}:${AWS::AccountId}:campaign/retaildemostore-related-items"}'

FeatureSearchResults:
Type: AWS::Evidently::Feature
Properties:
DefaultVariation: Personalize-PersonalizedRanking
Description: Search control auto-complete
EvaluationStrategy: ALL_RULES
Name: search_results
Project: !Ref EvidentlyProject
Variations:
- VariationName: RankingNoOp
StringValue: '{"type":"ranking-no-op"}'
- VariationName: Personalize-PersonalizedRanking
StringValue: !Sub '{"type":"personalize-ranking","arn":"arn:${AWS::Partition}:personalize:${AWS::Region}:${AWS::AccountId}:campaign/retaildemostore-personalized-ranking"}'

FeatureLiveStreamProductRecs:
Type: AWS::Evidently::Feature
Properties:
DefaultVariation: Personalize-PersonalizedRanking
Description: Live stream product recommendations
EvaluationStrategy: ALL_RULES
Name: live_stream_prod_recommendation
Project: !Ref EvidentlyProject
Variations:
- VariationName: RankingNoOp
StringValue: '{"type":"ranking-no-op"}'
- VariationName: Personalize-PersonalizedRanking
StringValue: !Sub '{"type":"personalize-ranking","arn":"arn:${AWS::Partition}:personalize:${AWS::Region}:${AWS::AccountId}:campaign/retaildemostore-personalized-ranking"}'

FeatureLiveStreamProductDiscounts:
Type: AWS::Evidently::Feature
Properties:
DefaultVariation: Personalize-PersonalizedRanking
Description: Live stream product discounts
EvaluationStrategy: ALL_RULES
Name: live_stream_prod_discounts
Project: !Ref EvidentlyProject
Variations:
- VariationName: RankingNoOp
StringValue: '{"type":"ranking-no-op"}'
- VariationName: Personalize-PersonalizedRanking
StringValue: !Sub '{"type":"personalize-ranking","arn":"arn:${AWS::Partition}:personalize:${AWS::Region}:${AWS::AccountId}:campaign/retaildemostore-personalized-ranking"}'

EvidentlyCleanupLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Description: 'Retail Demo Store deployment utility function that cancels and deletes experiments to allow project to be fully deleted'
Code:
ZipFile: |
import boto3
import cfnresponse
def handler(event, context):
print(event)
response_data = {}
response_status = cfnresponse.SUCCESS
try:
project_name = event['ResourceProperties']['EvidentlyProjectName']
if event['RequestType'] == 'Delete':
evidently = boto3.client('evidently')
experiments_stopped = 0
experiments_deleted = 0
paginator = evidently.get_paginator('list_experiments')
for paginate_result in paginator.paginate(project = project_name):
for experiment in paginate_result['experiments']:
if experiment['status'] == 'RUNNING':
print(f"Experiment {experiment['name']} is still running; cancelling")
evidently.stop_experiment(desiredState='CANCELLED',
experiment=experiment['name'],
project=project_name
)
experiments_stopped += 1
print(f"Deleting experiment {experiment['name']}")
evidently.delete_experiment(experiment=experiment['name'],
project=project_name
)
experiments_deleted += 1
message = f"Stopped {experiments_stopped} experiments and deleted {experiments_deleted} experiments"
response_data['Message'] = message
else:
response_data['Message'] = "Nothing to do for this request type"
except Exception as e:
print("Error: " + str(e))
response_status = cfnresponse.FAILED
response_data['Message'] = "Resource {} failed: {}".format(event['RequestType'], e)
cfnresponse.send(event, context, response_status, response_data)
Handler: index.handler
Runtime: python3.9
Timeout: 120
Role: !GetAtt EvidentlyCleanupLambdaExecutionRole.Arn

CustomEvidentlyCleanup:
Type: Custom::EvidentlyCleanup
DependsOn: [ FeatureHomeProductRecs, FeatureHomeProductRecsCold, FeatureHomeFeaturedRerank, FeatureProductDetailRelated, FeatureSearchResults, FeatureLiveStreamProductRecs, FeatureLiveStreamProductDiscounts ]
Properties:
ServiceToken: !GetAtt EvidentlyCleanupLambdaFunction.Arn
EvidentlyProjectName: !Ref Uid

EvidentlyCleanupLambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Policies:
- PolicyName: LoggingPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: '*'
- PolicyName: Evidently
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- evidently:*
Resource:
- '*'

Outputs:
EvidentlyProjectName:
Description: Evidently project name
Value: !Ref Uid
14 changes: 14 additions & 0 deletions aws/cloudformation-templates/base/notebook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ Parameters:
PinpointAppId:
Type: String

EvidentlyProjectName:
Type: String

Conditions:
UseDefaultGitHubUser: !Equals
- !Ref GitHubUser
Expand Down Expand Up @@ -245,6 +248,17 @@ Resources:
Resource:
- !Sub 'arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ExperimentStrategyTable}'
- !Sub 'arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${ExperimentStrategyTable}/index/*'
- Effect: Allow
Action:
- evidently:GetFeature
- evidently:EvaluateFeature
- evidently:CreateExperiment
- evidently:StartExperiment
- evidently:StopExperiment
Resource:
- !Sub 'arn:aws:evidently:${AWS::Region}:${AWS::AccountId}:project/${EvidentlyProjectName}'
- !Sub 'arn:aws:evidently:${AWS::Region}:${AWS::AccountId}:project/${EvidentlyProjectName}/experiment/*'
- !Sub 'arn:aws:evidently:${AWS::Region}:${AWS::AccountId}:project/${EvidentlyProjectName}/feature/*'
-
PolicyName: "4-Messaging"
PolicyDocument:
Expand Down
Loading

0 comments on commit f32e193

Please sign in to comment.