{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# SageMaker Edge Manager Example\n", "\n", "1. [Introduction](#Introduction)\n", "2. [Demo Setup](#Demo-Setup)\n", "3. [Compile Model using SageMaker Neo](#Compile-Model-using-SageMaker-Neo)\n", " 1. [Load pretrained model](#Load-pretrained-model)\n", "6. [Deploy Model using Sagemaker Edge Manager](#Deploy-Model-using-Sagemaker-Edge-Manager)\n", " 1. [Package Model](#Package-Model)\n", " 2. [Create AWS IoT thing](#Create-AWS-IoT-thing)\n", " 3. [Create Device Fleet](#Create-Device-Fleet)\n", " 4. [Create and register client certificate with AWS IoT](#Create-and-register-client-certificate-with-AWS-IoT)\n", "7. [Inference on Edge](#Inference-on-Edge)" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "## Introduction\n", "\n", "SageMaker Edge Manager is a service from Amazon SageMaker that lets you:\n", "\n", "+ prepares custom models for edge device hardware\n", "+ includes a runtime for running machine learning inference efficiently on edge devices\n", "+ enables the device to send samples of data from each model securely to SageMaker for relabeling and retraining.\n", "\n", "There are two main components to this service:\n", "+ SageMaker Edge Manager in the Cloud \n", "+ SageMaker Edge Agent on the Edge device\n", "\n", "This nootebook demonstrates the end-to-end workflow for getting a running Sagemaker Edge on the edge device. This will involve the following steps:\n", "\n", "+ Compile the model using SageMaker Neo\n", "+ Package the compiled model with Sagemaker Edge Manager\n", "+ Deploy with Sagemaker Edge Manager Agent\n", "+ Run inference with the model\n", "+ Capture model's input and output data to S3\n", "\n", "This notebook is intented only for notebook instances. When you run this notebook, choose the kernel: `conda_tensorflow_p36`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Please note**: There are pricing implications to the use of this notebook. Please refer to [Edge Manager](https://aws.amazon.com/sagemaker/edge-manager/pricing) for more information." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Demo Setup" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We need an AWS account role with SageMaker access. This role is used to give SageMaker access to S3, launch an EC2 instance and send command with Systems Manager." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#update boto3 version\n", "!pip3 install boto3==1.16.45 \n", "!pip3 install awscli==1.18.209" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import sagemaker\n", "from sagemaker import get_execution_role\n", "import boto3\n", "import botocore\n", "import json\n", "\n", "role = get_execution_role()\n", "sess = sagemaker.Session()\n", "region = boto3.Session().region_name" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(role)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Locate the above printed sagemaker role from IAM console, find and attach the following policies to role:\n", "\n", "AmazonEC2FullAccess\n", "AmazonEC2RoleforSSM\n", "AmazonSSMManagedInstanceCore\n", "AmazonSSMFullAccess\n", "AWSIoTFullAccess\n", "You can find more information about how to attach policies to role here - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html#add-policies-console.\n", "\n", "If you try this example with a real device, only attach AWSIoTFullAccess to create certificates on AWS IoT.\n", "\n", "We then need an S3 bucket that would be used for storing the model artifacts generated after compilation and packaged artifacts generated after edge packaging job." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We then need an S3 bucket that would be used for storing the model artifacts generated after compilation and packaged artifacts generated after edge packaging job." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# S3 bucket and folders for saving model artifacts.\n", "# Feel free to specify different bucket/folders here if you wish.\n", "bucket = sess.default_bucket() \n", "folder = 'DEMO-Sagemaker-Edge'\n", "compilation_output_sub_folder = folder + '/compilation-output'\n", "iot_folder = folder + '/iot'\n", "\n", "# S3 Location to save the model artifact after compilation\n", "s3_compilation_output_location = 's3://{}/{}'.format(bucket, compilation_output_sub_folder)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally we upload the test image to S3 bucket. This image will be used in inference later." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Upload an image for testing purposes. \n", "darknet_img_path = sess.upload_data('<>', bucket, iot_folder)\n", "keras_img_path = sess.upload_data('<>', bucket, iot_folder)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compile Model using SageMaker Neo\n", "\n", "Create Sagemaker client." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sagemaker_client = boto3.client('sagemaker', region_name=region)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Download pretrained darknet model" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!wget -O yolov3-tiny.cfg https://github.com/pjreddie/darknet/blob/master/cfg/yolov3-tiny.cfg?raw=true\n", "!wget https://pjreddie.com/media/files/yolov3-tiny.weights" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import tarfile\n", "\n", "with tarfile.open('yolov3-tiny.tar.gz', mode='w:gz') as archive:\n", " archive.add('yolov3-tiny.cfg')\n", " archive.add('yolov3-tiny.weights')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "darknet_model_path = sess.upload_data('yolov3-tiny.tar.gz', bucket, folder)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note**: When calling ``create_compilation_job()`` user is expected to provide all the correct input shapes required by the model for successful compilation. If we are using a different model, we need to specify the framework and data shape correctly.." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "darknet_model_data_shape = '{\"data\":[1,3,416,416]}'\n", "darknet_model_framework = 'darknet'\n", "target_device = 'jetson_xavier' " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import time\n", "darknet_compilation_job_name = 'Sagemaker-Edge-'+ str(time.time()).split('.')[0]\n", "print('Compilation job for %s started' % darknet_compilation_job_name)\n", "\n", "response = sagemaker_client.create_compilation_job(\n", " CompilationJobName=darknet_compilation_job_name,\n", " RoleArn=role,\n", " InputConfig={\n", " 'S3Uri': darknet_model_path,\n", " 'DataInputConfig': darknet_model_data_shape,\n", " 'Framework': darknet_model_framework.upper()\n", " },\n", " OutputConfig={\n", " 'S3OutputLocation': s3_compilation_output_location,\n", " 'TargetDevice': target_device \n", " },\n", " StoppingCondition={\n", " 'MaxRuntimeInSeconds': 900\n", " }\n", " )\n", "\n", "print(response)\n", "\n", "# Poll every 30 sec\n", "while True:\n", " response = sagemaker_client.describe_compilation_job(CompilationJobName=darknet_compilation_job_name)\n", " if response['CompilationJobStatus'] == 'COMPLETED':\n", " break\n", " elif response['CompilationJobStatus'] == 'FAILED':\n", " raise RuntimeError('Compilation failed')\n", " print('Compiling ...')\n", " time.sleep(30)\n", "print('Done!')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Package Model using Sagemaker Edge Manager\n", "\n", "In this section, we will walk through packaging two models that achieve different goals. One is an Image Classification model (from Keras framework) and another is an Object Detection Model from DarkNet framework. This showcases the versatility of SageMaker Edge Manager." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Package Darknet Model\n", "\n", "Before we can deploy the compiled model to edge devices, we need to package the model with Sagemaker Edge Manager cloud service." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "darknet_packaged_model_name = \"darknet-model\"\n", "darknet_model_version = \"1.0\"\n", "darknet_model_package = '{}-{}.tar.gz'.format(darknet_packaged_model_name, darknet_model_version)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "darknet_packaging_job_name=darknet_compilation_job_name+\"-packaging\"\n", "response = sagemaker_client.create_edge_packaging_job(\n", " RoleArn=role,\n", " OutputConfig={\n", " 'S3OutputLocation': s3_compilation_output_location,\n", " },\n", " ModelName=darknet_packaged_model_name,\n", " ModelVersion=darknet_model_version,\n", " EdgePackagingJobName=darknet_packaging_job_name,\n", " CompilationJobName=darknet_compilation_job_name,\n", ")\n", "\n", "print(response)\n", "\n", "# Poll every 30 sec\n", "while True:\n", " job_status = sagemaker_client.describe_edge_packaging_job(EdgePackagingJobName=darknet_packaging_job_name)\n", " if job_status['EdgePackagingJobStatus'] == 'COMPLETED':\n", " break\n", " elif job_status['EdgePackagingJobStatus'] == 'FAILED':\n", " raise RuntimeError('Edge Packaging failed')\n", " print('Packaging ...')\n", " time.sleep(30)\n", "print('Done!')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "darknet_model_data = job_status[\"ModelArtifact\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Download pretrained Keras model" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import tensorflow as tf\n", "\n", "model = tf.keras.applications.MobileNetV2()\n", "model.save('mobilenet_v2.h5')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import tarfile\n", "\n", "with tarfile.open('mobilenet_v2.tar.gz', mode='w:gz') as archive:\n", " archive.add('mobilenet_v2.h5')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "keras_model_path = sess.upload_data('mobilenet_v2.tar.gz', bucket, folder)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note**: When calling ``create_compilation_job()`` user is expected to provide all the correct input shapes required by the model for successful compilation. If we are using a different model, we need to specify the framework and data shape correctly.." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "keras_model_data_shape = '{\"input_1\":[1,3,224,224]}'\n", "keras_model_framework = 'keras'\n", "target_device = 'jetson_xavier'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import time\n", "keras_compilation_job_name = 'Sagemaker-Edge-'+ str(time.time()).split('.')[0]\n", "print('Compilation job for %s started' % keras_compilation_job_name)\n", "\n", "response = sagemaker_client.create_compilation_job(\n", " CompilationJobName=keras_compilation_job_name,\n", " RoleArn=role,\n", " InputConfig={\n", " 'S3Uri': keras_model_path,\n", " 'DataInputConfig': keras_model_data_shape,\n", " 'Framework': keras_model_framework.upper()\n", " },\n", " OutputConfig={\n", " 'S3OutputLocation': s3_compilation_output_location,\n", " 'TargetDevice': target_device \n", " },\n", " StoppingCondition={\n", " 'MaxRuntimeInSeconds': 900\n", " }\n", " )\n", "\n", "print(response)\n", "\n", "# Poll every 30 sec\n", "while True:\n", " response = sagemaker_client.describe_compilation_job(CompilationJobName=keras_compilation_job_name)\n", " if response['CompilationJobStatus'] == 'COMPLETED':\n", " break\n", " elif response['CompilationJobStatus'] == 'FAILED':\n", " raise RuntimeError('Compilation failed')\n", " print('Compiling ...')\n", " time.sleep(30)\n", "print('Done!')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Package Keras Model" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "keras_packaged_model_name = \"keras-model\"\n", "keras_model_version = \"1.0\"\n", "keras_model_package = '{}-{}.tar.gz'.format(keras_packaged_model_name, keras_model_version)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "keras_packaging_job_name=keras_compilation_job_name+\"-packaging\"\n", "response = sagemaker_client.create_edge_packaging_job(\n", " RoleArn=role,\n", " OutputConfig={\n", " 'S3OutputLocation': s3_compilation_output_location,\n", " },\n", " ModelName=keras_packaged_model_name,\n", " ModelVersion=keras_model_version,\n", " EdgePackagingJobName=keras_packaging_job_name,\n", " CompilationJobName=keras_compilation_job_name,\n", ")\n", "\n", "print(response)\n", "\n", "# Poll every 30 sec\n", "while True:\n", " job_status = sagemaker_client.describe_edge_packaging_job(EdgePackagingJobName=keras_packaging_job_name)\n", " if job_status['EdgePackagingJobStatus'] == 'COMPLETED':\n", " break\n", " elif job_status['EdgePackagingJobStatus'] == 'FAILED':\n", " raise RuntimeError('Edge Packaging failed')\n", " print('Packaging ...')\n", " time.sleep(30)\n", "print('Done!')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "keras_model_data = job_status[\"ModelArtifact\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create AWS IoT thing\n", "\n", "SageMaker Edge Manager uses AWS IoT core to authenticate the device so we can make calls to SageMaker Edge Manager endpoints in AWS Cloud. \n", "\n", "In order for an Edge device AWS to use AWS services, it is necessary for it to first authenticate. We recommend doing this via AWS IoT based authentication, for more details refer [here](https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html) and [here](https://aws.amazon.com/blogs/security/how-to-eliminate-the-need-for-hardcoded-aws-credentials-in-devices-by-using-the-aws-iot-credentials-provider/)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "iot_client = boto3.client('iot', region_name=region)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\n", "#You can use an existing IoT Thing and Type, OR even create a new one.\n", "iot_thing_name = '<>'\n", "iot_thing_type = '<>' #example:'SagemakerEdge'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "iot_client.create_thing_type(\n", " thingTypeName=iot_thing_type\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "iot_client.create_thing(\n", " thingName=iot_thing_name,\n", " thingTypeName=iot_thing_type\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create Device Fleet" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Create IAM role for device fleet" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Configure an IAM role in your AWS account that will be assumed by the credentials provider on behalf of the devices in your device fleet. \n", "\n", "**Notice**: The Name of the role must start with `SageMaker`.\n", "\n", "Go to [IAM console](https://console.aws.amazon.com/iam), create role for IoT, attach the following policies:\n", "\n", "- AmazonSageMakerEdgeDeviceFleetPolicy\n", "\n", "Add the statement to trust relationship:\n", "```\n", "{\n", " \"Version\": \"2012-10-17\",\n", " \"Statement\": [\n", " {\n", " \"Effect\": \"Allow\",\n", " \"Principal\": {\"Service\": \"credentials.iot.amazonaws.com\"},\n", " \"Action\": \"sts:AssumeRole\"\n", " },\n", " {\n", " \"Effect\": \"Allow\",\n", " \"Principal\": {\"Service\": \"sagemaker.amazonaws.com\"},\n", " \"Action\": \"sts:AssumeRole\"\n", " }\n", " ]\n", "}\n", "```\n", "\n", "Note down the role ARN, it will be later used for creating the device fleet." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "device_fleet_name =\"<>\" + str(time.time()).split('.')[0]\n", "role_name=\"AmazonSageMaker-ExecutionRole-20201120T163244\"\n", "\n", "sagemaker_client.create_device_fleet(\n", " DeviceFleetName=device_fleet_name,\n", " RoleArn=\"<>\",\n", " #Example: \"arn:aws:iam::ACCOUNT_ID:role/service-role/AmazonSageMaker-ExecutionRole-2021XXXXXXXXXXXX\",\n", " OutputConfig={\n", " 'S3OutputLocation': s3_compilation_output_location\n", " }\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Register device to the fleet" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "device_name = \"sagemaker-edge-demo-device\" + str(time.time()).split('.')[0] # device name should be 36 charactors\n", "#example > device_name = \"sagemaker-edge-demo-device-012345678\"\n", "\n", "sagemaker_client.register_devices(\n", " DeviceFleetName=device_fleet_name,\n", " Devices=[\n", " { \n", " \"DeviceName\": device_name,\n", " \"IotThingName\": iot_thing_name,\n", " \"Description\": \"this is a sample virtual device\"\n", " }\n", " ]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create and register client certificate with AWS IoT" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create private key, public key, and X.509 certificate files and registers and activates the certificate with AWS IoT. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Create a new cert and register if you dont have an existing one already.\n", "iot_cert = iot_client.create_keys_and_certificate(\n", " setAsActive=True\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Save the files and upload to S3 bucket, these files will be used to provide credentials on device to communicate with aws services." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('./iot.pem.crt', 'w') as f:\n", " for line in iot_cert['certificatePem'].split('\\n'):\n", " f.write(line)\n", " f.write('\\n')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('./iot_key.pem.key', 'w') as f:\n", " for line in iot_cert['keyPair']['PrivateKey'].split('\\n'):\n", " f.write(line)\n", " f.write('\\n')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('./iot_key_pair.pem.key', 'w') as f:\n", " for line in iot_cert['keyPair']['PublicKey'].split('\\n'):\n", " f.write(line)\n", " f.write('\\n')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Associate the role alias generated from `create_device_fleet()` with AWS IoT." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "role_alias_name = 'SageMakerEdge-' + device_fleet_name\n", "\n", "role_alias = iot_client.describe_role_alias(\n", " roleAlias=role_alias_name\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We created and registered a certificate with AWS IoT earlier for successful authentication of your device. Now, we need to create and attach a policy to the certificate to authorize the request for the security token." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "alias_policy = {\n", " \"Version\": \"2012-10-17\",\n", " \"Statement\": {\n", " \"Effect\": \"Allow\",\n", " \"Action\": \"iot:AssumeRoleWithCertificate\",\n", " \"Resource\": role_alias['roleAliasDescription']['roleAliasArn']\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "policy_name = 'aliaspolicy-'+ str(time.time()).split('.')[0]\n", "aliaspolicy = iot_client.create_policy(\n", " policyName=policy_name,\n", " policyDocument=json.dumps(alias_policy),\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "iot_client.attach_policy(\n", " policyName=policy_name,\n", " target=iot_cert['certificateArn']\n", " #example > target=\"arn:aws:iot:us-west-2:ACCOUNTID:cert/dXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Obtain your AWS account-specific endpoint for the credentials provider." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "iot_endpoint = iot_client.describe_endpoint(\n", " endpointType='iot:CredentialProvider'\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "endpoint = \"https://{}/role-aliases/{}/credentials\".format(iot_endpoint['endpointAddress'], role_alias_name)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(endpoint)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Get offical Amazon Root CA file and upload to S3 bucket. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!wget https://www.amazontrust.com/repository/AmazonRootCA1.pem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use the endpoint to make an HTTPS request to the credentials provider to return a security token. The following example command uses curl, but you can use any HTTP client.\n", "\n", "**Optional: verify the credentials.**\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!curl --cert iot.pem.crt --key iot_key.pem.key --cacert AmazonRootCA1.pem $endpoint" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the certificate can be verified with the endpoint without error, upload certificate files to S3 bucket.\n", "\n", "These files will be used in the [Setup Sagemaker Edge Manager Agent](#Setup-Sagemaker-Edge-Manager-Agent) section on EC2/device as Credential Provider." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "root_ca_path = sess.upload_data('AmazonRootCA1.pem', bucket, iot_folder)\n", "device_cert_path = sess.upload_data('iot.pem.crt', bucket, iot_folder)\n", "device_key_path = sess.upload_data('iot_key.pem.key', bucket, iot_folder)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Inference on Edge" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now you can move on to setting up Greengrass V2 Components to deploy the Neo models, Sagemaker Edge Manager Agent, Sagemaker Edge Manager Client Example(CLI, C++ or Python), and the business/inference logic in a greengrass Lambda functions. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Print the locations of the Artifacts\n", "print(darknet_img_path)\n", "print(darknet_model_data)\n", "print(darknet_model_package)\n", "print(keras_img_path)\n", "print(keras_model_data)\n", "print(keras_model_package)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Note the variable names that will be needed below when running the bash scripts\n", "print(role_name, role_alias_name)\n", "print(device_name,device_fleet_name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now you have certificates, packaged model, and sagemaker edge config that you can use on the edge device. You can use the bash scripts under the root directory to install Greengrass v2, create custom components in Greengrass v2 and deploy them to the edge device. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Open a terminal, go to the parent directory of this repo, and run the following:\n", "\n", "```\n", "export AWS_PROFILE=\n", "export AWS_REGION=\n", "export PLATFORM=linux-armv8\n", "export SSH_USER=\n", "export SSH_HOST=\n", "export IOT_THING_NAME=\n", "export BUCKET_NAME=\n", "export ROLE_NAME=\n", "export ROLE_ALIAS=\n", "```\n", "\n", "Make the scripts executable\n", "\n", "```\n", "chmod +x ./scripts/*.sh\n", "```\n", "\n", "Install GGv2 on the Edge device using SSH\n", "\n", "``` \n", "./scripts/install-ggv2-ssh-existing-role.sh $AWS_PROFILE $SSH_USER $SSH_HOST $AWS_REGION $IOT_THING_NAME $ROLE_NAME $ROLE_ALIAS \n", "```\n", "\n", "Download Edge Manager Agent Binary onto the device\n", "```\n", "./scripts/download_edge_manager_package.sh $AWS_PROFILE $PLATFORM\n", "```\n", "\n", "Add Agent Artifacts to artifacts folder\n", "```\n", "./scripts/add_agent_artifact.sh $AWS_PROFILE $PLATFORM 0.1.0 $AWS_REGION\n", "```\n", "\n", "Create a Python Stub of the SageMaker Edge Manager Agent\n", "```\n", "pip install grpcio-tools\n", "pip install --upgrade protobuf\n", "```\n", "\n", "Compile and Add the Python artifacts\n", "```\n", "./scripts/compile_add_python_stub_artifacts.sh $PLATFORM aws.sagemaker.edgeManagerPythonClient 0.1.0\n", "```\n", "\n", "Update recipes\n", "\n", "- In all of the recipe files, replace YOUR_BUCKET_NAME with the value assigned to $BUCKET_NAME\n", "\n", "- In components/recipe/aws.sagemaker.edgeManager-0.1.0.yaml, update the endpoint with your region and account number:\n", "\n", "```\n", "endpoint: arn:aws:iot:::rolealias/\n", "```\n", "\n", "- In components/recipe/aws.sagemaker.edgeManager-0.1.0.yaml, update the URI with your region:\n", "```\n", "URI: s3://YOUR_BUCKET_NAME/artifacts/aws.sagemaker.edgeManager/0.1.0/.pem\n", "```\n", "\n", "- In components/recipe/aws.sagemaker.edgeManager-0.1.0.yaml, make sure the device fleet name and device name are correct:\n", "```\n", " DefaultConfiguration:\n", " deviceName: \n", " deviceFleetName: \n", "```\n", "\n", "\n", "Upload your custom components to S3 bucket\n", "```\n", "./scripts/upload_component_version.sh $AWS_PROFILE com.model.darknet 0.1.0 $BUCKET_NAME $AWS_REGION\n", "./scripts/upload_component_version.sh $AWS_PROFILE aws.sagemaker.edgeManager 0.1.0 $BUCKET_NAME $AWS_REGION \n", "./scripts/upload_component_version.sh $AWS_PROFILE aws.sagemaker.edgeManagerPythonClient 0.1.0 $BUCKET_NAME $AWS_REGION\n", "```\n", "\n", "Create a new Greengrass v2 deployment, including the following components:\n", "\n", "- com.model.darknet v0.1.0\n", "- aws.sagemaker.edgeManager v0.1.0\n", "- aws.sagemaker.edgeManagerPythonClient v0.1.0 OR any other custom Lambda function that you create. See *greengrass_lambda.py* for example application that takes in Camera stream as input and runs inference using the PythonClient.\n", "\n", "\n", "\n", " " ] } ], "metadata": { "instance_type": "ml.t3.medium", "kernelspec": { "display_name": "Python 3 (TensorFlow 2.1 Python 3.6 CPU Optimized)", "language": "python", "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-west-2:236514542706:image/tensorflow-2.1-cpu-py36" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.9" } }, "nbformat": 4, "nbformat_minor": 4 }