Skip to content
Forward Deployed

Forward Deployed
Lessons and contents
Learn

Building demos with Gradio

Source
From the RAG & Agents Engineering course
By
Sourav Banerjee
Last updated
9 Nov 2026

Report an issue

Gradio Blocks

Gradio turns a Python function into a web page. The function stays ordinary Python; Gradio draws an input component for each argument, an output component for each return value, and calls the function when the user acts. launch() serves the page at http://localhost:7860, or the next free port above it.

Gradio has two ways to build that page:

  • gr.Interface(fn, inputs, outputs) builds a form around one function: the input components, a Submit button and the outputs. Notebook 05a wraps an adder, a text reverser, a greyscale filter and a classifier this way, and 05d sets live=True so the function reruns on every change instead of on Submit. Interface also adds a Flag button; in Gradio 6.31 flagged examples go to .gradio/flagged, not the flagged folder 05a names.
  • gr.Blocks() is a context manager in which you place components yourself, inside gr.Row(), gr.Column(scale=…), gr.Tab(), gr.Accordion() and gr.Group() (05b). Blocks adds no button and calls nothing by itself. You connect each event to a function (05c): button.click(fn, inputs, outputs) runs on a click, slider.change(...) on every change of value. One page can hold many components and many events, each with its own function.
Diagram: Textbox ticket; tag(ticket) Python function; Button Tag; Label sentimentDiagram: Textbox ticket; tag(ticket) Python function; Button Tag; Label sentiment

The event names its inputs and outputs by component, and Gradio passes values between the browser and the function. This is the Larkspur ticket tagger as a Blocks app, with the ticket box and button in a wide column and the result beside them:

import gradio as gr
from transformers import pipeline

clf = pipeline("sentiment-analysis",
               model="distilbert/distilbert-base-uncased-finetuned-sst-2-english",
               revision="714eb0f")                       # loaded once, when the app starts

def tag(ticket):
    if not ticket.strip():
        raise gr.Error("Paste a ticket first.")          # stops here and shows the message
    r = clf(ticket)[0]
    return {r["label"]: r["score"]}                      # gr.Label shows a label with its confidence

with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column(scale=2):
            ticket = gr.Textbox(label="Ticket", lines=4)
            go = gr.Button("Tag")
        with gr.Column(scale=1):
            label = gr.Label(label="Sentiment")
    go.click(fn=tag, inputs=ticket, outputs=label)

demo.launch()

Three habits from the notebooks carry over to every demo:

  • Load the model once, outside the function. 05e builds its sentiment pipeline at the top of the notebook and only calls it inside predict_sentiment. A pipeline built inside the event function would reload the weights on every click.
  • Fail with a message. raise gr.Error("…") stops the function and shows the message in the page; gr.Warning("…") shows a notice and lets the function finish (05f).
  • Style through launch() in Gradio 6. 05g passes theme= to gr.Interface and css= to gr.Blocks. Gradio 6.31, the version this course locks, still accepts both but warns "The parameters have been moved from the Blocks constructor to the launch() method in Gradio 6.0"; pass them as demo.launch(theme=…, css=…).

Notebook 05e's last cell, gr.load("distilbert-base-uncased-finetuned-sst-2-english", src=…), runs the model on Hugging Face's servers instead of locally. In the course copy its src points at a GitHub folder URL, which gr.load does not accept; the source notebook has src="models", which loads the model by its Hub name.

A demo is a tool for trying a model with people who do not run notebooks, such as the Larkspur support lead. It has no login, rate limit or monitoring unless you add them, so in production the model runs behind a service with those controls, and the demo stays a way to try it.

Run the notebooks

The code for this lesson is in these notebooks. Colab runs one in your browser: install the packages its first cell imports and set the API keys it reads. To run every notebook as written, clone the repository and use its uv environment.

Notebook GitHub Colab
Gradio introduction Open on GitHub Open in Colab
Gradio layout (optional) Open on GitHub Open in Colab
Gradio interactions (optional) Open on GitHub Open in Colab
Gradio image ml integration (optional) Open on GitHub Open in Colab
Gradio text ml integration (optional) Open on GitHub Open in Colab
Gradio modals errors (optional) Open on GitHub Open in Colab
Gradio styling and themes (optional) Open on GitHub Open in Colab

Key Takeaways

  • Use gr.Interface for a quick form around one function, and gr.Blocks when you need your own layout and many events, each wired to a function with calls such as button.click(fn, inputs, outputs).
  • Load the model once when the app starts, raise gr.Error to stop with a message, and pass theme= and css= to launch() in Gradio 6.
  • A demo has no login, rate limit or monitoring. Use it to let people try a model, and serve production traffic from a service with those controls.

Check yourself

1. What does gr.Blocks leave you to do that gr.Interface does for you?

gr.Interface builds a form around one function: input components, a Submit button, the outputs and a Flag button. gr.Blocks adds no button and calls nothing by itself: you place the components in rows, columns and tabs, and connect each event to a function, such as button.click(fn, inputs, outputs). In return one page can hold many components and events.

2. In the Larkspur ticket tagger, the support lead clicks Tag with an empty ticket box. What does the page show, and does the classifier run?

The page shows "Paste a ticket first." and the classifier does not run. tag checks for an empty ticket first, and raise gr.Error(...) stops the function there and shows the message. gr.Warning would show a notice and let the function finish.

3. Every click in a colleague's Gradio demo reloads the model weights. Where did they build the pipeline, and where should it go?

Inside the event function, so each call builds the pipeline again. Build it once outside the function, when the app starts, as 05e and the ticket tagger do, and only call it inside the function.

Rate your confidence and keep notes on the module page.