
Laboratoire de recherche en sécurité reproduisant CVE-2023-6572 (GHSA-gqvf-3hgp-5hxv) : injection de commandes dans la gestion de workflow_run de gradio-app/gradio pour generate-changeset.yml
Artefact de recherche automatisé — pas le projet en amont.
Ce dépôt est un laboratoire jetable construit par un harnais automatisé pour un mémoire de maîtrise à l'Université Laval sur la reproduction de vulnérabilités publiées dans les workflows GitHub Actions. Il s'agit d'un instantané verbatim de
gradio-app/gradioau commit1d986217f6f4fc1829e528d2afe365635788204f(2023-11-03), redistribué sous la licence propre de ce projet, dont le fichier est inclus inchangé dans cet instantané.Le projet en amont n'est pas impliqué, n'est jamais ciblé, et la vulnérabilité étudiée ici est déjà publique. Chaque secret et variable dans ce dépôt est une valeur factice générée aléatoirement — aucun identifiant réel n'est présent. Les références d'actions et les images d'exécuteur sont épinglées à ce qu'elles résolvaient le 2023-11-03 ; voir
pinning.mddans la sortie du harnais pour chaque modification apportée à l'instantané.Questions ou objections : [email protected]
Site web | Documentation | Guides | Pour commencer | Exemples | 中文
Gradio est une bibliothèque Python open-source utilisée pour créer des démos et des applications web d'apprentissage automatique et de science des données.
Avec Gradio, vous pouvez rapidement créer une belle interface utilisateur autour de vos modèles d'apprentissage automatique ou de votre flux de travail de science des données et permettre aux gens de « l'essayer » en glissant-déposant leurs propres images, en collant du texte, en enregistrant leur propre voix et en interagissant avec votre démo, le tout via le navigateur.

Gradio est utile pour :
Présenter vos modèles d'apprentissage automatique à des clients/collaborateurs/utilisateurs/étudiants.
Déployer vos modèles rapidement avec des liens partageables automatiques et obtenir des retours sur les performances du modèle.
Déboguer votre modèle de manière interactive pendant le développement à l'aide d'outils de manipulation d'entrée intégrés.
Prérequis : Gradio nécessite Python 3.8 ou supérieur, c'est tout !
L'une des meilleures façons de partager votre modèle d'apprentissage automatique, votre API ou votre flux de travail de science des données avec d'autres est de créer une application interactive qui permet à vos utilisateurs ou collègues d'essayer la démo dans leur navigateur.
Gradio vous permet de créer des démos et de les partager, tout en Python. Et généralement en quelques lignes de code seulement ! Alors commençons.
Pour faire fonctionner Gradio avec un simple exemple « Bonjour, le monde », suivez ces trois étapes :
1. Installez Gradio avec pip :
pip install gradio
2. Exécutez le code ci-dessous comme script Python ou dans un Jupyter Notebook (ou Google Colab) :
import gradio as gr
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
demo.launch()
Nous raccourcissons le nom importé en gr pour une meilleure lisibilité du code utilisant Gradio. C'est une convention largement adoptée que vous devriez suivre afin que quiconque travaille avec votre code puisse le comprendre facilement.
3. La démo ci-dessous apparaîtra automatiquement dans le Jupyter Notebook, ou s'ouvrira dans un navigateur sur http://localhost:7860 si elle est exécutée depuis un script :

