Deploy the next-gen of AI Apps using Streamlit
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/
-
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.
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.
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 itif canvas_result.image_data is not None and predict:
prediction = get_prediction(canvas_result.image_data)
st.text("Prediction : {}".format(prediction))
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()
You can even add a bar graph like this (refer here for code) to show the probability distribution of different predictions.
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.tomlecho "\
[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
And you’re done. The entire code can be found here.
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