Gradio tutorial (Build machine learning applications)

Kamanda Wycliffe
Kamanda Wycliffe

Table of Contents

You have built your optimally performing machine learning model. What next? This tutorial explores the use of Gradio in building machine learning applications.

What is Gradio?

Gradio is an open-source Python package that allows you to quickly create easy-to-use, customizable UI components for your ML model, any API, or even an arbitrary Python function using a few lines of code. You can integrate the Gradio GUI directly into your Jupyter notebook or share it as a link with anyone.

Gradio installation

Installation of Gradio can be done using PIP from your command prompt or in Google Colab using:

pip install gradio

If you are using a Jupyter Notebook, you can also type the following:

!pip install gradio

How to run Gradio applications

Now that we have Gradio installed in our system, let's begin by demonstrating how to run Gradio applications.

Consider a simple Python application that takes a user's name as input and generates a greetings message for the user:

#!pip install gradio
import gradio as gra
def user_greeting(name):
    return "Hi! " + name + " Welcome to your first Gradio application!😎"
    
#define gradio interface and other parameters
app =  gra.Interface(fn = user_greeting, inputs="text", outputs="text")
app.launch()

Run Gradio applications on command prompt

You can run the application using the command prompt. We will explore all the parameters in the app later on. From your command prompt, run:

gradio app.py

To display the application, open the URL: http://127.0.0.1:7862. This might differ in your case.

You should have something like the output shown below when you execute the above code:

Run Gradio application from Jupyter Notebook

Alternatively, you can run your code in Jupyter Notebook. After creating the Interface, you can run the app by invoking the launch() function using app.launch().

app =  gra.Interface(fn = user_greeting, inputs="text", outputs="text")
#run the app
app.launch()

A new widget will be created.

Gradio Interface class

Gradio Interface is the main high-level class. The Interface class allows you to create the GUI for your functions and ML models.

From the application we defined above, you will notice that the Interface class has three required parameters i.e.,  Interface(fn, inputs, outputs, ...).

Fn is the arbitrary function or ML model wrapped by the Gradio interface. The function accepts at least one parameter and returns one or more values:

  • Inputs - defines the type(s) of the input component. Gradio provides many pre-built components like text, image, or mic. The number of input components needs to match the number of parameters specified in fn. If inputs are set to None, only the output components are shown.
  • Outputs - specifies the type(s) of the output component. Gradio provides many pre-built output components like image, text, or label. The number of output components needs to match the number of values that are output by fn. If outputs are set to None, only the input components are displayed.

For additional parameters and their functions, see Gradio documentation.

In case you have created several interfaces, Gradio provides classes like TabbedInterface, Parallel, and Series for combining interfaces.

For example, building on the welcome application, we can define another arbitrary function that displays what a user would like to do and use TabbedInterface to combine the interfaces.

import gradio as gr

title = "Multiple Interfaces"

#app 1
def user_greeting(name):
    return "Hi! " + name + " Welcome to your first Gradio application!😎"

#app 2
def user_help(do):
    return "So today we will do " + do + "using Gradio. Great choice!"

#interface 1
app1 =  gr.Interface(fn = user_greeting, inputs="text", outputs="text")
#interface 2

app2 =  gr.Interface(fn = user_help, inputs="text", outputs="text")

demo = gr.TabbedInterface([app1, app2], ["Welcome", "What to do"])

demo.launch()

The resulting widget will be:

Gradio components

Gradio contains pre-built components for various functions. These components range from text and media such as audio, images, and video to charts created using packages like Plotly and Altair.

In this section, we will explore how Gradio displays various components.

Displaying text in Gradio

Text can be displayed using gradio.Text or gradio.Textbox.Each method provides a text area to enter string input or display string output.

#display a text
import gradio as gr

def text_display(text):
    return text

demo = gr.Interface(text_display, gr.Text(), "text")
#alternatively use gr.TextBox()
demo.launch()

Displaying data in Gradio

Data types such as "str", "number", "bool", "date", and "markdown" can be displayed in Gradio. By default, you will get a Pandas DataFrame.

You can obtain other data types by specifying the desired output type. For instance, a NumPy array can be obtained when numpy is specified, and array for a Python array.

#display a data
import gradio as gr

def data_display(input_img):
    return input_img

demo = gr.Interface(data_display, gr.Dataframe(), "dataframe")
demo.launch()

Displaying media in Gradio

You can display media such as images in Gradio. Besides, you can transform images by applying a filter such as sepia or blue hue filter. We can display media  by passing the correct input like Image, Video, Audio, or File.

The example below demonstrates how to visualize an image after applying a blue hue filter.

import numpy as np
import gradio as gr

def blue_hue(input_img):
    blue_hue_filter = np.array([
            [0.272, 0.534, 0.131], 
            [0.349, 0.686, 0.168],
            [0.393, 0.769, 0.189]])
    blue_hue_img = input_img.dot(blue_hue_filter.T)
    blue_hue_img /= blue_hue_img.max()
    return blue_hue_img

demo = gr.Interface(blue_hue, gr.Image(shape=(300, 200)), "image")
demo.launch()
Dove: Photo by 卡晨 on Unsplash

Alternatively, you can display video media as follows without any preprocessing:

#display a video
import gradio as gr

def video_display(input_img):
    return input_img

demo = gr.Interface(video_display, gr.Video(), "video")
demo.launch()

Displaying code in Gradio

Use gradio.Textbox to display code.

import gradio as gr
#define your code
#average of a list
code = '''def cal_average(numbers):
    sum_number = 0
    for t in numbers:
        sum_number = sum_number + t           

    average = sum_number / len(numbers)
    return average'''

with gr.Blocks() as demo:
    gr.Textbox(code)
    
demo.launch()

Displaying progress and status in Gradio

We show the progress and status of the pending process by specifying show_progress = True in components that support  change().

For example in gradio.Textbox.change() or gradio.Slider.change().

The status of the underlying process is displayed by specifying the parameter status_tracker in change()

import gradio as gr


def show_text(x):
    return x


demo = gr.Blocks()

with demo:
    gr.Markdown(
        """
    # Show text!
    Start typing below to see the output.
    """
    )
    input = gr.Textbox(placeholder="Flip this text")
    output = gr.Textbox()

    input.change(fn=show_text, inputs=input, outputs=output, show_progress = True, status_tracker = None)

demo.launch()

In the application above, using show_progress = False yields the following output:

Displaying charts in Gradio

Chart elements are displayed in Gradio using the gradio.Plot() component. After creating your chart, you can specify fn = your_ploting_function, input = None, and output = gradio.Plot().

Plotly

import plotly.express as px
import pandas as pd
def plotly_plot():
    # prepare some data
    x = ["Math", "Business", "Statistics", "IT", "Commerce"]
    y = [68, 73, 82, 74, 85]
    data = pd.DataFrame()
    data['Subject'] = x
    data['Score'] = y
    # create a new plot
    p = px.bar(data, x='Subject', y='Score')

    return p

# show the results
outputs = gr.Plot()

demo = gr.Interface(fn=plotly_plot, inputs=None, outputs=outputs)

demo.launch()

Matplotlib

import matplotlib.pyplot as plt
def plt_plot():
    # prepare some data
    x = ["Math", "Business", "Statistics", "IT", "Commerce"]
    y = [68, 73, 82, 74, 85]
    # create a new plot
    plt.rcParams['figure.figsize'] = 6,4
    fig = plt.figure()
    ax = fig.add_axes([0,0,1,1])
    ax.bar(x, y)
    plt.title("Marks per subject")
    plt.xlabel("Subject")
    plt.ylabel("Score")

    return fig

# show the results
outputs = gr.Plot()

demo = gr.Interface(fn=plt_plot, inputs=None, outputs=outputs)

demo.launch()

Gradio event listeners

An event listener initiates a predefined process if a specific event occurs. Therefore, various components have different event listeners. For instance, the gradio.Video() component supports a play() event listener, triggered when a user presses play while gradio.Text() supports a change() event listener which changes the text as you type.

import gradio as gr

def welcome(name):
    return f"Welcome back, {name}!"

with gr.Blocks() as demo:
    gr.Markdown(
    """
    Type anything to see the output
    """)
    inp = gr.Textbox(placeholder="Enter your name")
    out = gr.Textbox()
    inp.change(welcome, inp, out)

demo.launch()

Streaming components in Gradio

During streaming, data is continuously sent to the backend while it Interface is running continuously. Some components like Audio have a streaming mode in microphone mode, and also, the Image component has a webcam for streaming.

Additional permissions for audio and camera access are required during streaming, depending on the type of streaming.

import gradio as gr
import numpy as np

def flip(im):
    return np.flipud(im)

demo = gr.Interface(
    flip, 
    gr.Image(source="webcam", streaming=True), 
    "image",
    live=True
)
demo.launch()

Interactive components in Gradio

Interactivity is a central characteristic of Gradio. To this end, Gradio allows interactivity using various functionalities, as shown in the following subsections.

Button

Using gradio.Button() you can define a submission button for your application by specifying value = "Submit" and adding an event gradio.Button.click().

import gradio as gr
import os

def combine(a, b):
    return "Hey! " + a + " " + b + '\n'+ " Welcome to Machine Learning Nuggets."


with gr.Blocks() as demo:
    
    txt = gr.Textbox(label="First Name", lines=2)
    txt_2 = gr.Textbox(label="Second Name")
    txt_3 = gr.Textbox(value="", label="Output")
    btn = gr.Button(value="Submit")
    btn.click(combine, inputs=[txt, txt_2], outputs=[txt_3])


if __name__ == "__main__":
    demo.launch()

Check box

In addition to the slider, you can add a checkbox for making selections. The example below combines a slider and checkbox for time selection.

import gradio as gr


def sentence_builder( morning):
    return f"""It is a nice time take a {"morning" if morning else "later in the day"} glass of water"""


demo = gr.Interface(
    sentence_builder,
    [
        gr.Checkbox(label="Is it before noon"),
    ],
    "text")

if __name__ == "__main__":
    demo.launch()

Select box

A select box is created using gradio.CheckboxGroup(). This component allows you to specify a list of entries for selection.

import gradio as gr


def sentence_builder(morning, activity_list):
    return f"""It is a nice time take a {"morning" if morning else "later in the day"} glass of water {" and take a ".join(activity_list)}"""


demo = gr.Interface(
    sentence_builder,
    [
        gr.Checkbox(label="Is it before noon"),
        gr.CheckboxGroup(["juice", "beverage", "snack", "nap"]),
    ],
    "text")

if __name__ == "__main__":
    demo.launch()

Date input

Currently, Gradio does not support the selection of dates using a widget. However, you can display the current date among other operations using datetime  as input in Textbox() component.

import gradio as gr
import datetime

with gr.Blocks() as demo:
    gr.Textbox(datetime.datetime.now)
    
demo.launch()

Color picker

To generate random colors, you can use gradio.ColorPicker().

import gradio as gr
import cv2
import numpy as np
import random


# Convert decimal color to hexadecimal color
def RGB_to_Hex(rgb):
    color = "#"
    for i in rgb:
        num = int(i)
        color += str(hex(num))[-2:].replace("x", "0").upper()
    return color


# Randomly generate light or dark colors
def gen_random_color(is_light=True):
    return (
        random.randint(0, 127) + int(is_light) * 128,
        random.randint(0, 127) + int(is_light) * 128,
        random.randint(0, 127) + int(is_light) * 128,
    )


def change_color(color_style):
    if color_style == "light":
        is_light = True
    elif color_style == "dark":
        is_light = False
    back_color_ = gen_random_color(is_light)  # Randomly generate colors
    back_color = RGB_to_Hex(back_color_)  # Convert to hexadecimal

    # Draw color pictures.
    w, h = 50, 50
    img = np.zeros((h, w, 3), np.uint8)
    cv2.rectangle(img, (0, 0), (w, h), back_color_, thickness=-1)

    return back_color, back_color, img


inputs = [gr.Radio(["light", "dark"], value="light")]

outputs = [
    gr.ColorPicker(label="color"),
    gr.Textbox(label="hexadecimal color"),
    gr.Image(type="numpy", label="color picture"),
]

title = "Random Color Generator"
description = (
    "By clicking submit, a new color will be generated"
)

demo = gr.Interface(
    fn=change_color,
    inputs=inputs,
    outputs=outputs,
    title=title,
    description=description,
)

if __name__ == "__main__":
    demo.launch()

Slider

gradio.Slider() creates a slider with a range from minimum to maximum value with a step of size step. The default slider position is specified by value. For instance, below is an implementation of the slider with minimum = 20, maximum = 100, step = 5, with default slider position

import gradio as gr


def sentence_builder(quantity, morning, activity_list):
    return f"""{quantity} o'clock is a nice time take a {"morning" if morning else "later in the day"} glass of water {" and take a ".join(activity_list)}"""


demo = gr.Interface(
    sentence_builder,
    [  gr.Slider(2, 24, value=4, step = 2),
        gr.Checkbox(label="Is it before noon"),
        gr.CheckboxGroup(["juice", "beverage", "snack", "nap"]),
    ],
    "text")

if __name__ == "__main__":
    demo.launch()

Dropdown

Gradio's Dropdown() function allows you to specify an item from a list of possible items. Building on our application, we can define an additional parameter watch that shows what a user would alternatively do.

import gradio as gr


def sentence_builder(quantity, morning, activity_list, watch):
    return f"""{quantity} o'clock is a nice time take a {"morning" if morning else "later in the day"} glass of water {" and take a ".join(activity_list)} or watch a {watch}"""


demo = gr.Interface(
    sentence_builder,
    [   gr.Slider(2, 24, value=4, step = 2),
        gr.Checkbox(label="Is it before noon"),
        gr.CheckboxGroup(["juice", "beverage", "snack", "nap"]),
        gr.Dropdown(["Television series", "Movie", "Documentary", "Class"]),
     
    ],
    "text")

if __name__ == "__main__":
    demo.launch()

Caching in Gradio

You will lose examples from your server each time your application is refreshed. You can specify cache_examples = True in Gradio's main interface, i.e., gradio.Interface() after defining your examples.

#!pip install gradio
import gradio as gra
def user_greeting(name):
    return "Hi! " + name + " Welcome to your first Gradio application!😎"

app =  gra.Interface(fn = user_greeting, inputs="text", outputs="text", examples = ["Zenith", "Antoinne", "Amelia", "Johanna"], cache_examples = True)
app.launch()

Gradio configurations

Gradio applications are configured in the launch() process. However, you can make some configurations through environment variables.

Through environment variables

To make the app accessible on the local network, you will need to set the value "0.0.0.0" in theserver_name parameter in gradio.Interface.launch() . This can also be set through the environment variable GRADIO_SERVER_NAME. If None, it will use 127.0.0.1 by default.

Integrating visualization libraries with Gradio

Gradio provides an easy-to-use Plot output component for creating data visualizations with various Python visualization libraries, including Matplotlib, Bokeh, and Plotly.

Using Matplotlib and Seaborn in Gradio

Visualizing data using Seaborn or Matplotlib in Gradio follows the same syntax.

For matplotlib, use matplotlib.plot() while for Seaborn, use seaborn.plot().

Matplotlib

import gradio as gr
from math import log
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


def gdp_change(r, year, country, smoothen):
    years = ['1850', '1900', '1950', '2000', '2050']
    m = years.index(year)
    start_day = 10* m
    final_day = 10* (m + 1)
    x = np.arange(start_day, final_day + 1)
    pop_count = {"USA": 350, "Canada": 40, "Mexico": 300, "UK": 120}
    if smoothen:
        r = log(r)
    df = pd.DataFrame({'day': x})
    df[country] = ( x ** (r) * (pop_count[country] + 1))
    fig = plt.figure()
    plt.plot(df['day'], df[country].to_numpy(), label = country)
    plt.title("GDP in " + year)
    plt.ylabel("GDP (Millions)")
    plt.xlabel("Population Change since 1800")
    plt.grid()
    return fig

inputs = [
        gr.Slider(1, 4, 3.2, label="R"),
        gr.Dropdown(['1850', '1900', '1950', '2000', '2050'], label="Year"),
        gr.Radio(["USA", "Canada", "Mexico", "UK"], label="Countries", ),
        gr.Checkbox(label="Log of GDP Growth Rate?"),
    ]
outputs = gr.Plot()

demo = gr.Interface(fn=gdp_change, inputs=inputs, outputs=outputs)

demo.launch()

Seaborn

Seaborn follows the same syntax as Matplotlib. First, define a plotting function Interfaces. Place the chart as output.

def gdp_change(r, year, country, smoothen):
    years = ['1850', '1900', '1950', '2000', '2050']
    m = years.index(year)
    start_day = 10* m
    final_day = 10* (m + 1)
    x = np.arange(start_day, final_day + 1)
    pop_count = {"USA": 350, "Canada": 40, "Mexico": 300, "UK": 120}
    if smoothen:
        r = log(r)
    df = pd.DataFrame({'day': x})
    df[country] = ( x ** (r) * (pop_count[country] + 1))
    fig = plt.figure()
    sns.lineplot(x = df['day'], y = df[country].to_numpy())
    plt.title("GDP in " + year)
    plt.ylabel("GDP (Millions)")
    plt.xlabel("Population Change since 1800")
    plt.grid()
    return fig

inputs = [
        gr.Slider(1, 4, 3.2, label="R"),
        gr.Dropdown(['1850', '1900', '1950', '2000', '2050'], label="year"),
        gr.Radio(["USA", "Canada", "Mexico", "UK"], label="Countries", ),
        gr.Checkbox(label="Log of GDP Growth Rate?"),
    ]
outputs = gr.Plot()

demo = gr.Interface(fn=gdp_change, inputs=inputs, outputs=outputs)

demo.launch()

Integrating Plotly in Gradio

In the plotting function gdp_change(...), define a plotly visualization object and pass it into gradio.Plot().

import gradio as gr
from math import log
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
import plotly.express as px
import pandas as pd


def gdp_change(r, year, country, smoothen):
    years = ['1850', '1900', '1950', '2000', '2050']
    m = years.index(year)
    start_day = 10* m
    final_day = 10* (m + 1)
    x = np.arange(start_day, final_day + 1)
    pop_count = {"USA": 350, "Canada": 40, "Mexico": 300, "UK": 120}
    if smoothen:
        r = log(r)
    df = pd.DataFrame({'day': x})
    df[country] = ( x ** (r) * (pop_count[country] + 1))
    fig = px.line(df, x='day', y=df[country].to_numpy())
    fig.update_layout(title="GDP in " + year,
                yaxis_title="GDP",
                xaxis_title="Population change since 1800s")
    return fig

