Corso
L'utilità dei modelli di IA odierni si riduce notevolmente senza interfacce utente accessibili. Con Gradio, una libreria web UI open-source per Python, puoi colmare il divario tra gli LLM e gli utenti finali non tecnici. Ti permette di creare prototipi rapidi per i tuoi progetti di IA e di semplificarne la distribuzione a un pubblico più ampio.
Questo tutorial è rivolto a machine learning engineer che in genere non hanno esperienza di sviluppo web. Copre le basi e i concetti chiave di Gradio, la creazione di interfacce per vari tipi di modelli di IA, le funzionalità avanzate per UX e interattività e le buone pratiche per la distribuzione e la condivisione.
Iniziamo.
Primi passi con Gradio
Installazione
Cominciamo creando un ambiente virtuale (preferibilmente Conda):
$ conda create -n gradio_tutorial python=3.9 -y
$ conda activate gradio_tutorial
Poi puoi usare PIP per installare Gradio e le sue dipendenze:
$ pip install gradio ipykernel
Abbiamo installato anche il pacchetto ipykernel per poter visualizzare le interfacce Gradio direttamente nei notebook Jupyter. Questo processo richiede di aggiungere l'ambiente virtuale creato come kernel in Jupyter Lab. Ecco il comando per farlo:
$ ipython kernel install --user --name=gradio_tutorial
$ jupyter lab # Start the lab
Questo ti permetterà di creare un notebook con un kernel che ha Gradio installato. Per verificare, importalo con il suo alias standard e stampa la versione:
import gradio as gr
print(gr.__version__)
4.37.1
Concetti di base e terminologia
Esploriamo Gradio imparando i suoi concetti e termini chiave con un esempio "Hello World":
def greet(name):
return f"Hello, {name}!"
demo = gr.Interface(
fn=greet,
inputs=['text'],
outputs="text",
)
demo.launch()
Eseguendo il codice sopra in una cella, l'output sarà una piccola interfaccia interattiva che restituisce un messaggio di saluto personalizzato:

