
Laboratorio de investigación en seguridad que reproduce CVE-2023-6572 (GHSA-gqvf-3hgp-5hxv): inyección de comandos en el manejo de workflow_run de gradio-app/gradio en generate-changeset.yml
Artefacto de investigación automatizado — no es el proyecto original.
Este repositorio es un laboratorio desechable construido por un sistema automatizado para una tesis de maestría en la Université Laval sobre la reproducción de vulnerabilidades publicadas en flujos de trabajo de GitHub Actions. Es una instantánea verbatim de
gradio-app/gradioen el commit1d986217f6f4fc1829e528d2afe365635788204f(2023-11-03), redistribuida bajo la licencia del propio proyecto, cuyo archivo se incluye sin cambios en esta instantánea.El proyecto original no está involucrado, nunca es el objetivo, y la vulnerabilidad estudiada aquí ya es pública. Cada secreto y variable en este repositorio es un valor ficticio generado aleatoriamente — no hay ninguna credencial real. Las referencias de acciones e imágenes de ejecutores están fijadas a lo que resolvieron el 2023-11-03; consulta
pinning.mden la salida del sistema para cada cambio realizado en la instantánea.Preguntas u objeciones: [email protected]
Sitio web | Documentación | Guías | Primeros pasos | Ejemplos | 中文
Gradio es una biblioteca de Python de código abierto que se utiliza para crear demos y aplicaciones web de aprendizaje automático y ciencia de datos.
Con Gradio, puedes crear rápidamente una interfaz de usuario atractiva alrededor de tus modelos de aprendizaje automático o flujos de trabajo de ciencia de datos y permitir que las personas "lo prueben" arrastrando y soltando sus propias imágenes, pegando texto, grabando su propia voz e interactuando con tu demo, todo a través del navegador.

Gradio es útil para:
Demostrar tus modelos de aprendizaje automático a clientes/colaboradores/usuarios/estudiantes.
Desplegar tus modelos rápidamente con enlaces compartibles automáticos y obtener comentarios sobre el rendimiento del modelo.
Depurar tu modelo de forma interactiva durante el desarrollo utilizando herramientas integradas de manipulación de entradas.
Requisito previo: Gradio requiere Python 3.8 o superior, ¡eso es todo!
Una de las mejores formas de compartir tu modelo de aprendizaje automático, API o flujo de trabajo de ciencia de datos con otros es crear una aplicación interactiva que permita a tus usuarios o colegas probar la demo en sus navegadores.
Gradio te permite crear demos y compartirlas, todo en Python. ¡Y normalmente en solo unas pocas líneas de código! Así que empecemos.
Para poner Gradio en funcionamiento con un ejemplo simple de "Hola, mundo", sigue estos tres pasos:
1. Instala Gradio usando pip:
pip install gradio
2. Ejecuta el código siguiente como un script de Python o en un Jupyter Notebook (o Google Colab):
import gradio as gr
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
demo.launch()
Abreviemos el nombre importado a gr para una mejor legibilidad del código que usa Gradio. Esta es una convención ampliamente adoptada que deberías seguir para que cualquiera que trabaje con tu código pueda entenderlo fácilmente.
3. La demo siguiente aparecerá automáticamente dentro del Jupyter Notebook, o se abrirá en un navegador en http://localhost:7860 si se ejecuta desde un script:

Cuando desarrolles localmente, si quieres ejecutar el código como un script de Python, puedes usar la CLI de Gradio para lanzar la aplicación en modo de recarga, que proporcionará un desarrollo fluido y rápido. Aprende más sobre la recarga en la Guía de recarga automática.
gradio app.py
Nota: también puedes hacer python app.py, pero no proporcionará el mecanismo de recarga automática.
InterfaceNotarás que para crear la demo, creamos un gr.Interface. Esta clase Interface puede envolver cualquier función de Python con una interfaz de usuario. En el ejemplo anterior, vimos una función simple basada en texto, pero la función podría ser cualquier cosa, desde un generador de música hasta una calculadora de impuestos o la función de predicción de un modelo de aprendizaje automático preentrenado.
La clase principal Interface se inicializa con tres parámetros obligatorios:
fn: la función alrededor de la cual envolver una interfaz de usuarioinputs: qué componente(s) usar para la entrada (por ejemplo, "text", "image" o "audio")outputs: qué componente(s) usar para la salida (por ejemplo, "text", "image" o "label")Echemos un vistazo más de cerca a estos componentes utilizados para proporcionar entrada y salida.
Vimos algunos componentes simples Textbox en los ejemplos anteriores, pero ¿qué pasa si quieres cambiar cómo se ven o se comportan los componentes de la interfaz de usuario?
Digamos que quieres personalizar el campo de texto de entrada — por ejemplo, que sea más grande y tenga un texto de marcador de posición. Si usamos la clase real de Textbox en lugar del atajo de cadena, tienes acceso a mucha más personalización a través de los atributos del componente.
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()