inputs = [
        gr.Slider(1, 4, 3.2, label="R"),
        gr.Dropdown(['1850', '1900', '1950', '2000', '2050'], label="year"),
        gr.Radio(["USA", "Canada", "Mexico", "UK"], label="Countries", ),
        gr.Checkbox(label="Log of GDP Growth Rate?"),
    ]
outputs = gr.Plot()

demo = gr.Interface(fn=gdp_change, inputs=inputs, outputs=outputs)

demo.launch()

Visualize maps with Gradio

Map objects created using packages like Plotly or Seaborn can also be visualized using gradio.Plot().

import plotly.express as px
import pandas as pd
def map_plot():
  #define a map element
    df = px.data.gapminder().query("year==2002")
    fig = px.scatter_geo(df, locations="iso_alpha", color="continent",
                        hover_name="country", size="lifeExp",
                        projection="natural earth")
    return fig
outputs = gr.Plot()

demo = gr.Interface(fn=map_plot, inputs=None, outputs=outputs)

demo.launch()

Add statefulness to Gradio applications

Statefullness in Gradio can be done in either global or session states.

Global state

The global state in Blocks has similar functionality as in Interface. Any variable or data defined outside a function is accessible to all functions.

In the track_gdp example below, the variable gdps is shared between all users. Users who access the app will have their scores added to the list.

import gradio as gr

gdps = []

def track_gdp(gdp):
    gdps.append(gdp)
    top_gdps = sorted(gdps, reverse=True)[:3]
    return top_gdps

demo = gr.Interface(
    track_gdp, 
    gr.Number(label="gdp"), 
    gr.JSON(label="Top gdps")
)
demo.launch()

Session state

Gradio supports Session State, where the data persists across multiple submits within a page session and in Blocks apps. For session state:

  1. Define a gradio.State() object.
  2. Place the State object in the event listener, as input and output.
  3. In the event listener function, include the variable in the input parameter and the return value.

To demonstrate the session state of an app we will use the hangman game.

import gradio as gr
import random

secret_word = "Machine"

with gr.Blocks() as demo:    
    used_letters_var = gr.State([])
    with gr.Row() as row:
        with gr.Column():
            input_letter = gr.Textbox(label="Enter letter")
            btn = gr.Button("Guess Letter")
        with gr.Column():
            hangman = gr.Textbox(
                label="Hangman",
                value="_"*len(secret_word)
            )
            used_letters_box = gr.Textbox(label="Used Letters")

    def guess_letter(letter, used_letters):
        used_letters.append(letter)
        answer = "".join([
            (letter if letter in used_letters else "_")
            for letter in secret_word
        ])
        return {
            used_letters_var: used_letters,
            used_letters_box: ", ".join(used_letters),
            hangman: answer
        }
    btn.click(
        guess_letter, 
        [input_letter, used_letters_var],
        [used_letters_var, used_letters_box, hangman]
        )
demo.launch()

You will notice that the session persists within the page, but if you load the app in a new tab or refresh the application, the app will not share the "guess" history.

Laying out your Gradio application

The layout of the application's blocks can be customized using layout classes like gradio.Row(), gradio.Columns(), gradio.Tab(), and gradio.Accordion().

Rows

When using the row layout in the Blocks, all the children in your application will be rendered horizontally.

import gradio as gr
with gr.Blocks() as demo:
    with gr.Row():
        gr.Text()
        gr.Text()
demo.launch()

Columns

With gradio.Column() you can render your application's children vertically. You can specify the width of the columns by indicating the scale and min_width parameters.

import gradio as gr
with gr.Blocks() as demo:
    with gr.Column(scale=2):
         btn1 = gr.Button("Button 1")
         btn2 = gr.Button("Button 2")
    with gr.Column(scale=1):
         text1 = gr.Textbox()
         text2 = gr.Textbox()
demo.launch()

Tabs and accordions

Gradio applications can also be laid out in tabular form using gradio.Tab(). Components in a particular tab will be displayed when a user navigates to the corresponding Tab. Each Tab is assigned a label.

import gradio as gr
with gr.Blocks() as demo:
    with gr.Tab(label = "Button tab"):
         btn1 = gr.Button("Button 1")
         btn2 = gr.Button("Button 2")
    with gr.Tab(label = "Textbox tab"):
         text1 = gr.Textbox()
         text2 = gr.Textbox()
demo.launch()

