Gradio, Création d'interface Utilisation Machine Learning
Commencer
Prérequis : Python 3.7+ et c'est tout !
Prérequis : Python 3.7+ et c'est tout !
Démarrage rapide
Pour faire fonctionner Gradio avec un exemple simple "Hello, World", suivez ces trois étapes :
1. Installez Gradio à partir de pip.
pip install gradio
2. Exécutez le code ci-dessous en tant que script Python ou dans un notebook Python (ou dans un notebook Colab ).
import gradio as gr
def greet(name):
return "Hello " + name + "!!"
iface = gr.Interface(fn=greet, inputs="text", outputs="text")
iface.launch()
3. L'interface ci-dessous apparaîtra automatiquement dans le bloc-notes Python ou apparaîtra dans un navigateur sur http://localhost:7860 si elle est exécutée à partir d'un script.
NOM
Pour faire fonctionner Gradio avec un exemple simple "Hello, World", suivez ces trois étapes :
1. Installez Gradio à partir de pip.
pip install gradio
2. Exécutez le code ci-dessous en tant que script Python ou dans un notebook Python (ou dans un notebook Colab ).
import gradio as gr
def greet(name):
return "Hello " + name + "!!"
iface = gr.Interface(fn=greet, inputs="text", outputs="text")
iface.launch()
3. L'interface ci-dessous apparaîtra automatiquement dans le bloc-notes Python ou apparaîtra dans un navigateur sur http://localhost:7860 si elle est exécutée à partir d'un script.
Comprendre la Interface
classe
Gradio peut envelopper presque toutes les fonctions Python avec une interface utilisateur facile à utiliser. Dans l'exemple ci-dessus, nous avons vu une fonction textuelle simple. Mais la fonction peut être n'importe quoi, du rehausseur d'image à un calculateur d'impôts en passant (le plus souvent) par la fonction de prédiction d'un modèle d'apprentissage automatique pré-entraîné.
La classe core Interface
est initialisée avec trois paramètres :
fn
: la fonction pour envelopperinputs
: le ou les types de composants d'entrée, par exemple "image"
ou "audio"
( voir la documentation pour la liste complète )outputs
: le ou les types de composants de sortie, par exemple "image"
ou "label"
( voir la documentation pour la liste complète )
Avec ces trois arguments, on peut créer rapidement des interfaces et launch()
les. Mais que se passe-t-il si vous souhaitez modifier l'apparence ou le comportement des composants de l'interface utilisateur ?
Gradio peut envelopper presque toutes les fonctions Python avec une interface utilisateur facile à utiliser. Dans l'exemple ci-dessus, nous avons vu une fonction textuelle simple. Mais la fonction peut être n'importe quoi, du rehausseur d'image à un calculateur d'impôts en passant (le plus souvent) par la fonction de prédiction d'un modèle d'apprentissage automatique pré-entraîné.
La classe core Interface
est initialisée avec trois paramètres :
fn
: la fonction pour envelopperinputs
: le ou les types de composants d'entrée, par exemple"image"
ou"audio"
( voir la documentation pour la liste complète )outputs
: le ou les types de composants de sortie, par exemple"image"
ou"label"
( voir la documentation pour la liste complète )
Avec ces trois arguments, on peut créer rapidement des interfaces et launch()
les. Mais que se passe-t-il si vous souhaitez modifier l'apparence ou le comportement des composants de l'interface utilisateur ?
Composants personnalisables
Disons que nous voulons personnaliser le champ de saisie de texte - par exemple, nous voulions qu'il soit plus grand et qu'il ait un indice de texte. Si nous utilisons la classe d'entrée réelle pour Textbox
au lieu d'utiliser le raccourci de chaîne, nous avons accès à beaucoup plus de personnalisation. Pour voir une liste de tous les composants que nous prenons en charge et comment vous pouvez les personnaliser, consultez les Docs .
import gradio as gr
def greet(name):
return "Hello " + name + "!"
iface = gr.Interface(
fn=greet,
inputs=gr.inputs.Textbox(lines=2, placeholder="Name Here..."),
outputs="text",
)
iface.launch()
NOM
Disons que nous voulons personnaliser le champ de saisie de texte - par exemple, nous voulions qu'il soit plus grand et qu'il ait un indice de texte. Si nous utilisons la classe d'entrée réelle pour Textbox
au lieu d'utiliser le raccourci de chaîne, nous avons accès à beaucoup plus de personnalisation. Pour voir une liste de tous les composants que nous prenons en charge et comment vous pouvez les personnaliser, consultez les Docs .
import gradio as gr
def greet(name):
return "Hello " + name + "!"
iface = gr.Interface(
fn=greet,
inputs=gr.inputs.Textbox(lines=2, placeholder="Name Here..."),
outputs="text",
)
iface.launch()
Entrées et sorties multiples
Disons que nous avions une fonction beaucoup plus complexe, avec plusieurs entrées et sorties. Dans l'exemple ci-dessous, nous avons une fonction qui prend une chaîne, un booléen et un nombre, et renvoie une chaîne et un nombre. Regardez comment nous passons une liste de composants d'entrée et de sortie.
import gradio as gr
def greet(name, is_morning, temperature):
salutation = "Good morning" if is_morning else "Good evening"
greeting = "%s %s. It is %s degrees today" % (salutation, name, temperature)
celsius = (temperature - 32) * 5 / 9
return greeting, round(celsius, 2)
iface = gr.Interface(
fn=greet,
inputs=["text", "checkbox", gr.inputs.Slider(0, 100)],
outputs=["text", "number"],
)
iface.launch()
NOMEST LE MATINTEMPÉRATURENous enveloppons simplement les composants dans une liste. Chaque composant de la inputs
liste correspond à un des paramètres de la fonction, dans l'ordre. Chaque composant de la outputs
liste correspond à l'une des valeurs renvoyées par la fonction, toujours dans l'ordre.
Disons que nous avions une fonction beaucoup plus complexe, avec plusieurs entrées et sorties. Dans l'exemple ci-dessous, nous avons une fonction qui prend une chaîne, un booléen et un nombre, et renvoie une chaîne et un nombre. Regardez comment nous passons une liste de composants d'entrée et de sortie.
import gradio as gr
def greet(name, is_morning, temperature):
salutation = "Good morning" if is_morning else "Good evening"
greeting = "%s %s. It is %s degrees today" % (salutation, name, temperature)
celsius = (temperature - 32) * 5 / 9
return greeting, round(celsius, 2)
iface = gr.Interface(
fn=greet,
inputs=["text", "checkbox", gr.inputs.Slider(0, 100)],
outputs=["text", "number"],
)
iface.launch()
Nous enveloppons simplement les composants dans une liste. Chaque composant de la inputs
liste correspond à un des paramètres de la fonction, dans l'ordre. Chaque composant de la outputs
liste correspond à l'une des valeurs renvoyées par la fonction, toujours dans l'ordre.
Travailler avec des images
Essayons une fonction image à image. Lors de l'utilisation du Image
composant, votre fonction recevra un tableau numpy de la taille que vous avez spécifiée, avec la forme (width, height, 3)
, où la dernière dimension représente les valeurs RVB. Nous renverrons également une image sous la forme d'un tableau numpy.
import numpy as np
import gradio as gr
def sepia(input_img):
sepia_filter = np.array(
[[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]
)
sepia_img = input_img.dot(sepia_filter.T)
sepia_img /= sepia_img.max()
return sepia_img
iface = gr.Interface(sepia, gr.inputs.Image(shape=(200, 200)), "image")
iface.launch()
IMAGE D'ENTRÉEDéposer l'Image Ici- ou -Cliquer pour Télécharger
De plus, notre Image
interface de saisie est dotée d'un bouton "Modifier" qui ouvre des outils pour recadrer, retourner, faire pivoter, dessiner et appliquer des filtres aux images. Nous avons constaté que la manipulation d'images de cette manière révèle souvent des défauts cachés dans un modèle.
En plus des images, Gradio prend en charge d'autres types d'entrée multimédia, tels que les téléchargements audio ou vidéo, ainsi que de nombreux composants de sortie. Lisez à ce sujet dans les Docs .
Essayons une fonction image à image. Lors de l'utilisation du Image
composant, votre fonction recevra un tableau numpy de la taille que vous avez spécifiée, avec la forme (width, height, 3)
, où la dernière dimension représente les valeurs RVB. Nous renverrons également une image sous la forme d'un tableau numpy.
import numpy as np
import gradio as gr
def sepia(input_img):
sepia_filter = np.array(
[[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]
)
sepia_img = input_img.dot(sepia_filter.T)
sepia_img /= sepia_img.max()
return sepia_img
iface = gr.Interface(sepia, gr.inputs.Image(shape=(200, 200)), "image")
iface.launch()
De plus, notre Image
interface de saisie est dotée d'un bouton "Modifier" qui ouvre des outils pour recadrer, retourner, faire pivoter, dessiner et appliquer des filtres aux images. Nous avons constaté que la manipulation d'images de cette manière révèle souvent des défauts cachés dans un modèle.
En plus des images, Gradio prend en charge d'autres types d'entrée multimédia, tels que les téléchargements audio ou vidéo, ainsi que de nombreux composants de sortie. Lisez à ce sujet dans les Docs .
Travailler avec des DataFrames et des graphiques
Vous pouvez utiliser Gradio pour prendre en charge les entrées et les sorties de vos bibliothèques de données typiques, telles que les tableaux numpy, les cadres de données pandas et les graphiques de tracé. Jetez un œil à la démo ci-dessous (ignorez la manipulation compliquée des données dans la fonction !)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import gradio as gr
def sales_projections(employee_data):
sales_data = employee_data.iloc[:, 1:4].astype("int").to_numpy()
regression_values = np.apply_along_axis(
lambda row: np.array(np.poly1d(np.polyfit([0, 1, 2], row, 2))), 0, sales_data
)
projected_months = np.repeat(
np.expand_dims(np.arange(3, 12), 0), len(sales_data), axis=0
)
projected_values = np.array(
[
month * month * regression[0] + month * regression[1] + regression[2]
for month, regression in zip(projected_months, regression_values)
]
)
plt.plot(projected_values.T)
plt.legend(employee_data["Name"])
return employee_data, plt.gcf(), regression_values
iface = gr.Interface(
sales_projections,
gr.inputs.Dataframe(
headers=["Name", "Jan Sales", "Feb Sales", "Mar Sales"],
default=[["Jon", 12, 14, 18], ["Alice", 14, 17, 2], ["Sana", 8, 9.5, 12]],
),
["dataframe", "plot", "numpy"],
description="Enter sales figures for employees to predict sales trajectory over year.",
)
iface.launch()
Entrez les chiffres de vente des employés pour prédire la trajectoire des ventes sur l'année.
DONNÉES DES EMPLOYÉS
Vous pouvez utiliser Gradio pour prendre en charge les entrées et les sorties de vos bibliothèques de données typiques, telles que les tableaux numpy, les cadres de données pandas et les graphiques de tracé. Jetez un œil à la démo ci-dessous (ignorez la manipulation compliquée des données dans la fonction !)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import gradio as gr
def sales_projections(employee_data):
sales_data = employee_data.iloc[:, 1:4].astype("int").to_numpy()
regression_values = np.apply_along_axis(
lambda row: np.array(np.poly1d(np.polyfit([0, 1, 2], row, 2))), 0, sales_data
)
projected_months = np.repeat(
np.expand_dims(np.arange(3, 12), 0), len(sales_data), axis=0
)
projected_values = np.array(
[
month * month * regression[0] + month * regression[1] + regression[2]
for month, regression in zip(projected_months, regression_values)
]
)
plt.plot(projected_values.T)
plt.legend(employee_data["Name"])
return employee_data, plt.gcf(), regression_values
iface = gr.Interface(
sales_projections,
gr.inputs.Dataframe(
headers=["Name", "Jan Sales", "Feb Sales", "Mar Sales"],
default=[["Jon", 12, 14, 18], ["Alice", 14, 17, 2], ["Sana", 8, 9.5, 12]],
),
["dataframe", "plot", "numpy"],
description="Enter sales figures for employees to predict sales trajectory over year.",
)
iface.launch()
Entrez les chiffres de vente des employés pour prédire la trajectoire des ventes sur l'année.
Exemples d'entrées
Vous pouvez fournir des exemples de données qu'un utilisateur peut facilement charger dans le modèle. Cela peut être utile pour démontrer les types d'entrées que le modèle attend, ainsi que pour fournir un moyen d'explorer votre jeu de données en conjonction avec votre modèle. Pour charger des exemples de données, vous fournissez une liste imbriquée à l' examples=
argument de mot-clé du constructeur Interface. Chaque sous-liste dans la liste externe représente un échantillon de données, et chaque élément dans la sous-liste représente une entrée pour chaque composant d'entrée. Le format des exemples de données pour chaque composant est spécifié dans les Docs .
import gradio as gr
def calculator(num1, operation, num2):
if operation == "add":
return num1 + num2
elif operation == "subtract":
return num1 - num2
elif operation == "multiply":
return num1 * num2
elif operation == "divide":
return num1 / num2
iface = gr.Interface(
calculator,
["number", gr.inputs.Radio(["add", "subtract", "multiply", "divide"]), "number"],
"number",
examples=[
[5, "add", 3],
[4, "divide", 2],
[-4, "multiply", 2.5],
[0, "subtract", 1.2],
],
title="test calculator",
description="heres a sample toy calculator. enjoy!",
flagging_options=["this", "or", "that"],
)
iface.launch()
Vous pouvez fournir des exemples de données qu'un utilisateur peut facilement charger dans le modèle. Cela peut être utile pour démontrer les types d'entrées que le modèle attend, ainsi que pour fournir un moyen d'explorer votre jeu de données en conjonction avec votre modèle. Pour charger des exemples de données, vous fournissez une liste imbriquée à l' examples=
argument de mot-clé du constructeur Interface. Chaque sous-liste dans la liste externe représente un échantillon de données, et chaque élément dans la sous-liste représente une entrée pour chaque composant d'entrée. Le format des exemples de données pour chaque composant est spécifié dans les Docs .
import gradio as gr
def calculator(num1, operation, num2):
if operation == "add":
return num1 + num2
elif operation == "subtract":
return num1 - num2
elif operation == "multiply":
return num1 * num2
elif operation == "divide":
return num1 / num2
iface = gr.Interface(
calculator,
["number", gr.inputs.Radio(["add", "subtract", "multiply", "divide"]), "number"],
"number",
examples=[
[5, "add", 3],
[4, "divide", 2],
[-4, "multiply", 2.5],
[0, "subtract", 1.2],
],
title="test calculator",
description="heres a sample toy calculator. enjoy!",
flagging_options=["this", "or", "that"],
)
iface.launch()
calculatrice d'essai
voici un exemple de calculatrice jouet. prendre plaisir!
NUM1OPÉRATIONNUM2
voici un exemple de calculatrice jouet. prendre plaisir!
Exemples
num1 opération num2 5 ajouter 3 4 diviser 2 -4 multiplier 2.5 0 soustraire 1.2
Vous pouvez charger un grand ensemble de données dans les exemples pour parcourir et interagir avec l'ensemble de données via Gradio. Les exemples seront automatiquement paginés (vous pouvez le configurer via l' examples_per_page
argument de l'interface) et vous pouvez utiliser les touches fléchées CTRL + pour naviguer rapidement dans les exemples.
num1 | opération | num2 |
---|---|---|
5 | ajouter | 3 |
4 | diviser | 2 |
-4 | multiplier | 2.5 |
0 | soustraire | 1.2 |
Vous pouvez charger un grand ensemble de données dans les exemples pour parcourir et interagir avec l'ensemble de données via Gradio. Les exemples seront automatiquement paginés (vous pouvez le configurer via l' examples_per_page
argument de l'interface) et vous pouvez utiliser les touches fléchées CTRL + pour naviguer rapidement dans les exemples.
Interfaces en direct
Vous pouvez faire en sorte que les interfaces s'actualisent automatiquement en définissant live=True
dans l'interface. Maintenant, l'interface recalculera dès que l'entrée de l'utilisateur changera.
import gradio as gr
def calculator(num1, operation, num2):
if operation == "add":
return num1 + num2
elif operation == "subtract":
return num1 - num2
elif operation == "multiply":
return num1 * num2
elif operation == "divide":
return num1 / num2
iface = gr.Interface(
calculator,
["number", gr.inputs.Radio(["add", "subtract", "multiply", "divide"]), "number"],
"number",
live=True,
)
iface.launch()
NUM1OPÉRATIONNUM2Notez qu'il n'y a pas de bouton de soumission, car l'interface se soumet à nouveau automatiquement en cas de modification.
Vous pouvez faire en sorte que les interfaces s'actualisent automatiquement en définissant live=True
dans l'interface. Maintenant, l'interface recalculera dès que l'entrée de l'utilisateur changera.
import gradio as gr
def calculator(num1, operation, num2):
if operation == "add":
return num1 + num2
elif operation == "subtract":
return num1 - num2
elif operation == "multiply":
return num1 * num2
elif operation == "divide":
return num1 / num2
iface = gr.Interface(
calculator,
["number", gr.inputs.Radio(["add", "subtract", "multiply", "divide"]), "number"],
"number",
live=True,
)
iface.launch()
Notez qu'il n'y a pas de bouton de soumission, car l'interface se soumet à nouveau automatiquement en cas de modification.
Utilisation de l'état
Votre fonction peut utiliser des données qui persistent au-delà d'un seul appel de fonction. Si les données sont accessibles à tous les appels de fonction et à tous les utilisateurs, vous pouvez créer une variable globale en dehors de l'appel de fonction et y accéder à l'intérieur de la fonction. Par exemple, vous pouvez charger un grand modèle en dehors de la fonction et l'utiliser à l'intérieur de la fonction afin que chaque appel de fonction n'ait pas besoin de recharger le modèle.
Un autre type de persistance des données pris en charge par Gradio est l'état de session , où les données persistent sur plusieurs envois au sein d'un chargement de page. Cependant, les données ne sont pas partagées entre les différents utilisateurs de votre modèle. Pour stocker des données dans un état de session, vous devez faire trois choses : (1) Passer un paramètre supplémentaire dans votre fonction, qui représente l'état de l'interface. (2) À la fin de la fonction, renvoyez la valeur mise à jour de l'état en tant que valeur de retour supplémentaire (3) Ajoutez les composants 'state'
d'entrée et 'state'
de sortie lors de la création de votre fichier Interface
. Voir l'exemple de chatbot ci-dessous :
import random
import gradio as gr
def chat(message, history):
history = history or []
if message.startswith("How many"):
response = random.randint(1, 10)
elif message.startswith("How"):
response = random.choice(["Great", "Good", "Okay", "Bad"])
elif message.startswith("Where"):
response = random.choice(["Here", "There", "Somewhere"])
else:
response = "I don't know"
history.append((message, response))
return history, history
iface = gr.Interface(
chat,
["text", "state"],
["chatbot", "state"],
allow_screenshot=False,
allow_flagging="never",
)
iface.launch()
MESSAGERemarquez comment l'état persiste à travers les envois au sein de chaque page, mais l'état n'est pas partagé entre les deux pages. Quelques points supplémentaires à noter : vous pouvez passer une valeur par défaut au paramètre d'état, qui est utilisé comme valeur initiale de l'état. L'état doit être quelque chose qui peut être sérialisé au format JSON (par exemple, un dictionnaire, une liste ou une valeur unique. En règle générale, les objets ne fonctionneront pas).
Votre fonction peut utiliser des données qui persistent au-delà d'un seul appel de fonction. Si les données sont accessibles à tous les appels de fonction et à tous les utilisateurs, vous pouvez créer une variable globale en dehors de l'appel de fonction et y accéder à l'intérieur de la fonction. Par exemple, vous pouvez charger un grand modèle en dehors de la fonction et l'utiliser à l'intérieur de la fonction afin que chaque appel de fonction n'ait pas besoin de recharger le modèle.
Un autre type de persistance des données pris en charge par Gradio est l'état de session , où les données persistent sur plusieurs envois au sein d'un chargement de page. Cependant, les données ne sont pas partagées entre les différents utilisateurs de votre modèle. Pour stocker des données dans un état de session, vous devez faire trois choses : (1) Passer un paramètre supplémentaire dans votre fonction, qui représente l'état de l'interface. (2) À la fin de la fonction, renvoyez la valeur mise à jour de l'état en tant que valeur de retour supplémentaire (3) Ajoutez les composants 'state'
d'entrée et 'state'
de sortie lors de la création de votre fichier Interface
. Voir l'exemple de chatbot ci-dessous :
import random
import gradio as gr
def chat(message, history):
history = history or []
if message.startswith("How many"):
response = random.randint(1, 10)
elif message.startswith("How"):
response = random.choice(["Great", "Good", "Okay", "Bad"])
elif message.startswith("Where"):
response = random.choice(["Here", "There", "Somewhere"])
else:
response = "I don't know"
history.append((message, response))
return history, history
iface = gr.Interface(
chat,
["text", "state"],
["chatbot", "state"],
allow_screenshot=False,
allow_flagging="never",
)
iface.launch()
Remarquez comment l'état persiste à travers les envois au sein de chaque page, mais l'état n'est pas partagé entre les deux pages. Quelques points supplémentaires à noter : vous pouvez passer une valeur par défaut au paramètre d'état, qui est utilisé comme valeur initiale de l'état. L'état doit être quelque chose qui peut être sérialisé au format JSON (par exemple, un dictionnaire, une liste ou une valeur unique. En règle générale, les objets ne fonctionneront pas).
Signalement
Sous les interfaces de sortie, il y a un bouton marqué "Flag". Lorsqu'un utilisateur testant votre modèle voit une entrée avec une sortie intéressante, comme un comportement de modèle erroné ou inattendu, il peut signaler l'entrée pour que le créateur de l'interface l'examine. Dans le répertoire fourni par l' flagging_dir=
argument au constructeur d'interface, un fichier CSV enregistrera les entrées marquées. Si l'interface implique des données de fichier, comme pour les composants Image et Audio, des dossiers seront également créés pour stocker ces données marquées.
Par exemple, avec l'interface de la calculatrice illustrée ci-dessus, les données signalées seraient stockées dans le répertoire signalé ci-dessous :
+-- calculator.py
+-- flagged/
| +-- logs.csv
marqué/logs.csv
num1,operation,num2,Output
5,add,7,12
6,subtract,1.5,4.5
Avec l'interface sépia illustrée ci-dessus, nous aurions les données signalées stockées dans le répertoire signalé ci-dessous :
+-- sepia.py
+-- flagged/
| +-- logs.csv
| +-- im/
| | +-- 0.png
| | +-- 1.png
| +-- Output/
| | +-- 0.png
| | +-- 1.png
marqué/logs.csv
im,Output
im/0.png,Output/0.png
im/1.png,Output/1.png
Vous pouvez passer en revue ces entrées signalées en explorant manuellement le répertoire de signalisation ou les charger dans les exemples de l'interface Gradio en pointant l' examples=
argument vers le répertoire marqué. Si vous souhaitez que l'utilisateur fournisse une raison pour le signalement, vous pouvez passer une liste de chaînes à l' flagging_options
argument de Interface. Les utilisateurs devront sélectionner l'une des chaînes lors du marquage, qui sera enregistrée en tant que colonne supplémentaire dans le CSV.
Sous les interfaces de sortie, il y a un bouton marqué "Flag". Lorsqu'un utilisateur testant votre modèle voit une entrée avec une sortie intéressante, comme un comportement de modèle erroné ou inattendu, il peut signaler l'entrée pour que le créateur de l'interface l'examine. Dans le répertoire fourni par l' flagging_dir=
argument au constructeur d'interface, un fichier CSV enregistrera les entrées marquées. Si l'interface implique des données de fichier, comme pour les composants Image et Audio, des dossiers seront également créés pour stocker ces données marquées.
Par exemple, avec l'interface de la calculatrice illustrée ci-dessus, les données signalées seraient stockées dans le répertoire signalé ci-dessous :
+-- calculator.py
+-- flagged/
| +-- logs.csv
marqué/logs.csv
num1,operation,num2,Output
5,add,7,12
6,subtract,1.5,4.5
Avec l'interface sépia illustrée ci-dessus, nous aurions les données signalées stockées dans le répertoire signalé ci-dessous :
+-- sepia.py
+-- flagged/
| +-- logs.csv
| +-- im/
| | +-- 0.png
| | +-- 1.png
| +-- Output/
| | +-- 0.png
| | +-- 1.png
marqué/logs.csv
im,Output
im/0.png,Output/0.png
im/1.png,Output/1.png
Vous pouvez passer en revue ces entrées signalées en explorant manuellement le répertoire de signalisation ou les charger dans les exemples de l'interface Gradio en pointant l' examples=
argument vers le répertoire marqué. Si vous souhaitez que l'utilisateur fournisse une raison pour le signalement, vous pouvez passer une liste de chaînes à l' flagging_options
argument de Interface. Les utilisateurs devront sélectionner l'une des chaînes lors du marquage, qui sera enregistrée en tant que colonne supplémentaire dans le CSV.
Partage d'interfaces publiquement
Les interfaces peuvent être facilement partagées publiquement en définissant share=True
la launch()
méthode. Comme ça:
gr.Interface(classify_image, "image", "label").launch(share=True)
Cela génère un lien public et partageable que vous pouvez envoyer à n'importe qui ! Lorsque vous envoyez ce lien, l'utilisateur de l'autre côté peut essayer le modèle dans son navigateur. Étant donné que le traitement se produit sur votre appareil (tant que votre appareil reste allumé !), Vous n'avez pas à vous soucier de l'empaquetage des dépendances. Si vous travaillez à partir d'un bloc-notes Colab, un lien de partage est toujours créé automatiquement. Il ressemble généralement à ceci : XXXXX.gradio.app . Bien que le lien soit servi via un lien gradio, nous ne sommes qu'un proxy pour votre serveur local et ne stockons aucune donnée envoyée via les interfaces.
Gardez à l'esprit, cependant, que ces liens sont accessibles au public, ce qui signifie que n'importe qui peut utiliser votre modèle pour la prédiction ! Par conséquent, assurez-vous de ne pas exposer d'informations sensibles via les fonctions que vous écrivez, ou de permettre à des modifications critiques de se produire sur votre appareil. Si vous définissez share=False
(par défaut), seul un lien local est créé, qui peut être partagé par redirection de port avec des utilisateurs spécifiques.
Les liens de partage expirent après 72 heures. Pour un hébergement permanent, voir Hébergement des applications Gradio sur les espaces ci-dessous.
Les interfaces peuvent être facilement partagées publiquement en définissant share=True
la launch()
méthode. Comme ça:
gr.Interface(classify_image, "image", "label").launch(share=True)
Cela génère un lien public et partageable que vous pouvez envoyer à n'importe qui ! Lorsque vous envoyez ce lien, l'utilisateur de l'autre côté peut essayer le modèle dans son navigateur. Étant donné que le traitement se produit sur votre appareil (tant que votre appareil reste allumé !), Vous n'avez pas à vous soucier de l'empaquetage des dépendances. Si vous travaillez à partir d'un bloc-notes Colab, un lien de partage est toujours créé automatiquement. Il ressemble généralement à ceci : XXXXX.gradio.app . Bien que le lien soit servi via un lien gradio, nous ne sommes qu'un proxy pour votre serveur local et ne stockons aucune donnée envoyée via les interfaces.
Gardez à l'esprit, cependant, que ces liens sont accessibles au public, ce qui signifie que n'importe qui peut utiliser votre modèle pour la prédiction ! Par conséquent, assurez-vous de ne pas exposer d'informations sensibles via les fonctions que vous écrivez, ou de permettre à des modifications critiques de se produire sur votre appareil. Si vous définissez share=False
(par défaut), seul un lien local est créé, qui peut être partagé par redirection de port avec des utilisateurs spécifiques.
Les liens de partage expirent après 72 heures. Pour un hébergement permanent, voir Hébergement des applications Gradio sur les espaces ci-dessous.
Hébergement des applications Gradio sur les espaces
Huggingface fournit l'infrastructure pour héberger en permanence votre modèle Gradio sur Internet, gratuitement ! Vous pouvez soit faire glisser et déposer un dossier contenant votre modèle Gradio et tous les fichiers associés, soit pointer HF Spaces vers votre référentiel Git et HP Spaces extraira l'interface Gradio à partir de là. Voir Espaces Huggingface pour plus d'informations.
Huggingface fournit l'infrastructure pour héberger en permanence votre modèle Gradio sur Internet, gratuitement ! Vous pouvez soit faire glisser et déposer un dossier contenant votre modèle Gradio et tous les fichiers associés, soit pointer HF Spaces vers votre référentiel Git et HP Spaces extraira l'interface Gradio à partir de là. Voir Espaces Huggingface pour plus d'informations.
Fonctionnalités avancées
Ici, nous passons en revue plusieurs fonctionnalités avancées que votre démo Gradio peut inclure sans que vous ayez besoin d'écrire beaucoup plus de code !
Ici, nous passons en revue plusieurs fonctionnalités avancées que votre démo Gradio peut inclure sans que vous ayez besoin d'écrire beaucoup plus de code !
Authentification
Vous pouvez souhaiter mettre une page d'authentification devant votre interface pour limiter qui peut ouvrir votre interface. Avec l' auth=
argument de mot-clé dans la launch()
méthode, vous pouvez passer une liste de tuples de nom d'utilisateur/mot de passe acceptables ; ou, pour une gestion d'authentification plus complexe, vous pouvez même passer une fonction qui prend un nom d'utilisateur et un mot de passe comme arguments, et renvoie True pour autoriser l'authentification, False sinon. Voici un exemple qui fournit une authentification par mot de passe pour un seul utilisateur nommé "admin" :
gr.Interface(fn=classify_image, inputs=image, outputs=label).launch(auth=("admin", "pass1234"))
Vous pouvez souhaiter mettre une page d'authentification devant votre interface pour limiter qui peut ouvrir votre interface. Avec l' auth=
argument de mot-clé dans la launch()
méthode, vous pouvez passer une liste de tuples de nom d'utilisateur/mot de passe acceptables ; ou, pour une gestion d'authentification plus complexe, vous pouvez même passer une fonction qui prend un nom d'utilisateur et un mot de passe comme arguments, et renvoie True pour autoriser l'authentification, False sinon. Voici un exemple qui fournit une authentification par mot de passe pour un seul utilisateur nommé "admin" :
gr.Interface(fn=classify_image, inputs=image, outputs=label).launch(auth=("admin", "pass1234"))
Interpréter vos prédictions
La plupart des modèles sont des boîtes noires telles que la logique interne de la fonction est cachée à l'utilisateur final. Pour encourager la transparence, nous avons simplifié l'ajout d'interprétation à votre modèle en définissant simplement le mot- interpretation
clé de la Interface
classe sur default
. Cela permet à vos utilisateurs de comprendre quelles parties de l'entrée sont responsables de la sortie. Jetez un œil à l'interface simple ci-dessous qui montre un classificateur d'image qui inclut également l'interprétation :
import requests
import tensorflow as tf
import gradio as gr
inception_net = tf.keras.applications.MobileNetV2() # load the model
# Download human-readable labels for ImageNet.
response = requests.get("https://git.io/JJkYN")
labels = response.text.split("\n")
def classify_image(inp):
inp = inp.reshape((-1, 224, 224, 3))
inp = tf.keras.applications.mobilenet_v2.preprocess_input(inp)
prediction = inception_net.predict(inp).flatten()
return {labels[i]: float(prediction[i]) for i in range(1000)}
image = gr.inputs.Image(shape=(224, 224))
label = gr.outputs.Label(num_top_classes=3)
gr.Interface(
fn=classify_image, inputs=image, outputs=label, interpretation="default"
).launch()
En plus de default
, Gradio inclut également une interprétation basée sur Shapley , qui fournit des interprétations plus précises, bien que généralement avec une durée d'exécution plus lente. Pour l'utiliser, définissez simplement le interpretation
paramètre sur "shap"
(remarque : assurez-vous également que le package python shap
est installé). Facultativement, vous pouvez modifier le num_shap
paramètre, qui contrôle le compromis entre la précision et la durée d'exécution (l'augmentation de cette valeur augmente généralement la précision). Voici un exemple:
gr.Interface(fn=classify_image, inputs=image, outputs=label, interpretation="shap", num_shap=5).launch()
Cela fonctionnera pour n'importe quelle fonction, même si en interne, le modèle est un réseau neuronal complexe ou une autre boîte noire. Si vous utilisez l'interprétation de Gradio default
ou shap
, le composant de sortie doit être un fichier Label
. Tous les composants d'entrée courants sont pris en charge. Voici un exemple avec saisie de texte.
import re
import gradio as gr
male_words, female_words = ["he", "his", "him"], ["she", "hers", "her"]
def gender_of_sentence(sentence):
male_count = len([word for word in sentence.split() if word.lower() in male_words])
female_count = len(
[word for word in sentence.split() if word.lower() in female_words]
)
total = max(male_count + female_count, 1)
return {"male": male_count / total, "female": female_count / total}
iface = gr.Interface(
fn=gender_of_sentence,
inputs=gr.inputs.Textbox(default="She went to his house to get her keys."),
outputs="label",
interpretation="default",
)
iface.launch()
Alors que se passe-t-il sous le capot ? Avec ces méthodes d'interprétation, Gradio exécute la prédiction plusieurs fois avec des versions modifiées de l'entrée. Sur la base des résultats, vous verrez que l'interface met automatiquement en évidence les parties du texte (ou de l'image, etc.) qui ont contribué à augmenter la probabilité que la classe soit rouge. L'intensité de la couleur correspond à l'importance de cette partie de l'entrée. Les parties qui diminuent la confiance de classe sont surlignées en bleu.
Vous pouvez également écrire votre propre fonction d'interprétation. La démo ci-dessous ajoute une interprétation personnalisée à la démo précédente. Cette fonction prendra les mêmes entrées que la fonction enveloppée principale. La sortie de cette fonction d'interprétation sera utilisée pour mettre en évidence l'entrée de chaque interface d'entrée - donc le nombre de sorties correspond ici au nombre d'interfaces d'entrée. Pour voir le format d'interprétation pour chaque interface d'entrée, consultez la Docs.
import re
import gradio as gr
male_words, female_words = ["he", "his", "him"], ["she", "hers", "her"]
def gender_of_sentence(sentence):
male_count = len([word for word in sentence.split() if word.lower() in male_words])
female_count = len(
[word for word in sentence.split() if word.lower() in female_words]
)
total = max(male_count + female_count, 1)
return {"male": male_count / total, "female": female_count / total}
def interpret_gender(sentence):
result = gender_of_sentence(sentence)
is_male = result["male"] > result["female"]
interpretation = []
for word in re.split("( )", sentence):
score = 0
token = word.lower()
if (is_male and token in male_words) or (not is_male and token in female_words):
score = 1
elif (is_male and token in female_words) or (
not is_male and token in male_words
):
score = -1
interpretation.append((word, score))
return interpretation
iface = gr.Interface(
fn=gender_of_sentence,
inputs=gr.inputs.Textbox(default="She went to his house to get her keys."),
outputs="label",
interpretation=interpret_gender,
enable_queue=True,
)
iface.launch()
La plupart des modèles sont des boîtes noires telles que la logique interne de la fonction est cachée à l'utilisateur final. Pour encourager la transparence, nous avons simplifié l'ajout d'interprétation à votre modèle en définissant simplement le mot- interpretation
clé de la Interface
classe sur default
. Cela permet à vos utilisateurs de comprendre quelles parties de l'entrée sont responsables de la sortie. Jetez un œil à l'interface simple ci-dessous qui montre un classificateur d'image qui inclut également l'interprétation :
import requests
import tensorflow as tf
import gradio as gr
inception_net = tf.keras.applications.MobileNetV2() # load the model
# Download human-readable labels for ImageNet.
response = requests.get("https://git.io/JJkYN")
labels = response.text.split("\n")
def classify_image(inp):
inp = inp.reshape((-1, 224, 224, 3))
inp = tf.keras.applications.mobilenet_v2.preprocess_input(inp)
prediction = inception_net.predict(inp).flatten()
return {labels[i]: float(prediction[i]) for i in range(1000)}
image = gr.inputs.Image(shape=(224, 224))
label = gr.outputs.Label(num_top_classes=3)
gr.Interface(
fn=classify_image, inputs=image, outputs=label, interpretation="default"
).launch()
En plus de default
, Gradio inclut également une interprétation basée sur Shapley , qui fournit des interprétations plus précises, bien que généralement avec une durée d'exécution plus lente. Pour l'utiliser, définissez simplement le interpretation
paramètre sur "shap"
(remarque : assurez-vous également que le package python shap
est installé). Facultativement, vous pouvez modifier le num_shap
paramètre, qui contrôle le compromis entre la précision et la durée d'exécution (l'augmentation de cette valeur augmente généralement la précision). Voici un exemple:
gr.Interface(fn=classify_image, inputs=image, outputs=label, interpretation="shap", num_shap=5).launch()
Cela fonctionnera pour n'importe quelle fonction, même si en interne, le modèle est un réseau neuronal complexe ou une autre boîte noire. Si vous utilisez l'interprétation de Gradio default
ou shap
, le composant de sortie doit être un fichier Label
. Tous les composants d'entrée courants sont pris en charge. Voici un exemple avec saisie de texte.
import re
import gradio as gr
male_words, female_words = ["he", "his", "him"], ["she", "hers", "her"]
def gender_of_sentence(sentence):
male_count = len([word for word in sentence.split() if word.lower() in male_words])
female_count = len(
[word for word in sentence.split() if word.lower() in female_words]
)
total = max(male_count + female_count, 1)
return {"male": male_count / total, "female": female_count / total}
iface = gr.Interface(
fn=gender_of_sentence,
inputs=gr.inputs.Textbox(default="She went to his house to get her keys."),
outputs="label",
interpretation="default",
)
iface.launch()
Alors que se passe-t-il sous le capot ? Avec ces méthodes d'interprétation, Gradio exécute la prédiction plusieurs fois avec des versions modifiées de l'entrée. Sur la base des résultats, vous verrez que l'interface met automatiquement en évidence les parties du texte (ou de l'image, etc.) qui ont contribué à augmenter la probabilité que la classe soit rouge. L'intensité de la couleur correspond à l'importance de cette partie de l'entrée. Les parties qui diminuent la confiance de classe sont surlignées en bleu.
Vous pouvez également écrire votre propre fonction d'interprétation. La démo ci-dessous ajoute une interprétation personnalisée à la démo précédente. Cette fonction prendra les mêmes entrées que la fonction enveloppée principale. La sortie de cette fonction d'interprétation sera utilisée pour mettre en évidence l'entrée de chaque interface d'entrée - donc le nombre de sorties correspond ici au nombre d'interfaces d'entrée. Pour voir le format d'interprétation pour chaque interface d'entrée, consultez la Docs.
import re
import gradio as gr
male_words, female_words = ["he", "his", "him"], ["she", "hers", "her"]
def gender_of_sentence(sentence):
male_count = len([word for word in sentence.split() if word.lower() in male_words])
female_count = len(
[word for word in sentence.split() if word.lower() in female_words]
)
total = max(male_count + female_count, 1)
return {"male": male_count / total, "female": female_count / total}
def interpret_gender(sentence):
result = gender_of_sentence(sentence)
is_male = result["male"] > result["female"]
interpretation = []
for word in re.split("( )", sentence):
score = 0
token = word.lower()
if (is_male and token in male_words) or (not is_male and token in female_words):
score = 1
elif (is_male and token in female_words) or (
not is_male and token in male_words
):
score = -1
interpretation.append((word, score))
return interpretation
iface = gr.Interface(
fn=gender_of_sentence,
inputs=gr.inputs.Textbox(default="She went to his house to get her keys."),
outputs="label",
interpretation=interpret_gender,
enable_queue=True,
)
iface.launch()
Thèmes et style personnalisé
Si vous souhaitez modifier l'apparence de votre interface, vous pouvez sélectionner un thème différent en passant simplement le theme
paramètre, comme ceci :
gr.Interface(fn=classify_image, inputs=image, outputs=label, theme="huggingface").launch()
Voici les thèmes que nous supportons actuellement : "default"
, "huggingface"
, "grass"
, "peach"
, et les thèmes sombres correspondant à chacun d'entre eux : "darkdefault"
, "darkhuggingface"
, "darkgrass"
, "darkpeach"
.
Si vous souhaitez avoir un contrôle plus précis sur n'importe quel aspect de l'application, vous pouvez également écrire votre propre css ou passer dans un fichier css, avec le css
paramètre de la Interface
classe.
Si vous souhaitez modifier l'apparence de votre interface, vous pouvez sélectionner un thème différent en passant simplement le theme
paramètre, comme ceci :
gr.Interface(fn=classify_image, inputs=image, outputs=label, theme="huggingface").launch()
Voici les thèmes que nous supportons actuellement : "default"
, "huggingface"
, "grass"
, "peach"
, et les thèmes sombres correspondant à chacun d'entre eux : "darkdefault"
, "darkhuggingface"
, "darkgrass"
, "darkpeach"
.
Si vous souhaitez avoir un contrôle plus précis sur n'importe quel aspect de l'application, vous pouvez également écrire votre propre css ou passer dans un fichier css, avec le css
paramètre de la Interface
classe.
Options de marquage personnalisées
Dans certains cas, vous souhaiterez peut-être fournir à vos utilisateurs ou testeurs plus qu'une simple option binaire pour marquer un échantillon. Vous pouvez prévoir flagging_options
qu'ils sélectionnent dans une liste déroulante chaque fois qu'ils cliquent sur le bouton du drapeau. Cela leur permet de fournir des commentaires supplémentaires chaque fois qu'ils signalent un échantillon.
Voici un exemple :
gr.Interface(fn=classify_image, inputs=image, outputs=label, flagging_options=["incorrect", "ambiguous", "offensive", "other"]).launch()
Dans certains cas, vous souhaiterez peut-être fournir à vos utilisateurs ou testeurs plus qu'une simple option binaire pour marquer un échantillon. Vous pouvez prévoir flagging_options
qu'ils sélectionnent dans une liste déroulante chaque fois qu'ils cliquent sur le bouton du drapeau. Cela leur permet de fournir des commentaires supplémentaires chaque fois qu'ils signalent un échantillon.
Voici un exemple :
gr.Interface(fn=classify_image, inputs=image, outputs=label, flagging_options=["incorrect", "ambiguous", "offensive", "other"]).launch()
Chargement de modèles de visage et d'espaces enlacés
Gradio s'intègre parfaitement au Hugging Face Hub, vous permettant de charger des modèles et des espaces avec une seule ligne de code. Pour l'utiliser, utilisez simplement la load()
méthode dans la Interface
classe. Alors:
- Pour charger n'importe quel modèle à partir de Hugging Face Hub et créer une interface autour de lui, vous passez
"model/"
ou "huggingface/"
suivez le nom du modèle, comme ces exemples :
gr.Interface.load("huggingface/gpt2").launch();
gr.Interface.load("huggingface/EleutherAI/gpt-j-6B",
inputs=gr.inputs.Textbox(lines=5, label="Input Text") # customizes the input component
).launch()
- Pour charger n'importe quel Space depuis le Hugging Face Hub et le recréer localement (afin de pouvoir personnaliser les entrées et les sorties par exemple), vous passez
"spaces/"
suivi du nom du modèle :
gr.Interface.load("spaces/eugenesiow/remove-bg", inputs="webcam", title="Remove your webcam background!").launch()
L'un des avantages du chargement de modèles ou d'espaces Hugging Face à l'aide de Gradio est que vous pouvez ensuite utiliser immédiatement l' Interface
objet résultant, tout comme la fonction dans votre code Python (cela fonctionne pour chaque type de modèle/espace : texte, images, audio, vidéo, et même des modèles multimodaux) :
io = gr.Interface.load("models/EleutherAI/gpt-neo-2.7B")
io("It was the best of times") # outputs model completion
Gradio s'intègre parfaitement au Hugging Face Hub, vous permettant de charger des modèles et des espaces avec une seule ligne de code. Pour l'utiliser, utilisez simplement la load()
méthode dans la Interface
classe. Alors:
- Pour charger n'importe quel modèle à partir de Hugging Face Hub et créer une interface autour de lui, vous passez
"model/"
ou"huggingface/"
suivez le nom du modèle, comme ces exemples :
gr.Interface.load("huggingface/gpt2").launch();
gr.Interface.load("huggingface/EleutherAI/gpt-j-6B",
inputs=gr.inputs.Textbox(lines=5, label="Input Text") # customizes the input component
).launch()
- Pour charger n'importe quel Space depuis le Hugging Face Hub et le recréer localement (afin de pouvoir personnaliser les entrées et les sorties par exemple), vous passez
"spaces/"
suivi du nom du modèle :
gr.Interface.load("spaces/eugenesiow/remove-bg", inputs="webcam", title="Remove your webcam background!").launch()
L'un des avantages du chargement de modèles ou d'espaces Hugging Face à l'aide de Gradio est que vous pouvez ensuite utiliser immédiatement l' Interface
objet résultant, tout comme la fonction dans votre code Python (cela fonctionne pour chaque type de modèle/espace : texte, images, audio, vidéo, et même des modèles multimodaux) :
io = gr.Interface.load("models/EleutherAI/gpt-neo-2.7B")
io("It was the best of times") # outputs model completion
Mettre les interfaces en parallèle et en série
Gradio permet également de mixer très facilement les interfaces grâce aux classes gradio.Parallel
et . vous permet de mettre deux modèles similaires (s'ils ont le même type d'entrée) en parallèle pour comparer les prédictions du modèle :gradio.Series
Parallel
generator1 = gr.Interface.load("huggingface/gpt2")
generator2 = gr.Interface.load("huggingface/EleutherAI/gpt-neo-2.7B")
generator3 = gr.Interface.load("huggingface/EleutherAI/gpt-j-6B")
gr.Parallel(generator1, generator2, generator3).launch()
Series
vous permet de mettre des modèles et des espaces en série, en canalisant la sortie d'un modèle vers l'entrée du modèle suivant.
generator = gr.Interface.load("huggingface/gpt2")
translator = gr.Interface.load("huggingface/t5-small")
gr.Series(generator, translator).launch() # this demo generates text, then translates it to German, and outputs the final result.
Et bien sûr, vous pouvez aussi mélanger Parallel
et Series
assembler chaque fois que cela a du sens !
Gradio permet également de mixer très facilement les interfaces grâce aux classes gradio.Parallel
et . vous permet de mettre deux modèles similaires (s'ils ont le même type d'entrée) en parallèle pour comparer les prédictions du modèle :gradio.Series
Parallel
generator1 = gr.Interface.load("huggingface/gpt2")
generator2 = gr.Interface.load("huggingface/EleutherAI/gpt-neo-2.7B")
generator3 = gr.Interface.load("huggingface/EleutherAI/gpt-j-6B")
gr.Parallel(generator1, generator2, generator3).launch()
Series
vous permet de mettre des modèles et des espaces en série, en canalisant la sortie d'un modèle vers l'entrée du modèle suivant.
generator = gr.Interface.load("huggingface/gpt2")
translator = gr.Interface.load("huggingface/t5-small")
gr.Series(generator, translator).launch() # this demo generates text, then translates it to German, and outputs the final result.
Et bien sûr, vous pouvez aussi mélanger Parallel
et Series
assembler chaque fois que cela a du sens !
Mise en file d'attente pour gérer les longs temps d'inférence
Si beaucoup de personnes utilisent votre interface ou si le temps d'inférence de votre fonction est long (> 1min), il suffit de régler le enable_queue
paramètre dans la launch
méthode True
pour éviter les timeouts.
gr.Interface(fn=classify_image, inputs=image, outputs=label).launch(enable_queue=True)
Cela configure une file d'attente de travailleurs pour gérer les prédictions et renvoyer la réponse au frontal. Ceci est fortement recommandé si vous prévoyez de télécharger votre démo sur Hugging Face Spaces (comme décrit ci-dessus) afin de pouvoir gérer un grand nombre d'utilisateurs simultanément en utilisant votre démo.
Si beaucoup de personnes utilisent votre interface ou si le temps d'inférence de votre fonction est long (> 1min), il suffit de régler le enable_queue
paramètre dans la launch
méthode True
pour éviter les timeouts.
gr.Interface(fn=classify_image, inputs=image, outputs=label).launch(enable_queue=True)
Cela configure une file d'attente de travailleurs pour gérer les prédictions et renvoyer la réponse au frontal. Ceci est fortement recommandé si vous prévoyez de télécharger votre démo sur Hugging Face Spaces (comme décrit ci-dessus) afin de pouvoir gérer un grand nombre d'utilisateurs simultanément en utilisant votre démo.
Commentaires
Enregistrer un commentaire