APIs from Python models with Flask

Let’s assume you have written this complex classifier that you now want to deploy behind an API:

class CatVsDogPersonClassifier(object):
    def predict(self, first_name, last_name):
        """Determine whether someone is a cat or a dog person."""
        if last_name in {'Schrodinger', 'Schrödinger', 'Schroedinger'}:
            return 'cat'
        else:
            return 'dog'

In order to quickly deploy this, let’s wrap this in a Flask application. Flask is a popular lightweight Python library for writing APIs.

Save the following in a file called app.py in the root of your project:

# coding: utf-8

import logging

from flask import Flask, jsonify, request, abort, make_response

logging.basicConfig(level=logging.INFO)

flask_server = Flask(__name__)

PORT = 8000

class CatVsDogPersonClassifier(object):
    def predict(self, first_name, last_name):
        """Determine whether someone is a cat or a dog person."""
        if last_name in {'Schrodinger', 'Schrödinger', 'Schroedinger'}:
            return 'cat'
        else:
            return 'dog'

classifier = CatVsDogPersonClassifier()

def _parse_request_body():
    """Extract first and last name from request."""
    request_body = request.get_json(force=True)
    try:
        first_name = request_body['firstName']
        last_name = request_body['lastName']
    except KeyError:
        # Missing first or last name fields.
        logging.info('Badly formatted request body: {}'.format(request_body))
        response_body = {
            'error': "Missing 'firstName' or 'lastName' key in request body"
        }
        response = make_response(jsonify(response_body), 400)
        abort(response)
    return first_name, last_name

@flask_server.route('/predict', methods=['POST'])
def predict():
    """Respond to requests for a prediction."""
    first_name, last_name = _parse_request_body()
    person_type = classifier.predict(first_name, last_name)
    logging.info('Predicted that {} {} is a {} person'.format(
        first_name, last_name, person_type))
    return jsonify({"mostLikely": person_type})

if __name__ == '__main__':
    logging.info('Listening on port {}'.format(PORT))
    flask_server.run(debug=True, host='127.0.0.1', port=PORT)

We can now create our API. Go to the APIs page for your project in SherlockML and create a new API. You will be asked to choose a name, a domain name and a type for your API. For type, choose Flask (Python). Your domain name needs to be unique across all of SherlockML. I suggest a domain name like cats-vs-dogs-2118, where you replace 2118 with a random string of your choice. In the API settings page, change the working directory to /project, the python module to app (the name of your python script), and the python object to flask_server (the name of the flask object defined in our script). You can leave the environments dropdown empty.

../../../_images/flask-api-configure-screen.png

After you have your API set up, you can test and ultimately deploy it. Head to Test your API to find out how to go about the testing process.

Once you are familiar with the API development process, you may want to write a more complex API. Take a look at these examples below for inspiration: