Aller au contenu principal

Module 1 — Interface : entrées, sorties, fonction

La question que reçoit tout chercheur ou ingénieur au moment de montrer un modèle est presque toujours la même : « on peut l'essayer quelque part ? ». Répondre par un notebook, c'est perdre la moitié du public. Répondre par une application web à écrire à la main, c'est perdre une semaine. Gradio propose une troisième voie : décrire l'interface à partir de la fonction Python qui appelle le modèle, en une dizaine de lignes, sans quitter le terminal.

Le contrat de gr.Interface

gr.Interface est le point d'entrée le plus simple de la bibliothèque. Il tient sur une seule ligne conceptuelle : on lui donne une fonction fn, une liste d'entrées inputs et une liste de sorties outputs. Gradio se charge de générer une page web qui présente les composants d'entrée à gauche, appelle la fonction quand l'utilisateur clique sur « Envoyer », et affiche à droite ce que la fonction a retourné.

La fonction reste une fonction Python ordinaire. Elle est appelée dans le processus qui a lancé l'interface, elle a accès aux mêmes objets globaux (modèle chargé, pipeline, connexion à une base), et elle peut retourner n'importe quel type que Gradio sait afficher. Cette contrainte est libératrice : votre code de démonstration ne mélange plus la logique du modèle avec la mécanique de l'interface. Vous écrivez la fonction que vous auriez de toute façon écrite, puis vous l'exposez.

Le premier exemple canonique tient en cinq lignes et sert de test d'installation.

import gradio as gr

def saluer(nom):
return f"Bonjour {nom}, ravi de vous voir sur Gradio."

demo = gr.Interface(fn=saluer, inputs="text", outputs="text")
demo.launch()

L'ouverture d'un navigateur sur http://127.0.0.1:7860 révèle deux zones : une boîte de texte à gauche, une boîte de texte à droite, et un bouton « Envoyer » entre les deux. C'est peu spectaculaire, mais c'est déjà une application web complète, servie par le serveur Uvicorn intégré à Gradio.

La correspondance entre types Python et composants

Les chaînes "text", "image", "audio", "video", "number", "checkbox", "slider" sont des raccourcis. Elles pointent vers des classes réelles — gr.Textbox, gr.Image, gr.Audio, gr.Video, gr.Number, gr.Checkbox, gr.Slider — qui exposent bien plus d'options : étiquette, valeur par défaut, plage, format attendu. Utiliser la classe explicite dès qu'on veut personnaliser est une bonne habitude. Utiliser le raccourci convient pour les brouillons et les démonstrations de laboratoire.

Chaque composant a un type d'entrée pour la fonction et un type de sortie pour l'affichage qui lui sont propres. Un gr.Image sans paramètre supplémentaire livre à votre fonction un tableau NumPy de forme (H, W, 3), c'est-à-dire une image RGB déjà décodée. Un gr.Audio livre par défaut un couple (fréquence, tableau). Un gr.Slider livre un flottant. Un gr.Textbox livre une chaîne. Ces types sont documentés dans le module 2 et forment l'une des sources d'erreur les plus fréquentes des débutants.

Un classificateur d'images en dix lignes

Le fil rouge de ce cours démarre ici. Nous prenons un classificateur d'images entraîné dans le cours 10 (ResNet18 sur ImageNet), et nous l'exposons sans réentraînement, avec exactement dix lignes de code utiles.

import gradio as gr
import torch
from torchvision import models, transforms

modele = models.resnet18(weights=models.ResNet18_Weights.DEFAULT).eval()
etiquettes = models.ResNet18_Weights.DEFAULT.meta["categories"]
pretraitement = models.ResNet18_Weights.DEFAULT.transforms()

def classer(image):
lot = pretraitement(image).unsqueeze(0)
with torch.no_grad():
scores = modele(lot).softmax(dim=1)[0]
top = torch.topk(scores, k=3)
return {etiquettes[i]: float(p) for i, p in zip(top.indices, top.values)}

