in lambda-function/src/controllers/sagemakerController.js [4:155]
function sagemakerController() {
/**
* Accepts an image as base64 and posts it to the selected Amazon Sagemaker Endpoint for inference.
* Response object includes a response var with predictions including class type, confidence and location image.
*
* @param {*} req
* @param {*} res
*/
async function postInference(req, res) {
let response = {};
try {
let body = req.body;
let endpoint = body.endpoint;
let region = body.region;
let imageBase64 = body.imageBase64;
//================================================
// Validate the user inputs:
// Test an image was provided in call.
if (imageBase64 === undefined || imageBase64.length < 1) {
throw new Error('No Image data was provided in inference call.');
};
// Test an Endpoint was entered.
if (endpoint === undefined || endpoint.length < 1) {
throw new Error('No Sagemaker Inference Endpoint was provided.');
} else {
// remove any spaces that can happen from copy and paste
endpoint = endpoint.replace(/ /g, '');
};
// Test if an AWS Region was entered.
if (region === undefined || region.length < 1) {
throw new Error('No AWS Region was provided.');
};
//================================================
// Convert base64 image to file (blob) for sagemaker.
// Get the MIME type of the base64 image received
let mimeType = imageBase64.match(/[^:]\w+\/[\w-+\d.]+(?=;|,)/)[0];
// Pop the base64 image data to local variable.
let imageData = imageBase64.split(';base64,').pop();
// Write to local file as image
await fsp.writeFile('/tmp/image', imageData, { encoding: 'base64' });
// Get the file handle.
let imageFile = await fsp.readFile('/tmp/image');
// Init the AWS client.
var sageMakerRuntime = new AWS.SageMakerRuntime({
apiVersion: '2017-05-13',
region: region
});
// Create the param to send to Sagemaker.
var params = {
Body: imageFile,
EndpointName: endpoint,
Accept: 'application/json',
ContentType: mimeType
};
// Send the image to Sagemaker endpoint for inference and parse result.
let data = await sageMakerRuntime.invokeEndpoint(params).promise();
let result = String.fromCharCode.apply(null, data.Body);
let predictions = JSON.parse(result).prediction;
// Build the success response object with inference predictions.
response.status = 'success';
response.statusCode = 200;
response.predictions = predictions;
} catch (err) {
response.status = 'error';
response.statusCode = 500;
response.error_message = err.message;
response.error_trace = err.stack;
console.log(response);
} finally {
res.json(response);
}
}
/**
* Requests againt the Amazon Sagamaker API to get a list of InService Endpoints that an image can be
* sent for inference. Assumes the Endpoints have an object-detection model loaded.
*
* @param {*} req
* @param {*} res
*/
async function postEndpoints(req, res) {
let response = {};
try {
let body = req.body;
let region = body.region;
//================================================
// Validate the user inputs:
// Test if an AWS Region was entered.
if (region === undefined || region.length < 1) {
throw new Error('No AWS Region was provided.');
};
// Init the AWS client.
var sagemaker = new AWS.SageMaker({
apiVersion: '2017-07-24',
region: region
});
// Create the param to send to Sagemaker.
var params = {
SortBy: "Name",
SortOrder: "Descending",
StatusEquals: "InService"
};
// Make the requst to Sagemaker API and parse result.
let data = await sagemaker.listEndpoints(params).promise();
console.log(data);
let endpoints = data.Endpoints;
// Build the success response object with Sagemaker Endpoints meeting the Status='InService' filter.
response.status = 'success';
response.statusCode = 200;
response.result = endpoints;
} catch (err) {
response.status = 'error';
response.statusCode = 500;
response.error_message = err.message;
response.error_trace = err.stack;
console.log(response);
} finally {
res.json(response);
}
}
return { postInference, postEndpoints };
}