An accordion returns the component's update() function with functionality to toggle and hide the content contained.

import gradio as gr
with gr.Blocks() as demo:
    with gr.Accordion("Display Details"):
        gr.Markdown("Machine Learning and Big Data")
demo.launch()

Visibility

After passing a function into Gradio's Interface or to a Block even, a typical value is returned. gradio.updateupdates the value. But, the properties of an output component can also be updated. These updates include the number of lines of a Textbox or the visibility of an Image by returning the component's update() function.

The example below shows the application of updating the visibility of an interface component.

import gradio as gr

import gradio as gr
def update_textbox(choice):
  if choice == "short":
      return gr.Textbox.update(lines=1, visible=True)
  elif choice == "long":
      return gr.Textbox.update(lines=6, visible=True)
  else:
      return gr.Textbox.update(visible=False)
gr.Interface(
  update_textbox,
  gr.Radio(
      ["short", "long", "No message"], label="What kind of message would you like to send?"
  ),
  gr.Textbox(lines=2),
  live=True,
).launch()

Multi-page Gradio apps

After creating different apps, you can use methods like:

  • gradio.TabbedInterfaces() and  gradio.Parallel() for comparing outputs from multiple apps
  • gradio.Series() for feeding input from one app to the next

to combine the apps into multi-page applications.

In this section, we will use gradio.TabbedInterface() to create a multi-page app for the Dropdown and Seaborn applications that we had created earlier.

#define your first application
#!pip install gradio
import gradio as gr
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from math import log
def user_greeting(name):
    return "Hi! " + name + " Welcome to your multi-page application!😎"
#app 1
app =  gr.Interface(fn = user_greeting, inputs="text", outputs="text", examples = ["Zenith", "Antoinne", "Amelia", "Johanna"])

#define your second application
def gdp_change(r, year, country, smoothen):
    years = ['1850', '1900', '1950', '2000', '2050']
    m = years.index(year)
    start_day = 10* m
    final_day = 10* (m + 1)
    x = np.arange(start_day, final_day + 1)
    pop_count = {"USA": 350, "Canada": 40, "Mexico": 300, "UK": 120}
    if smoothen:
        r = log(r)
    df = pd.DataFrame({'day': x})
    df[country] = ( x ** (r) * (pop_count[country] + 1))
    fig = plt.figure()
    sns.lineplot(x = df['day'], y = df[country].to_numpy())
    plt.title("GDP in " + year)
    plt.ylabel("GDP (Millions)")
    plt.xlabel("Population Change since 1800s")
    plt.grid()
    return fig

inputs = [
        gr.Slider(1, 4, 3.2, label="R"),
        gr.Dropdown(['1850', '1900', '1950', '2000', '2050'], label="year"),
        gr.Radio(["USA", "Canada", "Mexico", "UK"], label="Countries", ),
        gr.Checkbox(label="Log of GDP Growth Rate?"),
    ]
outputs = gr.Plot()
#app 2
app2 = gr.Interface(fn=gdp_change, inputs=inputs, outputs=outputs)
#combine to create a multipage app
demo = gr.TabbedInterface([app, app2], ["Welcome page", "Visualization page"])

if __name__ == "__main__":
    demo.launch()

Custom CSS and Javascript in Gradio

You can style your app to custom specifications by passing any CSS to your app using css = kwarg. For example, in the Tab layout example, you can define a custom background CSS as follows:

import gradio as gr
with gr.Blocks(css=".gradio-container {background-color: grey}") as demo:
    with gr.Tab(label = "Button tab"):
         btn1 = gr.Button("Button 1")
         btn2 = gr.Button("Button 2")
    with gr.Tab(label = "Textbox tab"):
         text1 = gr.Textbox()
         text2 = gr.Textbox()
demo.launch()

Similarly, you can define custom JS for your app.

import gradio as gr

blocks = gr.Blocks()

with blocks as demo:
    subject = gr.Radio(["Analyse", "Explore", "Learn"])
    verb = gr.Radio(["GDP Change", "Population Growth", "Big Data"])
    object = gr.Textbox(placeholder="region")

    with gr.Row():
        btn = gr.Button("Create sentence.")
        reverse_btn = gr.Button("Reverse sentence.")

    def sentence_maker(w1, w2, w3):
        return f"{w1} {w2} in {w3}"

    output1 = gr.Textbox(label="output 1")
    output2 = gr.Textbox(label="verb reversed")

    btn.click(sentence_maker, [subject, verb, object], output1)
    #custom JS to reverse the sentense
    reverse_btn.click(None, [subject, verb, object], output2, _js="(s, v, o) => o + ' ' + v + ' ' + s")

demo.launch()

Authenticating Gradio apps