Gradio ruota attorno a pochi concetti chiave:
- Interface: la classe principale per creare UI.
- Componenti: elementi di input e output come caselle di testo, immagini e audio. Al momento ci sono più di 30 componenti integrati.
- Funzioni: funzioni Python che elaborano le informazioni dai componenti di input e restituiscono i risultati da visualizzare con i componenti di output.
- Launch: il metodo per avviare la tua app Gradio.
Sopra abbiamo creato una funzione greet che accetta e restituisce un input di testo. Per questo motivo, i componenti di input e output sono specificati come text all'interno della classe Interface.
Infine chiamiamo il metodo launch, che avvia un server locale. Per rendere la UI disponibile a chiunque, puoi impostare il parametro share su True. Questo avvierà un tunnel SSH e distribuirà l'app Gradio su una pagina web pubblicamente condivisibile:
demo.launch(share=True)
Running on public URL: https://d638ed5f2ce0044296.gradio.live
This share link expires in 72 hours. For free permanent hosting and GPU upgrades, run gradio deploy from Terminal to deploy to Spaces (https://huggingface.co/spaces)
Componenti di Gradio
Durante la creazione di app Gradio, passerai la maggior parte del tempo a sperimentare con i vari componenti e con il loro posizionamento sulla pagina. Vediamo più da vicino cosa hai a disposizione.
Componenti di input e di output
Gradio offre un'ampia gamma di componenti per creare interfacce interattive. In generale, questi componenti sono suddivisi in due categorie: input e output.
I componenti di input consentono agli utenti di fornire dati all'elaboratore sottostante (che può essere qualsiasi funzione Python). Alcuni input comuni sono:
- Textbox
- Image
- Audio
- Slider
- Dropdown
Ecco un'interfaccia di esempio che usa alcuni dei componenti sopra:
def process_inputs(text, image, audio, number, option):
# Process inputs and return results
return f"Processed: {text}, {number}, {option}"
demo = gr.Interface(
fn=process_inputs,
inputs=[
gr.Textbox(label="Enter text"),
gr.Image(label="Upload image"),
gr.Audio(label="Upload audio"), # Uncomment this line to add audio input
gr.Slider(0, 100, label="Choose a number"),
gr.Dropdown(["Streamlit", "Taipy", "Gradio"], label="Select a UI library"),
],
outputs="text",
)
demo.launch()
In questo esempio, la funzione process_inputs richiede cinque parametri. Di conseguenza, dobbiamo creare cinque componenti di input e passarli a inputs. Anche se il numero di componenti di input dovrebbe corrispondere al numero di parametri richiesti dalla funzione, non è una regola rigida. Per evitare errori e avvisi, imposta valori predefiniti per i parametri che non richiedono input dell'utente dalla UI.

Nota come stiamo usando la classe Textbox per specificare il componente di input invece di una semplice stringa text come nel primo esempio. È sempre consigliato usare le classi dedicate per specificare i componenti di input e output, in modo da poterli personalizzare. Ad esempio, tutte le classi di componenti hanno un utile attributo label, mentre Slider e Dropdown hanno argomenti per specificare intervalli e opzioni disponibili.
Molti componenti di input possono essere usati anche per visualizzare output. Ecco alcuni scenari comuni:
- Label: per mostrare testo o risultati di classificazione
- Image: per visualizzare immagini elaborate o generate
- Audio: per riprodurre audio elaborato o generato
- Plot: per mostrare grafici o diagrammi
Come per gli input, il numero di componenti di output deve corrispondere al numero di valori restituiti dalla funzione di elaborazione.
Personalizzare l'aspetto dei componenti
Gradio ti consente di personalizzare l'aspetto dei componenti in base alle tue esigenze. Ecco un esempio che usa caselle di testo personalizzate:
demo = gr.Interface(
fn=lambda x: int(x) ** 7,
inputs=gr.Textbox(
lines=5,
placeholder="Enter any number...",
label="Custom textbox",
info="This is a customized textbox component to raise any number to the power of 7.",
),
outputs=gr.Textbox(label="And the number is...", show_copy_button=True),
)
demo.launch()

In questo esempio abbiamo personalizzato i componenti Textbox specificando il numero di righe, aggiungendo un placeholder e un testo informativo, e includendo un pulsante di copia per l'output.
Sperimenta con i vari componenti e le loro proprietà per creare interfacce che si adattino al meglio alle esigenze della tua applicazione di IA. Per scoprire quali proprietà puoi modificare per un componente, puoi consultare la documentazione o, meglio ancora, usare l'operatore ? in Jupyter Lab dopo il nome della classe:

Creare interfacce per LLM
Mettiamo insieme tutto ciò che abbiamo imparato creando due interfacce reali basate su testo e immagini, alimentate da LLM.
Per prima cosa costruiremo un traduttore dall'inglese al turco, spagnolo o cinese:
import openai # pip install openai
def translate_text(api_key, text, target_language):
openai.api_key = api_key # Set openai API key
language_map = {
"Turkish": "Turkish",
"Spanish": "Spanish",
"Chinese": "Chinese (Simplified)",
}
prompt = f"Translate the following English text to {language_map[target_language]}:\n\nEnglish: {text}\n\n{target_language} translation:"
try:
response = openai.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a professional translator."},
{"role": "user", "content": prompt},
],
)
translation = response.choices[0].message.content.strip()
return translation
except Exception as e:
return f"Error: {str(e)}"
Per iniziare, definiamo una funzione translate_text. Al suo interno impostiamo la chiave API di OpenAI e creiamo una mappa delle lingue. Poi costruiamo il prompt per la traduzione. Quindi, all'interno di un blocco try-except inviamo una richiesta all'endpoint ChatCompletion con un prompt di sistema. Infine restituiamo la prima scelta.
Ora possiamo costruire l'interfaccia:
iface = gr.Interface(
fn=translate_text,
inputs=[
gr.Textbox(
placeholder="Enter your OpenAI API key",
type="password",
label="OpenAI API Key",
),
gr.Textbox(
lines=4,
placeholder="Enter English text to translate...",
label="English Text",
),
gr.Dropdown(choices=["Turkish", "Spanish", "Chinese"], label="Target Language"),
],
outputs=gr.Textbox(label="Translation", show_copy_button=True),
title="English to Turkish/Spanish/Chinese Translator",
description="Translate English text to Turkish, Spanish, or Chinese using OpenAI's GPT-4 model. Enter your OpenAI API key, the text you want to translate, and select the target language.",
)
iface.launch(share=True)
Il codice è semplice, come negli esempi precedenti, ma introduciamo un paio di nuove proprietà:
- l'argomento type delle caselle di testo trasforma il campo di input in formato password, nascondendo il testo.
- gli argomenti title e description della classe Interface aggiungono un titolo H1 e un sottotitolo nella parte alta e centrale della pagina.
Ecco il risultato:

