A web API for our spam classifier

Building and deploying a spam classifier (Part 2): Setting up a web API for our classifier

In the previous post, we created a classifier that predicts wether an input message is spam or not. We also saved our classifier to a file. In this post, we’ll use the flask library to develop a simple web API for our classifier.

To begin, let’s copy our saved classifier to a new folder

mkdir web-api
cp text-classifier.pkl web-api
cd web-api 

Next, we’ll create a python module that sets up a Flask application around our classifier. Flask is an amazing python microwebframework. No kidding about the ‘micro’ part. You can actually build a whole web application using only a single python file with Flask. Let’s create our app file.

app.py

from flask import Flask, jsonify, request
from sklearn.externals import joblib

app = Flask(__name__)

spam_classifier = None

with open('text-classifier.pkl', 'rb') as model_file:
    spam_classifier = joblib.load(model_file) 


@app.route('/predict', methods = ['POST','GET'])
def predict():
    global spam_classifier
    
    if request.method == 'POST':
        try:
            data = request.get_json()
            print('Request info: ',data)
            message = str(data['message'])
            result = spam_classifier.predict([message]).tolist()
            return jsonify(result);
        except ValueError as e:
            print(e)
            return jsonify("Please enter a message.")
        

if __name__ == "__main__":
    app.run()

This is a simple flask application with a single route: /predict that acccepts the POST and GET HTTP requests. When either of these requests comes in, it unpacks the request parameters and extracts the message parameter value.

message = str(data[‘message’])

Next, we pass the value to the classifier

result = spam_classifier.predict([message]).tolist()

and convert the result to a JSON formatted response.

return jsonify(result);

Running and testing

To run and test this code, Launch a shell in the app folder and run:

python app.py

photo 1

Looks like its up. To test it lets send a request to the predict endpoint. I like to use httpie but you can use curl or any other HTTP client.

 http POST http://127.0.0.1:5000/predict message='where is the garbage can?'

We get a response:

photo 2

http POST http://127.0.0.1:5000/predict message='a chance to win cash' 

photo 3

Looks like our API is working. Sweet!

Running in production and scaling up.

Now we’re finally ready to deploy this API to the web but we should not just run python app.py on our server. This method uses the built-in flask web server which is not very suitable for production as it does not scale very well. Thing is, we should deploy our app using a WSGI-enabled web server. In this post, I’ll use gunicorn which is a fairly lightweight HTTP server for python. Let’s get it installed:

pip install gunicorn

Once this command completes, we should have it installed in our python environment, Next let’s create a shell script in our app folder to launch our app.

start.sh

gunicorn -w 5 -b 127.0.0.1:5000 app:app 

Let’s make this script runnable and execute it.

chmod +x start.sh
./start.sh

photo 4

This command starts our app in the gunicorn server on port 5000 with five worker processes. We can go ahead and test our app again to make sure everything’s nice and dandy.

http POST http://127.0.0.1:5000/predict message='sugar, spice and everything nice'

photo 5

Looks good. Now we can send cheesy http requests to this web API as much as we want.

Thanks for reading!

Published 6 Jan 2019

A software developer that's passionate about Javascript, Python and Java. When I'm not coding, I love to listen to hip hop music and read science fiction books.
Kuro Souza on Twitter