DEV Community

Cover image for Deploy a Machine Learning Model as a Web App with Anvil and Deepnote
Meredydd Luff
Meredydd Luff

Posted on

Deploy a Machine Learning Model as a Web App with Anvil and Deepnote

Prefer watching to reading? This tutorial is also on YouTube:

Deploying Data Science with nothing but Python

Deepnote is a seriously slick Python notebook, hosted in the cloud, with incredible real-time collaboration. It's great for working with other data scientists. But what happens when you want to share your project with non-programmers? They need an easy-to-use interface -- so you need to deploy what you've built.

Anvil lets you build full-featured web apps entirely in Python (no HTML or JS required) -- and you can connect it to external notebooks.

Follow along as we use Deepnote and Anvil to deploy a machine learning model as a web app -- a web app anyone can use!

The app we're going to build
We're going to build this app -- and it's going to be easy!


Step 0 - Get the notebook

In this example, we're going to start with an image classifier that can tell the difference between cats and dogs. Believe it or not, getting this notebook running in the cloud is the easy part! Just open the notebook in Deepnote and click Duplicate:

Open the notebook >>

Deepnote screenshot
Click “Duplicate” to make a copy of this notebook in your own (free) Deepnote account.

All right, we have a notebook. Let's deploy it as a web app!


Step 1 - Create your Anvil app

Creating web apps with Anvil is simple. No need to wrestle with HTML, CSS, JavaScript or PHP -- we can do everything in Python.

Log in to Anvil and click 'New Blank App'. Choose the Material Design theme.

Location of the Create App button

First, name the app. Click on the name at the top of the screen and give it a name:

Rename your app by clicking on the title

Step 2 - Add your components

We construct the UI by dragging-and-dropping components from the Toolbox. Drop a Card and a FileLoader. The FileLoader will let users upload the image they want classified.

Next, add an Image component, which will display the input image, and a Label to display the returned classification.

Anvil Drag and Drop demo

Select the Label we just added and, in the components properties, change the name to 'results_lbl'. Then add a spacer component above the label to centre the label against the image.

Now we have a user interface, let's connect our app to the code in our Jupyter notebook.


Step 3 - Enable the Uplink

From the IDE, let's enable the Uplink. Open the Gear menu in the top left of the IDE, then select Uplink and then Enable the Anvil Server Uplink.

Enable the Uplink via the gear at the top of the left panel

This will then give us an Uplink key we can use in our Deepnote notebook.

Now let's install the Uplink in our Deepnote environment, and connect our script using the key we just created.


Step 4 - Install the Uplink Library in our Deepnote notebook

It's time to connect our notebook to Anvil!

The first thing we need to do is install the anvil-uplink library. Let's add !pip install anvil-uplink to our notebook:

!pip install anvil-uplink
Enter fullscreen mode Exit fullscreen mode

The ! operator tells our notebook that this line is a command line script and not Python code.


Step 5 - Connecting our Script

Now that the Uplink library will be installed when we start our notebook, we can connect our notebook in the same way as any other Uplink script.

Start by importing the anvil.server module:

import anvil.server
Enter fullscreen mode Exit fullscreen mode

Then connect to the Uplink:

anvil.server.connect("your-uplink-key")
Enter fullscreen mode Exit fullscreen mode

Replace "your-uplink-key" with the Uplink key from your app.

Run the cell. You should see output like this:

Connecting to wss://anvil.works/uplink
Anvil websocket open
Authenticated OK
Enter fullscreen mode Exit fullscreen mode

That's it! When we run our notebook, it will now connect to our web app via the Uplink. Next, let's create a function we can call from our Anvil app.


Step 6 - Creating a callable function

In a new cell, let's define a function we can call from our app to classify an image. We'll call it classify_image, and decorate it with @anvil.server.callable so we can call it from the web.

The image will be passed to our classify_image function as an Anvil media object. We'll write it to a temporary file and load it into it into Pillow.

Our notebook already has a function, get_prediction(), for putting the Pillow image through the classifier. We'll call that function and return the results in two parts: the numerical score, and then the classification. We'll say anything scoring less than 0.5 is a 'dog', and anything else is a 'cat'.

Here is how our finished cell should look:

import anvil.media

@anvil.server.callable
def classify_image(file):
  with anvil.media.TempFile(file) as f:
    img = load_img(f)

  score = get_prediction(img)

  return score, 'dog' if score < 0.5 else 'cat'
Enter fullscreen mode Exit fullscreen mode

Our notebook is now ready to classify images! Let's go back into our Anvil app and call that classify_image function when someone uploads an image.


Step 7 - Calling notebook functions from the web

In the design view of our Anvil app, double click the FileLoader component we added earlier. It will take us to the code view and add a function that runs whenever a file is uploaded.

Adding a FileLoader change event

In the function, type anvil.server.callable() and pass it the name of our notebook function 'classify_image'. Then pass it the uploaded file as the argument to our notebook function. (Anvil will take care of transmitting the data.)

We can then create two variables, score and cls, and set them to the two values returned by classify_image:

Calling the server


Step 8 - Displaying our classification

We've got the results -- it's time to show them on the screen!

Still in our file_loader_1_change function, let's display the classification as text on our Label, and display the uploaded image on the Image component.

We set the text of results_lbl to include both the classification and the score returned by our model:

self.results_lbl.text = f"{cls} ({score:.1f})"
Enter fullscreen mode Exit fullscreen mode

Then set the source of image_1 to the uploaded file:

self.image_1.source = file
Enter fullscreen mode Exit fullscreen mode

The finished function will look like this:

def file_loader_1_change(self, file, **event_args):
    """This method is called when a new file is loaded into this FileLoader"""
    score, classification = anvil.server.call('classify_image', file)

    self.result_lbl.text = f"{classification} ({score})"
    self.image_1.source = file
Enter fullscreen mode Exit fullscreen mode

We now have an app that takes an image, sends it to our Deepnote notebook, classifies it and returns the results to our app. It's all in the cloud, and all in Python!

All we need to do now is deploy our app to the internet for everyone to use.


Step 9 - Publishing our app

From the IDE, open the Gear menu in the top left of the IDE, then select Publish app and then Share via public link. Choose a URL and click "Apply":

Publish your app

That's it -- we've deployed a machine learning model as a web app, with Deepnote hosting the notebook and Anvil hosting the web app. Best of all, we didn't need anything but Python!


Clone the App

You can open the source code for the finished Anvil app here:

Clone the finished Anvil app >>

And you can duplicate our Deepnote notebook from the link below:

Open the finished notebook >>


New to Anvil?

If you haven't seen it before, Anvil makes web development accessible: Build fully featured webs apps painlessly, without JavaScript, HTML or CSS - just Python.

The runtime platform is open source, and the online IDE is free, so you can try it out at https://anvil.works.

Top comments (0)