Deploy the next-gen of AI Apps using Streamlit

Priyansi
GDSC KIIT
Published in
6 min readNov 9, 2020

--

What if you could create a web app to showcase how well your model performs without going through the holy trinity of HTML/CSS/JS? Want to build a minimalistic yet sleek UI for your data app that doesn’t require weeks of web dev knowledge?

Behold Streamlit, an open-source library, build on Python scripts and customizable widgets that can get a web app up and running for your AI projects in mere hours. Below are the steps + the code to help you ease into Streamlit along with a few Easter eggs :)

First, we install Streamlit (Version 0.70.0 minimum) and check if it’s properly installed via -

$ pip3 install streamlit
$ streamlit hello

This will greet you with a web page as follows at http://localhost:8501/ -

The default landing page

Simple yet beautiful, let’s see how we can convert this to create a handwritten letters classifier app with a drawable canvas and then deploy it on Heroku.

The final product

Before we begin, we need to install another component, a Streamlit — Drawable Canvas (Version 0.5.1 minimum) via-

$ pip3 install streamlit-drawable-canvas

Now, make a directory for our web app

$ md letters-classifier-streamlit
$ cd letters-classifier-streamlit

And create a file called app.py in which we’ll write our Streamlit code.

Run streamlit run app.py in a separate terminal to see our app in action while we make changes in the source code.

Let’s make a few imports in app.py

import streamlit as st
from streamlit_drawable_canvas import st_canvas

Hit Ctrl+S and you’ll notice that a change has been detected by Streamlit in your source code at the top right of your page.

To enable Hot Reload, click on Always rerun.

From this
To this

You’ll also notice that the name of your app is set to the name of your Python file. Let’s change that and add an icon to our page by setting the configuration of the page -

st.set_page_config(
page_title = "Handwritten Letters Classifier",
page_icon = ":pencil:",
)

There is also a hamburger menu at the top right with a few options like Streamlit docs and a text at the bottom left of your page that says Made with Streamlit. If you wish to hide that, just write -

hide_streamlit_style = """            
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style>
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True)

With a clear web page, now, let’s begin to build our app. We need a title for the page and it’s as simple as -

st.title("Handwritten Letters Classifier")

By default, this title is left aligned. However, if you wish to customize this, you can always use st.markdown. And if you want to include some CSS, add the unsafe_allow_html=True tag in st.markdown() to become invincible, like this -

st.markdown("<h1 style='text-align: center;'>Handwritten Letters Classifier</h1>", unsafe_allow_html=True)

Now we want to let the user draw something on a canvas whose image will be fed into a model and the result will be predicted. Let’s start by drawing a canvas.

canvas_result = st_canvas(
stroke_width = 25,
stroke_color = "#fff",
background_color = "#000",
height = 280,
width = 280,
drawing_mode = "freedraw",
key = "canvas",
)

If you want to tweak the parameters, take a look at the documentation — https://github.com/andfanilo/streamlit-drawable-canvas

You can even add a sidebar, so let’s do that and let the user vary the stroke width in that. Do the following change in st_canvas

stroke_width = st.sidebar.slider("Stroke width: ", 1, 100, 25)

Draw something on the canvas and test it out. Then add a Predict button.

predict = st.button("Predict")

We use canvas_result.image_data as follows to retrieve the image from the canvas only when it isn’t empty and the user has clicked the Predict button to feed the image into the model and obtain a prediction.

def get_prediction(image):
# get the prediction from your model and return it
if canvas_result.image_data is not None and predict:
prediction = get_prediction(canvas_result.image_data)
st.text("Prediction : {}".format(prediction))
When your model predicts correctly :”)

Let’s put a progress bar just before predicting and some balloon animation after it to indicate your model’s done predicting.

if canvas_result.image_data is not None and predict:    progress_bar = st.progress(0)
for i in range(100):
progress_bar.progress(i + 1)
time.sleep(0.01)
prediction = get_prediction(canvas_result.image_data)
st.text("Prediction : {}".format(prediction))
st.balloons()
Streamlit : Making data apps fun since 2018

You can even add a bar graph like this (refer here for code) to show the probability distribution of different predictions.

The probability distribution of different letters from a-z

If you’re interested in what else can be achieved through these simple tools, along with their source code, visit https://awesome-streamlit.org/ and navigate to Gallery, then Select an App.

Now it’s time to deploy this model on Heroku. For this, you need their CLI. Follow the instructions in https://devcenter.heroku.com/articles/heroku-cli, to get started. If on Linux, simply use snap-

$ sudo snap install --classic heroku
$ heroku --version

You internal directory structure should now look like this -

.
├── app
│ ├── app.py
│ ├── model.pth
│ └── utils.py
├── Procfile
├── requirements.txt
├── runtime.txt
└── setup.sh

app.py contains our Streamlit code, utils.py and model.pth contains functions and model weights to predict the output. The Procfile specifying the commands required by the app during execution will look like this -

web: sh setup.sh && streamlit run app/app.py

For requirements.txt, in your terminal, run pip freeze > requirements.txt, and a text file will be generated. Try working on a virtual environment to manage your dependencies better. Look at this -

runtime.txt specifies the current version of Python that you’re using which can be found out by running python --version. Here’s what my runtime.txt looks like -

python-3.7.2

And finally, here’s what your setup.sh will look like -

mkdir -p ~/.streamlit/echo "\
[general]\n\
email = \"youremail@domain.com\"\n\
" > ~/.streamlit/credentials.toml
echo "\
[server]\n\
headless = true\n\
enableCORS=false\n\
port = $PORT\n\
" > ~/.streamlit/config.toml

Just replace youremail@domain.com with your Heroku email address.

Then log in and enter your credentials-

$ heroku login -i

Before creating a new app, make sure you have initialized a local Git repository and committed your application code to it. Create a new app and replace your-app-name with it -

$ heroku create your-app-name

Confirm that an app has been created with git remote -v and you should get an output like -

heroku  https://git.heroku.com/your-app-name.git (fetch)       
heroku https://git.heroku.com/your-app-name.git (push)

Then simply, push the app to Heroku remote -

$ git push heroku master
Web app deployed yay!

And you’re done. The entire code can be found here.

A meme. Enjoy. Courtesy of https://medium.com/@biswaroop08.

Refer to the docs for more features or try out Streamlit Nightly to keep up-to-date with the most recent Streamlit version as it is an ever-growing community and major features get added left and right.

Finally, if you want to stan over Streamlit, DM me on Twitter :D

--

--

Priyansi
GDSC KIIT

Loves programming languages as well as natural ones