Once we have trained our model and deployed to an Amazon SageMaker fully-managed endpoint, we are ready to build a REST API that will be invoked by client applications to get inferences. Although the Amazon SageMaker HTTPs endpoint might be called directly, using Amazon API Gateway for our REST API provides more control on things like user authorization, usage profiles, throttling, API versioning, etc.
The request flow would be:
- The client application executes a POST request to the Amazon API Gateway endpoint
- An AWS Lambda function processes the request and calls the Amazon SageMaker HTTPs endpoint where our model is hosted
- The inference response is returned by the Amazon SageMaker endpoint and sent back to the client via Amazon API Gateway
Let's get started by creating our rest API.
We are going to use AWS Cloud9 for building our API: AWS Cloud9 is a cloud-based integrated development environment (IDE) that lets you write, run, and debug your code with just a browser. The service preconfigures the development environment with all the SDKs, libraries, and plug-ins needed for serverless development, thus facilitating the development of AWS Lambda functions and API Gateway APIs.
-
Open your AWS Console and open Cloud9
-
Click on Create environment
-
Add a name endtoendml-env, click on Next step
-
Leave the configuration with the default settings and click on Next step
-
Click Create environment
Now that we have created our Cloud9 environment we will be waiting a couple of minutes for the environment to be up and running and in front of us.
Once the environment is up and running please:
-
Press on AWS Resources on the right side of the screen
-
Click on the Lambda icon to create a new function as it is shown on the picture below.
-
Type endtoendmllambdafunction in the function name textbox and endtoendmlapplication in the application name textbox and click Next.
-
Select Python3.6 in runtime. Then chose empty-python and click Next.
-
In Function trigger, leave none and click Next.
-
In the Create serverless application window, select Choose existing role from the Role dropdown and then choose the IAM role LambdaInvokeSageMakerEndpointRole-endtoendml from the Existing Role dropdown. This will allow the function to invoke the Amazon SageMaker endpoint. Then press Next.
The LambdaInvokeSageMakerEndpointRole-endtoendml IAM role has been created in advance in your AWS account for the purpose of this workshop.
-
Press Finish.
-
Once clicked on Finish you might get a pop up window asking for Drag & drop files here, in this case, please ignore it by click on x on the top right corner of the popup window.
Now that we have created our Lambda function, we need to add the code to it. The files that we are going to edit are lambda_function.py and template.yaml that you can open using the file browser in the left side of the Cloud9 editor.
The file lambda_function.py will contain the code that will process the content of the HTTP request of the API call and invoke the Amazon SageMaker endpoint.
Please replace the content of that file with the following snippet, making sure that the indentation is matching:
⚠️ Warning: the ENDPOINT_NAME variable must be set to the name of the endpoint that was deployed in the previus module of this workshop.
import boto3
import json
import csv
import os
# Remember to update the endpoint name with the name of the SageMaker endpoint
ENDPOINT_NAME = 'pred-main-pipeline-endpoint-XXXXXXXXXX'
runtime= boto3.client('runtime.sagemaker')
def build_response(status_code, response_body):
return {
'statusCode': status_code,
'body': json.dumps(response_body),
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Credentials' : 'true',
'Access-Control-Allow-Headers': '*'
},
}
def lambda_handler(event, context):
print("Received event: " + json.dumps(event, indent=2))
if 'httpMethod' in event:
if event['httpMethod'] == 'OPTIONS':
return build_response(200, '')
elif event['httpMethod'] == 'POST':
turbine_data = event['body']
response = runtime.invoke_endpoint(EndpointName=ENDPOINT_NAME,
ContentType='text/csv',
Body=turbine_data)
print(response)
result = json.loads(response['Body'].read().decode())
print(result)
return build_response(200, result)
else:
return build_response(405, 'null')
The implementation is straightforward: the Lambda handler can manage both OPTIONS and POST requests, and when a POST is executed, the Amazon SageMaker endpoint is invoked with the Body parameter set to the request body. Then, the response is returned to the caller.
The file template.yaml contains a template - defined through the Serverless Application Model - to deploy the AWS Lambda function. We are going to add a few instructions to deploy also an Amazon API Gateway API.
Please add the following lines to the template.yaml file, after the CodeUri property, making sure that the Events property indentation is matching the indentation of CodeUri:
Events:
GetInference:
Type: Api
Properties:
Path: /
Method: POST
OptionsInference:
Type: Api
Properties:
Path: /
Method: OPTIONS
The additional statements are used to deploy an Amazon API Gateway REST API, which will accept POST and OPTIONS requests and pass the request content to the AWS Lambda function defined above.
For additional information on this way of integrating AWS Lambda and Amazon API Gateway, please visit AWS Lambda Proxy Integration.
After you have finished editing lambda_function.py and template.yaml, you have to save all changes by using the menu item File > Save All.
Before deploying our Lambda function, it is a good practice to test it locally in the AWS Cloud9 environment. To accomplish this task:
-
Ensure the lambda__function.py file is opened and is the active tab, then press the Run button in the top-central area of the screen as shown in the following screenshot:
-
A new tab will appear, where you can type the payload that will be passed to the function and execute it.
-
Input the following payload and press Run to test the function locally.
{ "httpMethod": "POST", "body": "TID008,VAWT,64,80,46.0,21,55,55,7,34,NE" }
-
You should see some output as shown in the following screenshot:
Now we are ready to deploy our AWS Lambda function and Amazon API Gateway API. Please execute the following actions:
-
In the right-side panel make sure AWS Resources is selected.
-
Then, in the panel tree browser select the package endtoendmlapplication.
-
Press in sequence the Refresh functions list and then the Deploy the selected Lambda function buttons as shown in the following screenshot:
-
After a while, the deploy completes and you should not see any error message.
After our Lambda function and API have been deployed from Cloud9, we can verify the API Gateway deployment in order to get the address of our REST endpoint.
-
Go back to the AWS Console and access API Gateway (you can use the top search bar for finding the service).
-
In the dashboard, click on the widget cloud9-endtoendmlapplication. A screen showing the API resources and the defined HTTP methods will appear, similar to the one shown below:
-
Click on Stages in the left tree menu and then on the Prod stage. Copy/take note of the Invoke URL that will be used by the client application as API endpoint.
-
At your convenience, you can also browse through the different settings that can be specified for the stage, like log and tracing, throttling, caching, etc.
You can now proceed to Module 06 to invoke the API Gateway endpoint from an Angular single-page application.