Understanding Full-Stack Data Science: How the NLP model in your Jupyter Notebooks Could Actually Help Stop Disasters, Part 2
By: Bowen Chen
Tags: Continuous Integration, Full Stack, Web Development, Machine Learning, NLP

NATURAL LANGUAGE PROCESSING

Understanding Full-Stack Data Science: How the NLP model in your Jupyter Notebooks Could Actually Help Stop Disasters, Part 2

Photo by Piotr Chrobot on Unsplash

The excitement has begun. I hope you enjoyed part 1 of the series on how to turn your NLP model in jupyter notebooks into production-ready models, where we have successfully automated a series of steps including data acquisition, data processing, model training, model evaluation, and model packaging. That’s all fantastic progress — except we are still far from putting the model in use and actually drive some value. In part 2, we will continue the process of further automating our model development process that will involve building a functional backend and frontend in a docker container, which will be hosted on the platform-as-a-service provider Heroku. At the end of the day, the whole end-to-end project will be fully automated and continuously integrated — any version bumps will simply require merging in a pull request.

What we have so far

In part 1, we have already successfully built a packaged model that is hosted on the PyPI server, and all of the files are in the disaster_messaging_classification_model directory. Remember we had a project structure like the following,

.circleci — required by circleci continuous integration tools, contains the circleci.config file, which is used for automating the model training and deployment workflow

— required by circleci continuous integration tools, contains the file, which is used for automating the model training and deployment workflow disaster_messaging_classification_model — contains the machine learning model package that predicts the incoming messages into its appropriate classes

— contains the machine learning model package that predicts the incoming messages into its appropriate classes disaster_messaging_app — contains the API and the docker file that could serve the trained machine learning model, which will be deployed by circleci

— contains the API and the docker file that could serve the trained machine learning model, which will be deployed by circleci notebooks — contains the exploratory analysis notebooks

We have already looked at the .circleci, disaster_messaging_classification_model, and notebooks directories, now we will start building out the frontend and backend of the disaster response flask app with a docker file, which will be hosted in the disaster_messaging_app directory. We will have a look at the content of this folder in the following section.

Directory Structure

Just as the disaster_messaging_classification_model, we will have another dependency definition file pyproject.toml in the disaster_messaging_app directory. In addition, we will have the following directories.

app — contains the main definitions of the flask app

— contains the main definitions of the flask app logs — auto-generated logs for the flask app

— auto-generated logs for the flask app templates — HTML templates for flask app’s frontend

— HTML templates for flask app’s frontend tests — unit tests for the flask app

— unit tests for the flask app Dockerfile — Container definition that builds the flask app

— Container definition that builds the flask app Makefile — the important automation script that is being used by circleci

— the important automation script that is being used by circleci pyproject.toml — the dependency definition file that is used to generate the dependency lock file (more information here)

— the dependency definition file that is used to generate the dependency lock file (more information here) poetry.lock — the lock file generated from the pyproject.toml file by calling poetry lock

— the lock file generated from the file by calling run.py — script that runs the flask app

— script that runs the flask app run.sh — shell script that runs the run.py file

With the disaster_messaging_app directory sorted out, we are now ready to start building out our flask app. In the next section, we will start by building out the appropriate environment.

Building the environment

Remember we have packaged our machine learning model into a package that’s hosted in the PyPI server? Now it’s time to it put to use. Building a model package as we did in part 1 allows us to install our model as a package dependency when we are trying to productionize the model (just as pandas, numpy, and more). We will again use poetry as the dependency management tool that ensures the versions of all dependencies are locked in place. We will create a new virtual environment completely separate from the environment we built when we were creating the model. This environment will be dedicated to creating our app. We will define the following pyproject.toml in the disaster_messaging_app folder.

Notice that we are installing disaster-message-classification-model as a dependency here. This installation will enable us to use all the modules of our machine learning model defined in part 1. With the environment properly defined, we are now ready to define the main backbones for our web app using flask.

Building the Flask app

To make use of the model’s predictive power, we will need to create an interface that allows the downstream user to interact. Common practices involve either constructing an API or create a presentable web application. Fortunately, either of the goals could be accomplished by using the powerful, lightweight framework flask. More resources about flask could be found here. In our case, we will attempt to create a fully functional web app which will be hosted on Heroku.

Web applications on flask follow the app-controller framework, which involves the creation of an app module that registers and runs the app, and a controller module that controls the routing and internal functionalities of the app. We will have those two modules in the app.py and controller.py files respectively. We will also create a config file that handles the miscellaneous tasks such as creating the logger and sets the routing ports.

The app.py module is really simple, as it only creates the flask object and calls the controller defined in controller.py , which is shown in the following.

The controller.py module defines the routing and internal functionalities of the app. In general, it involves the following 2 steps,

Define a blueprint and save it to a variable name Use the blueprint variable as a decorator, define the routing and the function handling the specific route’s functionality.

For example, suppose we have already defined the blueprint as the following

classification_app = Blueprint(“classification_app”, __name__)

if we want to route to the /index URL, we could define the decorator as the following

@classification_app.route(“/index”)

For our controller, we will define the following 5 routes

index

The main page when the app is first fired up. On the front page, we will show the word cloud of all the frequently mentioned words in our message dataset. The module that generates the Plotly visuals are defined in part 1. The function that defines this route is shown below.

Once the page is loaded up, we will see the app’s front page that looks like the following.