When launching a Gradio application, you can define an authentication method by specifying the auth parameter. If auth is passed, a username and password (or list of username-password tuples) will be required to access the interface.

You can also add an auth_message to guide the user on what to include.

import gradio as gr

def data_display(input_img):
    return input_img

demo = gr.Interface(data_display, gr.Dataframe(), "matrix")
demo.launch(enable_queue=False, auth=("username", "password"), auth_message="Try this")

Uploading and processing files in Gradio

You can upload and display generic and displaying generic files as output. Moreover, you can choose to process the uploaded files.

Uploading a single file

import numpy as np
import gradio as gr

def upload_image(input_img):

    return input_img

demo = gr.Interface(upload_image, gr.Image(shape=(400, 300)), "image")
demo.launch()

gradio.File() enables you to upload generic files like zip files.

from zipfile import ZipFile

import gradio as gr


def upload_file(file_obj):
    files = []
    with ZipFile(file_obj.name) as zfile:
        for zinfo in zfile.infolist():
            files.append(
                {
                    "name": zinfo.filename,
                }
            )
    return files


demo = gr.Interface(upload_file, "file", "json")

if __name__ == "__main__":
    demo.launch()

Uploading multiple files

To upload multiple files, add a file_count parameter, which specifies the number of files you can upload in a single session.

import os
from zipfile import ZipFile

import gradio as gr

def zip_files(files):
    with ZipFile("tmp.zip", "w") as zipObj:
        for idx, file in enumerate(files):
            zipObj.write(file.name, "file" + str(idx))
    return "tmp.zip"

demo = gr.Interface(
    zip_files,
    gr.File(file_count="multiple"),
    "file"
)

if __name__ == "__main__":
    demo.launch()

Uploading and processing data

While uploading your files, you can define a function that preprocesses the data and returns an output of the preprocessed file. For instance, you can change the hue of your image data.

import numpy as np
import gradio as gr

def sepia_hue(input_img):
    sepia_filter = np.array([[.393, .769, .189],
                         [.349, .686, .168],
                         [.272, .534, .131]])
    sepia_hue_img = input_img.dot(sepia_hue_filter.T)
    sepia_hue_img /= sepia_hue_img.max()
    return sepia_hue_img

demo = gr.Interface(sepia_hue, gr.Image(shape=(300, 200)), "image")
demo.launch()
Dog: Photo by Dongsh on Unsplash


Flagging in Gradio

Flagging allows you to collect data on users who use your application/ model, especially data points in which the application behaves unexpectedly. Gradio has an easy flagging method.

By including a Flag button in each interface, a user can send data back to the location where the application is running.

Gradio allows four parameters in the gradio.Interface() component that define how Flagging functions. The parameters include  allow_flagging, flagging_options, flagging_dir, and flagging_callback.

allow_flagging is  manual by default, where samples are flagged when the user clicks the Flag button. You can then use flagging_dir = "path/to/store" specifying the directory for storing the log data. Otherwise, the logs will be stored in a new folder in the location where the app is launched.

We can add flagging to the Altair visualization app, as shown below.


import numpy as np
import pandas as pd

import gradio as gr
import altair as alt

from math import log
import numpy as np
import pandas as pd


def gdp_change(r, year, country, smoothen):
    years = ['1850', '1900', '1950', '2000', '2050']
    m = years.index(year)
    start_day = 1* m
    final_day = 1* (m + 1)
    x = np.arange(start_day, final_day + 1)
    pop_count = {"USA": 350, "Canada": 40, "Mexico": 300, "UK": 120}
    if smoothen:
        r = log(r)
    df = pd.DataFrame({'day': x})
    df[country] = ( x ** (r) * (pop_count[country] + 1))
    df['country'] = df[country].values

    return alt.Chart(df).mark_bar().encode(
            x='day',
            y= 'country').properties(width=550)

inputs = [
        gr.Slider(0.1, 1, 0.3,step = 0.001, label="R"),
        gr.Dropdown(['1850', '1900', '1950', '2000', '2050'], label="year"),
        gr.Radio(["USA", "Canada", "Mexico", "UK"], label="Countries", ),
        gr.Checkbox(label="Log of GDP Growth Rate?"),
    ]
outputs = gr.Plot()


demo = gr.Interface(fn=gdp_change, inputs=inputs, outputs=outputs, allow_flagging="manual", flagging_options=["No plot shown", "Wrong axis", "Other"])

demo.launch()

See Gradio documentation for the parameter options.

Using Flagging
A Step-by-Step Gradio Tutorial

Build an image Classification with Vision Transformers in Gradio

Transformers offer APIs and tools to download and train state-of-the-art pre-trained models quickly. As shown below, you can easily create a classification application using vision transformers.

import gradio as gr
#load your preffered model
app = gr.Interface.load(
             "huggingface/google/vit-base-patch16-224")

#launch
app.launch()
Llama: Photo by Raspopova Marina, on Unsplash

For additional transformer models, go to Hugging face documentation.

google (Google AI)
We’re on a journey to advance and democratize artificial intelligence through open source and open science.

Use Hugging face to develop a chatbot application with Gradio

Creating a chatbot is simplified by using Hugging face pre-trained models. You will need a pre-trained tokenizer and conversational model such as DialoGPT.

In the example below, we use a  DialoGPT tokenizer and conversational model.

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
#set up the model (large version of DialoGPT)
tokenizer = AutoTokenizer.from_pretrained("microsoft/DialoGPT-large")
model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-large")

#Defining a predict function

def predict(input, history=[]):
    # tokenize the new input sentence
    new_user_input_ids = tokenizer.encode(input + tokenizer.eos_token, return_tensors='pt')

    # append the new user input tokens to the chat history
    bot_input_ids = torch.cat([torch.LongTensor(history), new_user_input_ids], dim=-1)

    # generate a response 
    history = model.generate(bot_input_ids, max_length=1000, pad_token_id=tokenizer.eos_token_id).tolist()

    # convert the tokens to text, and then split the responses into lines
    response = tokenizer.decode(history[0]).split("<|endoftext|>")
    response = [(response[i], response[i+1]) for i in range(0, len(response)-1, 2)]  # convert to tuples of list
    return response, history

#creating a gradio interface

import gradio as gr

demo = gr.Interface(fn=predict,
             inputs=["text", "state"],
             outputs=["chatbot", "state"])

demo.launch()

Deploying Gradio applications

The Gradio package simplifies the creation of a shareable GUI & public link for your model. This is true as long as the model runs in your local environment. But when you need a long-term hosted solution, you will need to look elsewhere.

This is where hosting services like Heroku and Hugging Face spaces come in.

Heroku

Deploying a Gradio application in Heroku follows five steps:

  1. Create your application ( app.py) and store it in a new directory.
  2. Write your requirements.txt file

You’ll need a Heroku account and, optionally, for convenience, the Heroku CLI. Create a Heroku account and download the CLI if you haven’t done that already:

  1. Create a setup.sh file. For your app to run correctly, ensure it’s served on the correct URL & port. Add export GRADIO_SERVER_NAME=0.0.0.0 and export GRADIO_SERVER_PORT="$PORT" to the setup.sh file.
  2. Create a Procfile. The Procfile specifies the commands that are run to start the Gradio app. There are only two commands: to run the bash script, and then to launch the app. So your Heroku Procfilelooks like web: source setup.sh && python app.py
  3. Deploy! With that in place, you can proceed with your usual Heroku deployment process.

Hugging Face spaces

Create a user account at https://huggingface.co/. Navigate to Spaces in the navigation bar and create a New Space.

Provide the necessary information.

A link with a repo will be created. Copy the link in your command prompt. In our case, we obtained the link as shown below, but it might differ depending on your details.

git clone https://huggingface.co/spaces/Kamanda/Gradio_machine_learning

A new folder ( Gradio_machine_learning) will be created.

  • Make a copy of  the files necessary for running your Gradio application, such asapp.py, requirements.txt in this new folder.
  • Back in your terminal, execute the following commands, replacing the respective names with that of your workspace.
cd Gradio_Machine_Learning
git add .
git commit -m "first commit"
git push

You will be prompted to enter your Hugging face credentials. For Windows users, the widget will be something like:

If you have met all the requirements, go to your spaces and click on your space. You should see an app running.

Below is the link to this guide's Hugging face application.

Gradio Machine Learning - a Hugging Face Space by Kamanda
Discover amazing ML apps made by the community


Final thoughts

While developing your machine learning model often takes place in a local environment, its intended application is often in deployment. This guide taught you how to create easy-to-use, customizable UI components for your ML model, any API, or even an arbitrary python function using a few lines of code with Gradio.

That's it!


Whenever you're ready, there is 2 way I can help you:

If you're looking for a way to build a career while writing about data science and machine learning, I'd recommend starting with an affordable ebook:

Writing for Data Scientists: The exact path I followed to get technical work that pays between $250-$500 from machine learning companies such as Comet, Neptune, cnvrg, Paperspace, Layer, Neural Magic, Determined, Activeloop, and many more. Get your copy.

Data Science and Machine Learning Ebook: I offer numerous free and paid data science and machine learning ebooks to help you in your data science career. Check them out.

Open On GitHub
Data Science

Kamanda Wycliffe

Data Scientist and Ethical Hacker with interest in data modeling and data-driven cyber security systems.

Comments