Potresti chiederti perché chiediamo la chiave API dell'utente come parte dell'app invece di fornirla noi. Il motivo ha a che fare con il modo in cui Gradio distribuisce le UI.
Se fornissimo la nostra chiave API come variabile d'ambiente (che è la prassi), la versione dell'app condivisibile pubblicamente non funzionerebbe perché non avrebbe accesso alle nostre variabili d'ambiente. Nella sezione sulla distribuzione vedremo come risolvere distribuendo le nostre app su HuggingFace Spaces.
Costruiamo ora un'altra UI per generare immagini:
def generate_surrealist_art(api_key, prompt):
surrealist_prompt = f"Create a surrealist artwork based on the following concept: {prompt}. The artwork should be dreamlike, with unexpected juxtapositions and a sense of the uncanny."
client = OpenAI(api_key=api_key)
response = client.images.generate(
model="dall-e-3",
prompt=surrealist_prompt,
size="1024x1024",
)
image_url = response.data[0].url
return image_url
Creiamo una funzione chiamata generate_surrealist_art che invia una richiesta a dall-e-3 e restituisce l'URL dell'immagine generata usando un prompt surrealista. Quindi passeremo questa funzione di nuovo a una classe Interface:
iface = gr.Interface(
fn=generate_surrealist_art,
inputs=[
gr.Textbox(
placeholder="Enter your OpenAI API key",
type="password",
label="OpenAI API Key",
),
gr.Textbox(
lines=2,
placeholder="Describe your surrealist concept...",
label="Concept Description",
),
],
outputs=gr.Image(value="str"),
title="Surrealist Artwork Generator",
description="Generate surrealist artwork based on your prompts using DALL-E. Enter your OpenAI API key and describe your concept.",
)
iface.launch(share=True)
Specifichiamo due input per la chiave API e per il concetto che vogliamo rappresentare in un'immagine surrealista. Poi creiamo un componente di output per l'immagine generata con la classe Image. Se imposti il suo argomento value su str, il componente può scaricare e mostrare immagini da URL, proprio quello che ci serve.
Ed ecco il risultato:

Creare interfacce per modelli ML classici
Ora creiamo un'interfaccia per un classico modello di regressione tabellare. Useremo il dataset Diamonds, disponibile in Seaborn.
Inizia creando una nuova directory di lavoro e, al suo interno, un nuovo script chiamato app.py. Quindi incolla il codice da questa gist su GitHub che carica i dati, li elabora usando una Pipeline di Scikit-learn e addestra un modello di RandomForestRegression.

