Skip to content

Commit 5ea318b

Browse files
committed
Update register script to send CloudWatch event
1 parent 72ab1e4 commit 5ea318b

File tree

7 files changed

+29
-14
lines changed

7 files changed

+29
-14
lines changed

deployment_pipeline/README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@ This deployment pipeline contains a few stages.
1010
1. **Source**: Pull the latest deployment configuration from AWS CodeCommit repository.
1111
1. **Build**: AWS CodeBuild job to create the AWS CloudFormation template for deploying the endpoint.
1212
- Query the Amazon SageMaker project to get the top approved models.
13-
- Use the AWS CDK to create a CFN stack with multiple endpoint variants.
14-
- Create a `register.json` file that contains the target SageMaker endpoint and A/B testing strategy.
15-
2. **Deploy**: Run the AWS CloudFormation stack to create/update the SageMaker endpoint.
16-
3. **Register**: Call the RegisterAPI for the endpoint to create/clear the A/B testing metrics.
13+
- Use the AWS CDK to create a CFN stack to deploy multi-variant SageMaker Endpoint.
14+
2. **Deploy**: Run the AWS CloudFormation stack to create/update the SageMaker endpoint, tagged with properties based on configuration:
15+
- `ab-testing:enabled` equals `true`
16+
- `ab-testing:strategy` is one `WeightedSampling`, `EpslionGreedy`, `UCB1` or `ThompsonSampling`.
17+
- `ab-testing:epsilon` is parameters for `EpslionGreedy` strategy, defaults to `0.1`.
18+
- `ab-testing:warmup` the number of invocations to warmup with `WeightedSampling` strategy, defaults to `0`.
1719

1820
![\[AWS CodePipeline\]](../docs/ab-testing-pipeline-code-pipeline.png)
1921

2022
## Testing
2123

22-
Once you have created a SageMaker Project, you can test the **Build** and **Register** stages locally by setting some environment variables, and running the commands found in the `buildspec` defined in the pipeline.
24+
Once you have created a SageMaker Project, you can test the **Build** stage and **Register** events locally by setting some environment variables.
2325

2426
### Build Stage
2527

@@ -32,12 +34,11 @@ export STAGE_NAME="dev"
3234
cdk synth
3335
```
3436

35-
### Register Stage
37+
### Register
3638

3739
Export the environment variable for the `REGISTER_LAMBDA` created as part of the `ab-testing-api` stack, then run `register.py` file.
3840

3941
```
4042
export REGISTER_LAMBDA="<<register_lambda>>"
4143
python register.py
4244
```
43-

deployment_pipeline/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
# Append tags for ab-testing
4646
tags += [
4747
core.CfnTag(key="ab-testing:enabled", value="true"),
48-
core.CfnTag(key="ab-testing:stategy", value=deployment_config.strategy),
48+
core.CfnTag(key="ab-testing:strategy", value=deployment_config.strategy),
4949
core.CfnTag(key="ab-testing:epsilon", value=str(deployment_config.epsilon)),
5050
core.CfnTag(key="ab-testing:warmup", value=str(deployment_config.warmup)),
5151
]

deployment_pipeline/infra/model_registry.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def get_latest_approved_packages(
5959
# Return error if no packages found
6060
if len(model_packages) == 0 and creation_time_after is None:
6161
error_message = (
62-
f"No latest packages found for: {model_package_group_name}"
62+
f"No approved packages found for: {model_package_group_name}"
6363
)
6464
logger.error(error_message)
6565
raise Exception(error_message)
@@ -121,9 +121,7 @@ def get_versioned_approved_packages(
121121

122122
# Return error if no packages found
123123
if len(model_packages) == 0:
124-
error_message = (
125-
f"No versioned packages found for: {model_package_group_name}"
126-
)
124+
error_message = f"No approved packages found for: {model_package_group_name} and versions: {model_package_versions}"
127125
logger.error(error_message)
128126
raise Exception(error_message)
129127

deployment_pipeline/register.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,20 @@
2424
# Get the config and include with endpoint to register this model
2525
with open(f"{stage_name}-config.json", "r") as f:
2626
j = json.load(f)
27-
event = json.dumps({"endpoint_name": endpoint_name, **j})
27+
event = json.dumps({
28+
'source': 'aws.sagemaker',
29+
'detail-type': 'SageMaker Endpoint State Change',
30+
'detail': {
31+
'EndpointName': endpoint_name,
32+
'EndpointStatus': 'IN_SERVICE',
33+
'Tags': {
34+
'ab-testing:enabled': 'true',
35+
'ab-testing:strategy': j.get('strategy', 'ThompsonSampling'),
36+
'ab-testing:epsilon': str(j.get('epsilon', 0.1)),
37+
'ab-testing:warmup': str(j.get('warmup', 0)),
38+
}
39+
}
40+
})
2841
response = lambda_client.invoke(
2942
FunctionName=register_lambda,
3043
InvocationType="RequestResponse",
-3.96 KB
Loading

infra/api_stack.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ def __init__(
190190
targets=[targets.LambdaFunction(lambda_register)],
191191
)
192192

193+
# Return the register lambda function as output
194+
core.CfnOutput(self, "RegisterLambda", value=lambda_register.function_name)
195+
193196
# Get cloudwatch put metrics policy ()
194197
cloudwatch_metric_policy = aws_iam.PolicyStatement(
195198
actions=["cloudwatch:PutMetricData"], resources=["*"]

lambda/api/lambda_register.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def lambda_handler(event, context):
111111
if endpoint_status == "DELETING":
112112
result, status_code = handle_delete(endpoint_name)
113113
elif endpoint_status == "IN_SERVICE":
114-
strategy = endpoint_tags["ab-testing:stategy"]
114+
strategy = endpoint_tags["ab-testing:strategy"]
115115
epsilon = float(endpoint_tags["ab-testing:epsilon"])
116116
warmup = int(endpoint_tags["ab-testing:warmup"])
117117
result, status_code = handle_register(

0 commit comments

Comments
 (0)