demo = gr.Interface(
fn=classer,
inputs=gr.Image(type="pil"),
outputs=gr.Label(num_top_classes=3),
title="Classificateur d'images (ResNet18)",
description="Déposez une image ou cliquez pour la prendre depuis votre appareil photo. Le modèle retourne les trois catégories les plus probables.",
)
demo.launch()

Deux détails méritent d'être soulignés. Le paramètre type="pil" du composant gr.Image demande à Gradio de livrer à la fonction non pas un tableau NumPy mais un objet PIL.Image, ce qui est exactement ce que pretraitement (de torchvision) attend. Le composant gr.Label est le pendant naturel d'une classification : il attend un dictionnaire {étiquette: probabilité} et affiche une barre pour chacune, triée par probabilité décroissante. Ce couple gr.Image + gr.Label est la signature visuelle d'une démonstration de classification d'images en Gradio, et vous la reconnaîtrez dans presque tous les espaces Hugging Face de vision.

Titre, description, article : les métadonnées qui rendent une démo présentable

gr.Interface accepte trois paramètres textuels qui transforment un jouet en démonstration prête à partager. Le title s'affiche en haut, en grande police. La description s'affiche juste en dessous, avant les composants, et sert à expliquer ce que fait la démonstration ainsi qu'à donner une consigne d'usage (« déposez une image contenant un seul objet principal »). L'article, souvent oublié, s'affiche sous les composants et supporte le Markdown : c'est l'endroit naturel pour créditer les auteurs du modèle, préciser les données d'entraînement, ou mentionner une limitation connue.

Rédiger ces trois zones dès le premier lancement

Les négliger et se dire « je remplirai plus tard » est le meilleur moyen d'oublier. Une démonstration sans titre ni description reçoit systématiquement des retours du type « je ne comprends pas ce que ça fait ». Cinq minutes de rédaction claire économisent trente minutes de messages Slack.

Lancer, arrêter, relancer

demo.launch() démarre un serveur en avant-plan. Dans un notebook, il rend la cellule bloquante et affiche l'interface dans une iframe. Dans un script, il ouvre le navigateur et attend indéfiniment. Deux paramètres reviennent constamment. server_port=7860 fixe le port ; sans lui, Gradio incrémente automatiquement en cas de conflit, ce qui casse les liens partagés. server_name="0.0.0.0" fait écouter sur toutes les interfaces réseau, ce qui est nécessaire pour un accès depuis un autre appareil de votre réseau local mais dangereux sur une machine exposée à Internet.

Pour arrêter proprement une démonstration dans un notebook, on utilise demo.close(). Sans cela, une nouvelle exécution de la cellule tente de rouvrir un port déjà occupé et échoue avec un message peu explicite. Ce réflexe évite des redémarrages de noyau à répétition.

En résumé

  • gr.Interface(fn, inputs, outputs) traduit une fonction Python en interface web avec un serveur intégré, en quelques lignes ; la fonction reste ordinaire et ne mélange pas la logique et l'affichage.
  • Les raccourcis "text", "image", "audio" pointent vers des classes (gr.Textbox, gr.Image, gr.Audio) qu'il faut utiliser explicitement dès qu'on veut personnaliser un type d'entrée ou une étiquette.
  • Le duo gr.Image(type="pil") + gr.Label(num_top_classes=3) est la signature d'une démonstration de classification d'images ; la fonction reçoit une image PIL, la sortie attend un dictionnaire probabilité par étiquette.
  • title, description et article transforment une preuve technique en démonstration présentable ; les rédiger dès le premier lancement évite les mêmes questions répétées.

Le module suivant détaille les composants pour texte, image, audio et vidéo, avec un accent particulier sur le format exact que reçoit votre fonction pour chacun — la source d'erreur la plus fréquente en Gradio.