Supongamos que tienes una función más compleja, con múltiples entradas y salidas. En el ejemplo siguiente, definimos una función que toma una cadena, un booleano y un número, y devuelve una cadena y un número. Observa cómo pasas una lista de componentes de entrada y salida.
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()

Simplemente envuelves los componentes en una lista. Cada componente en la lista inputs corresponde a uno de los parámetros de la función, en orden. Cada componente en la lista outputs corresponde a uno de los valores devueltos por la función, también en orden.
Gradio admite muchos tipos de componentes, como Image, DataFrame, Video o Label. ¡Probemos una función de imagen a imagen para tener una idea de estos!
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()

Al usar el componente Image como entrada, tu función recibirá un array de NumPy con la forma (height, width, 3), donde la última dimensión representa los valores RGB. También devolveremos una imagen en forma de array de NumPy.
También puedes establecer el tipo de datos utilizado por el componente con el argumento de palabra clave type=. Por ejemplo, si quisieras que tu función tomara una ruta de archivo a una imagen en lugar de un array de NumPy, el componente de entrada Image podría escribirse como:
gr.Image(type="filepath", shape=...)
También ten en cuenta que nuestro componente de entrada Image viene con un botón de edición 🖉, que permite recortar y hacer zoom en las imágenes. Manipular imágenes de esta manera puede ayudar a revelar sesgos o defectos ocultos en un modelo de aprendizaje automático.
Puedes leer más sobre los muchos componentes y cómo usarlos en la documentación de Gradio.
Gradio incluye una clase de alto nivel, gr.ChatInterface, que es similar a gr.Interface, pero está diseñada específicamente para interfaces de usuario de chatbots. La clase gr.ChatInterface también envuelve una función, pero esta función debe tener una firma específica. La función debe tomar dos argumentos: message y luego history (los argumentos pueden llamarse de cualquier manera, pero deben estar en este orden)
message: un str que representa la entrada del usuariohistory: una list de list que representa las conversaciones hasta ese punto. Cada lista interna consta de dos str que representan un par: [entrada del usuario, respuesta del bot].Tu función debe devolver una única respuesta de cadena, que es la respuesta del bot a la entrada de usuario particular message.
Aparte de eso, gr.ChatInterface no tiene parámetros obligatorios (aunque hay varios disponibles para personalizar la interfaz de usuario).
Aquí tienes un ejemplo de juguete:
import random
import gradio as gr
def random_response(message, history):
return random.choice(["Yes", "No"])
demo = gr.ChatInterface(random_response)
demo.launch()

Gradio ofrece dos enfoques para crear aplicaciones:
1. Interface y ChatInterface, que proporcionan una abstracción de alto nivel para crear demos, como hemos estado discutiendo hasta ahora.
2. Blocks, una API de bajo nivel para diseñar aplicaciones web con diseños y flujos de datos más flexibles. Blocks te permite hacer cosas como incluir múltiples flujos de datos y demos, controlar dónde aparecen los componentes en la página, manejar flujos de datos complejos (por ejemplo, las salidas pueden servir como entradas para otras funciones) y actualizar propiedades/visibilidad de los componentes según la interacción del usuario — todo en Python. Si esta personalización es lo que necesitas, ¡prueba Blocks!
Echemos un vistazo a un ejemplo simple. Observa cómo la API aquí difiere 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()

Cosas a tener en cuenta:
Blocks se crean con una cláusula with, y cualquier componente creado dentro de esta cláusula se agrega automáticamente a la aplicación.Button y luego se agregó un listener de eventos click a este botón. ¡La API para esto debería resultarte familiar! Como un Interface, el método click toma una función de Python, componentes de entrada y componentes de salida.Aquí tienes una aplicación para darte una idea de lo que es posible con 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()

¡Hay mucho más en juego aquí! Cubriremos cómo crear aplicaciones Blocks complejas como esta en la sección construyendo con blocks para ti.
¡Felicidades, ahora estás familiarizado con los conceptos básicos de Gradio! 🥳 Ve a nuestra siguiente guía para aprender más sobre las características clave de Gradio.
Gradio está construido con muchas bibliotecas de código abierto maravillosas, ¡apóyalas también!
Gradio está licenciado bajo la Apache License 2.0 que se encuentra en el archivo LICENSE en el directorio raíz de este repositorio.
También consulta el artículo Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild, ICML HILL 2019, y cítalo si usas Gradio en tu trabajo.
@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},
}