Lors d'un développement local, si vous souhaitez exécuter le code comme script Python, vous pouvez utiliser la CLI Gradio pour lancer l'application en mode rechargement, ce qui offrira un développement fluide et rapide. Apprenez-en plus sur le rechargement dans le Guide de rechargement automatique.
gradio app.py
Remarque : vous pouvez aussi faire python app.py, mais cela ne fournira pas le mécanisme de rechargement automatique.
InterfaceVous remarquerez que pour créer la démo, nous avons créé un gr.Interface. Cette classe Interface peut envelopper n'importe quelle fonction Python avec une interface utilisateur. Dans l'exemple ci-dessus, nous avons vu une fonction simple basée sur du texte, mais la fonction pourrait être n'importe quoi, d'un générateur de musique à un calculateur d'impôts en passant par la fonction de prédiction d'un modèle d'apprentissage automatique pré-entraîné.
La classe centrale Interface est initialisée avec trois paramètres requis :
fn : la fonction à envelopper avec une interface utilisateurinputs : le(s) composant(s) à utiliser pour l'entrée (par ex. "text", "image" ou "audio")outputs : le(s) composant(s) à utiliser pour la sortie (par ex. "text", "image" ou "label")Examinons de plus près ces composants utilisés pour fournir l'entrée et la sortie.
Nous avons vu quelques composants Textbox simples dans les exemples précédents, mais que faire si vous voulez changer l'apparence ou le comportement des composants de l'interface utilisateur ?
Disons que vous voulez personnaliser le champ de saisie de texte — par exemple, le rendre plus grand et avec un texte d'espace réservé. Si nous utilisons la classe réelle pour Textbox au lieu du raccourci sous forme de chaîne, vous avez accès à beaucoup plus de personnalisation grâce aux attributs des composants.
import gradio as gr
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(
fn=greet,
inputs=gr.Textbox(lines=2, placeholder="Name Here..."),
outputs="text",
)
demo.launch()

Supposons que vous ayez une fonction plus complexe, avec plusieurs entrées et sorties. Dans l'exemple ci-dessous, nous définissons une fonction qui prend une chaîne, un booléen et un nombre, et renvoie une chaîne et un nombre. Regardez comment vous transmettez 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 = f"{salutation} {name}. It is {temperature} degrees today"
celsius = (temperature - 32) * 5 / 9
return greeting, round(celsius, 2)
demo = gr.Interface(
fn=greet,
inputs=["text", "checkbox", gr.Slider(0, 100)],
outputs=["text", "number"],
)
demo.launch()

Il suffit d'envelopper les composants dans une liste. Chaque composant de la liste inputs correspond à l'un des paramètres de la fonction, dans l'ordre. Chaque composant de la liste outputs correspond à l'une des valeurs renvoyées par la fonction, toujours dans l'ordre.
Gradio prend en charge de nombreux types de composants, tels que Image, DataFrame, Video ou Label. Essayons une fonction image-à-image pour avoir une idée de ces composants !
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
demo = gr.Interface(sepia, gr.Image(width=200, height=200), "image")
demo.launch()

Lorsque vous utilisez le composant Image comme entrée, votre fonction recevra un tableau NumPy de forme (height, width, 3), où la dernière dimension représente les valeurs RVB. Nous renverrons également une image sous forme de tableau NumPy.
Vous pouvez également définir le type de données utilisé par le composant avec l'argument de mot-clé type=. Par exemple, si vous vouliez que votre fonction prenne un chemin de fichier vers une image au lieu d'un tableau NumPy, le composant d'entrée Image pourrait être écrit comme suit :
gr.Image(type="filepath", shape=...)
Notez également que notre composant d'entrée Image est accompagné d'un bouton d'édition 🖉, qui permet de recadrer et de zoomer sur les images. Manipuler les images de cette manière peut aider à révéler des biais ou des défauts cachés dans un modèle d'apprentissage automatique !
Vous pouvez en savoir plus sur les nombreux composants et comment les utiliser dans la documentation Gradio.
Gradio inclut une classe de haut niveau, gr.ChatInterface, qui est similaire à gr.Interface, mais spécifiquement conçue pour les interfaces utilisateur de chatbot. La classe gr.ChatInterface enveloppe également une fonction, mais cette fonction doit avoir une signature spécifique. La fonction doit prendre deux arguments : message puis history (les arguments peuvent être nommés comme vous voulez, mais doivent être dans cet ordre)
message : une str représentant la saisie de l'utilisateurhistory : une list de list représentant les conversations jusqu'à ce point. Chaque liste interne se compose de deux str représentant une paire : [saisie utilisateur, réponse du bot].Votre fonction doit renvoyer une seule réponse sous forme de chaîne, qui est la réponse du bot à la saisie utilisateur particulière message.
À part cela, gr.ChatInterface n'a aucun paramètre requis (bien que plusieurs soient disponibles pour personnaliser l'interface utilisateur).
Voici un exemple jouet :
import random
import gradio as gr
def random_response(message, history):
return random.choice(["Yes", "No"])
demo = gr.ChatInterface(random_response)
demo.launch()

Vous pouvez en savoir plus sur gr.ChatInterface ici.
Gradio propose deux approches pour créer des applications :
1. Interface et ChatInterface, qui fournissent une abstraction de haut niveau pour créer les démos dont nous avons parlé jusqu'à présent.
2. Blocks, une API de bas niveau pour concevoir des applications web avec des mises en page et des flux de données plus flexibles. Blocks vous permet de gérer plusieurs flux de données et démos, de contrôler où les composants apparaissent sur la page, de gérer des flux de données complexes (par ex. les sorties peuvent servir d'entrées à d'autres fonctions) et de mettre à jour les propriétés/la visibilité des composants en fonction des interactions utilisateur — toujours en Python. Si cette personnalisation est ce dont vous avez besoin, essayez Blocks à la place !
Jetons un œil à un exemple simple. Remarquez comment l'API diffère ici de Interface.
import gradio as gr
def greet(name):
return "Hello " + name + "!"
with gr.Blocks() as demo:
name = gr.Textbox(label="Name")
output = gr.Textbox(label="Output Box")
greet_btn = gr.Button("Greet")
greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")
demo.launch()

Points à noter :
Blocks sont créés avec une clause with, et tout composant créé dans cette clause est automatiquement ajouté à l'application.Button a été créé, puis un écouteur d'événement click a été ajouté à ce bouton. L'API pour cela devrait vous sembler familière ! Comme une Interface, la méthode click prend une fonction Python, des composants d'entrée et des composants de sortie.Voici une application pour vous donner un aperçu de ce qui est possible avec Blocks :
import numpy as np
import gradio as gr
def flip_text(x):
return x[::-1]
def flip_image(x):
return np.fliplr(x)
with gr.Blocks() as demo:
gr.Markdown("Flip text or image files using this demo.")
with gr.Tab("Flip Text"):
text_input = gr.Textbox()
text_output = gr.Textbox()
text_button = gr.Button("Flip")
with gr.Tab("Flip Image"):
with gr.Row():
image_input = gr.Image()
image_output = gr.Image()
image_button = gr.Button("Flip")
with gr.Accordion("Open for More!"):
gr.Markdown("Look at me...")
text_button.click(flip_text, inputs=text_input, outputs=text_output)
image_button.click(flip_image, inputs=image_input, outputs=image_output)
demo.launch()

Il se passe beaucoup plus de choses ici ! Nous verrons comment créer des applications Blocks complexes comme celle-ci dans la section construire avec blocks.
Félicitations, vous connaissez maintenant les bases de Gradio ! 🥳 Rendez-vous dans notre prochain guide pour en savoir plus sur les fonctionnalités clés de Gradio.
Gradio est construit avec de nombreuses merveilleuses bibliothèques open source, soutenez-les également !
Gradio est sous licence Apache License 2.0, disponible dans le fichier LICENSE à la racine de ce dépôt.
Consultez également l'article Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild, ICML HILL 2019, et citez-le si vous utilisez Gradio dans votre travail.
@article{abid2019gradio,
title = {Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild},
author = {Abid, Abubakar and Abdalla, Ali and Abid, Ali and Khan, Dawood and Alfozan, Abdulrahman and Zou, James},
journal = {arXiv preprint arXiv:1906.02569},
year = {2019},
}