Il passo successivo è creare una funzione di elaborazione che accetti lo stesso numero di input delle feature del dataset Diamonds:
# Create the Gradio interface
def predict_price(carat, cut, color, clarity, depth, table, x, y, z):
input_data = pd.DataFrame(
{
"carat": [carat],
"cut": [cut],
"color": [color],
"clarity": [clarity],
"depth": [depth],
"table": [table],
"x": [x],
"y": [y],
"z": [z],
}
)
prediction = model.predict(input_data)[0]
return f"Predicted Price: ${prediction:.2f}"
La funzione converte questi input in un DataFrame e lo passa al metodo .predict() della pipeline del modello addestrato. Infine restituisce una stringa con il prezzo previsto.
Ora la classe Interface deve corrispondere alla firma di questa funzione: nove componenti di input per elaborare le feature e un output per visualizzare il prezzo previsto:
iface = gr.Interface(
fn=predict_price,
inputs=[
gr.Slider(
minimum=diamonds["carat"].min(),
maximum=diamonds["carat"].max(),
label="Carat",
),
gr.Dropdown(["Fair", "Good", "Very Good", "Premium", "Ideal"], label="Cut"),
gr.Dropdown(["D", "E", "F", "G", "H", "I", "J"], label="Color"),
gr.Dropdown(
["I1", "SI2", "SI1", "VS2", "VS1", "VVS2", "VVS1", "IF"], label="Clarity"
),
gr.Slider(
minimum=diamonds["depth"].min(),
maximum=diamonds["depth"].max(),
label="Depth",
),
gr.Slider(
minimum=diamonds["table"].min(),
maximum=diamonds["table"].max(),
label="Table",
),
gr.Slider(minimum=diamonds["x"].min(), maximum=diamonds["x"].max(), label="X"),
gr.Slider(minimum=diamonds["y"].min(), maximum=diamonds["y"].max(), label="Y"),
gr.Slider(minimum=diamonds["z"].min(), maximum=diamonds["z"].max(), label="Z"),
],
outputs="text",
title="Diamond Price Predictor",
description="Enter the characteristics of a diamond to predict its price.",
)
iface.launch(share=True)
All'interno della classe creiamo tre menu a discesa per le feature categoriche. Le opzioni sono compilate con le categorie uniche di ciascuna feature. Creiamo inoltre sei slider per accettare le feature numeriche. Gli intervalli degli slider sono determinati dai valori minimo e massimo di ogni feature.
Ora non ci resta che eseguire lo script per avviare e distribuire l'app:
$ python app.py
Ecco il risultato:

Per le buone pratiche e i consigli di ottimizzazione, vai alla sezione Best Practices qui sotto.
Distribuire app Gradio
Abbiamo già visto quanto sia facile distribuire app Gradio abilitando un singolo argomento. Naturalmente, lo svantaggio di questo metodo è che le demo scadono entro 72 ore. Per questo, il metodo consigliato per distribuire Gradio è tramite HuggingFace Spaces. HuggingFace ha acquisito Gradio nel 2021, rendendo l'integrazione tra le due piattaforme senza soluzione di continuità.
Quindi, per questo tutorial o per qualsiasi app futura che creerai con Gradio, registrati gratuitamente su huggingface.co e vai su Settings > Tokens per generare un access token:

Il token viene mostrato una sola volta, quindi assicurati di conservarlo in un luogo sicuro.
Con questo token, puoi distribuire quante app Gradio vuoi con hosting permanente su Spaces. Come esempio, distribuiremo il modello di previsione dei prezzi dei diamanti della sezione precedente, e scoprirai che è sorprendentemente semplice.
Tutto quello che devi fare è andare nella directory con lo script della UI e chiamare gradio deploy dal terminale:

Il terminale ti guida nella conversione dello script in uno Space funzionante su HuggingFace. Chiede dettagli come:
- l'access token che hai generato
- titolo dello Space: farà parte dell'URL dello Space dopo la distribuzione
- il nome dello script che contiene il codice della UI Gradio (app.py di default)
- l'hardware dello Space; lascia vuoto per usare solo CPU (gratuito)
- eventuali variabili d'ambiente usate dallo script (qui puoi archiviare in modo sicuro API key e segreti utente)
- dipendenze— inseriscile una per volta premendo INVIO
E il terminale ti fornisce un link allo Space distribuito. Ecco come appare:

Un altro grande vantaggio di questo metodo di distribuzione è che Gradio converte automaticamente la demo in una REST API funzionante. Le istruzioni per accedervi e interrogarla si trovano sempre in fondo:

Quindi, in un colpo solo, hai sia l'hosting permanente della UI per la tua applicazione destinata a utenti non tecnici sia una REST API per colleghi e sviluppatori.
Per ulteriori opzioni di distribuzione e condivisione, come incorporare le demo in pagine web, aggiungere l'autenticazione Google alle app, ecc., visita la sezione “Sharing Your App” della documentazione di Gradio.
Buone pratiche e consigli per Gradio
Quando sviluppi interfacce utente con Gradio, seguire le buone pratiche può migliorare sensibilmente l'esperienza utente e la manutenibilità dell'applicazione. Ecco alcune raccomandazioni chiave:
1. Usa script per organizzazione e manutenibilità
Organizza le applicazioni Gradio in script Python per un miglior controllo versione, collaborazione e distribuzione.
2. Ottimizza l'allocazione dello spazio per i componenti
Usa dimensionamenti e strumenti di layout appropriati (ad es. gr.Column(), gr.Row()) per garantire un'interfaccia equilibrata e responsiva.
3. Fornisci informazioni complete
Utilizza gli attributi 'info' e 'label' per fornire istruzioni e contesto chiari per ogni componente.
4. Gestisci in modo efficiente set di feature estesi
Per modelli con molte feature, usa input file (CSV, JSON) per abilitare previsioni batch e semplificare l'interfaccia.
5. Gestisci correttamente le variabili d'ambiente
Usa python-dotenv per lo sviluppo locale e imposta le variabili in Hugging Face Spaces per la distribuzione.
6. Implementa gestione errori e convalida
Convalida gli input, fornisci messaggi di errore chiari e usa blocchi try-except per una gestione degli errori efficace.
7. Ottimizza le prestazioni
Implementa caching, caricamento lazy per modelli di grandi dimensioni e usa gr.LoadingStatus() per attività di lunga durata.
8. Progetta per l'accessibilità
Assicura alto contrasto, fornisci testo alternativo per le immagini e abilita la navigazione da tastiera per tutti gli elementi interattivi.
9. Usa la disclosure progressiva
Usa fisarmoniche o tab per organizzare interfacce complesse, mostrando le opzioni avanzate solo quando necessario.
10. Aggiorna e mantieni regolarmente
Tieni aggiornate le dipendenze, monitora i bug e migliora continuamente in base al feedback degli utenti.
11. Sfrutta le risorse di HuggingFace
Usa gli strumenti e le risorse di HuggingFace per un'integrazione senza attriti con Gradio, inclusi repository di modelli e dataset.
12. Ospita modelli grandi su HuggingFace Hub
Per grandi modelli tabellari, caricali su HuggingFace Hub e caricali direttamente nel tuo script Gradio per migliorare le prestazioni e ridurre i requisiti di storage locale.
13. Utilizza i dataset di HuggingFace
Per dataset di grandi dimensioni, caricali su HuggingFace Hub e accedili direttamente nella tua applicazione Gradio per semplificare la gestione dei dati e migliorare i tempi di caricamento.
Conclusione e risorse aggiuntive
In questo articolo abbiamo imparato le basi per creare interfacce utente per applicazioni di IA usando Gradio. Abbiamo solo scalfito la superficie, perché Gradio offre molte altre funzionalità per costruire interfacce complesse. Ad esempio, interface state permette alla tua app di ricordare output da una chiamata di funzione all'altra. Reactive interfaces modificano dinamicamente la UI non appena cambia l'input dell'utente. Con Blocks, puoi costruire app con layout e design personalizzati.
Allo stesso modo, dai un'occhiata a queste risorse correlate per ulteriori contenuti:

