curso
Construir interfaces de usuario para aplicaciones de IA con Gradio en Python
La utilidad de los modelos de IA actuales disminuye enormemente sin interfaces de usuario accesibles. Con Gradio, una biblioteca de interfaz web de Python de código abierto, puedes salvar esa distancia entre los LLM y los usuarios finales no técnicos. Te permite crear prototipos rápidos para tus proyectos de IA y simplificar su despliegue a un público más amplio.
Este tutorial está dirigido a ingenieros de aprendizaje automático que normalmente no tienen experiencia en desarrollo web. Abarca los fundamentos y conceptos básicos de Gradio, la creación de interfaces para varios tipos de modelos de IA, las funciones avanzadas para la UX y la interactividad, y las mejores prácticas de despliegue e intercambio.
Empecemos.
Primeros pasos con Gradio
Instalación
Empezaremos creando un entorno virtual (preferiblemente Conda):
$ conda create -n gradio_tutorial python=3.9 -y
$ conda activate gradio_tutorial
A continuación, puedes utilizar PIP para instalar Gradio y sus dependencias:
$ pip install gradio ipykernel
También hemos instalado el paqueteipykernel para poder visualizar las interfaces de Gradio directamente en los cuadernos Jupyter. Este proceso requiere que añadas el entorno virtual que has creado como núcleo a Jupyter Lab. Aquí tienes el comando para hacerlo:
$ ipython kernel install --user --name=gradio_tutorial
$ jupyter lab # Start the lab
Esto debería permitirte crear un cuaderno con un núcleo que tenga Gradio instalado. Para verificarlo, impórtalo con su alias estándar e imprime su versión:
import gradio as gr
print(gr.__version__)
4.37.1
Conceptos básicos y terminología
Nos sumergiremos en Gradio aprendiendo sus conceptos clave y su terminología mediante un ejemplo de "Hola Mundo":
def greet(name):
return f"Hello, {name}!"
demo = gr.Interface(
fn=greet,
inputs=['text'],
outputs="text",
)
demo.launch()
Cuando ejecutes el código anterior en una celda, la salida será una pequeña interfaz interactiva que devuelve un mensaje de saludo personalizado:
Gradio gira en torno a unos cuantos conceptos clave:
- Interfaz: la clase principal para crear interfaces de usuario.
- Componentes: Elementos de entrada y salida como cuadros de texto, imágenes y audio. Actualmente hay más de 30 componentes incorporados.
- Funciones: Funciones de Python que procesan la información de los componentes de entrada y devuelven los resultados para mostrarlos con componentes de salida.
- Lanzamiento: El método para iniciar tu aplicación Gradio.
Arriba hemos creado una funcióngreet que toma y devuelve una entrada de texto. Por esta razón, los componentes de entrada y salida se especifican comotexto en dentro de la claseInterfaz.
Al final, estamos llamando al método delanzamiento, que inicia un servidor local. Para que la IU esté disponible para cualquiera, puedes establecer el parámetro compartir en Verdadero. Esto iniciará un túnel SSH y desplegará la aplicación Gradio en una página web que se pueda compartir públicamente:
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)
Componentes Gradio
Pasarás la mayor parte del tiempo trasteando con diferentes componentes y cómo colocarlos en la página mientras construyes aplicaciones Gradio. Así pues, veamos más de cerca lo que tienes a tu disposición.
Componentes de entrada y salida
Gradio ofrece una amplia gama de componentes para construir interfaces interactivas. Estos componentes se dividen generalmente en dos categorías: entrada y salida.
Los componentes de entrada permiten a los usuarios proporcionar datos al procesador subyacente (puede ser cualquier función de Python). Algunas entradas habituales son:
- Textbox
- Imagen
- Audio
- Deslizador
- Desplegable
Aquí tienes una interfaz ficticia que utiliza algunos de los componentes anteriores:
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()
En este ejemplo, la funciónproceso_entradas requiere cinco parámetros. Por lo tanto, necesitamos crear cinco componentes de entrada y pasarlos a inputs. Aunque el número de componentes de entrada debe coincidir con el número de parámetros de función necesarios, no es una regla estricta. Para evitar errores y advertencias, establece valores por defecto para los parámetros que no requieran la intervención del usuario desde la interfaz de usuario.
Fíjate en que estamos utilizando una clase Cuadro de texto para especificar el componente de entrada en lugar de una cadena de texto sin formato como en el primer ejemplo. Siempre se recomienda utilizar clases dedicadas para especificar los componentes de entrada y salida, para que sean personalizables. Por ejemplo, todas las clases de componentes tienen un útil atributo de etiqueta , mientras que el Deslizador y el Desplegable tienen argumentos para especificar el rango y las opciones disponibles.
Muchos componentes de entrada pueden utilizarse también para mostrar la salida. He aquí algunas situaciones habituales:
- Etiqueta: Para mostrar resultados de texto o clasificación
- Imagen: Para mostrar imágenes procesadas o generadas
- Audio: Para reproducir audio procesado o generado
- Parcela: Para visualizar gráficos o diagramas
Al igual que las entradas, el número de componentes de salida debe coincidir con el número de valores devueltos por la función de procesamiento.
Personalizar el aspecto de los componentes
Gradio te permite personalizar la apariencia de tus componentes para adaptarla a tus necesidades. Aquí tienes un ejemplo que utiliza cuadros de texto personalizados:
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()
En este ejemplo, hemos personalizado los componentes del Cuadro de texto especificando el número de líneas, añadiendo un marcador de posición y un texto informativo, e incluyendo un botón de copia para la salida.
Experimenta con distintos componentes y sus propiedades para crear las interfaces que mejor se adapten a los requisitos de tu aplicación de IA. Para saber qué tipo de propiedades puedes cambiar de tu componente, puedes visitar su documentación, o mejor aún, utilizar el operando ? en Jupyter Lab después de su nombre de clase:
Construir interfaces para LLM
Pongamos en común todo lo que hemos aprendido creando dos interfaces basadas en texto e imágenes del mundo real que funcionan con LLM.
Primero, construiremos un traductor de idiomas del inglés al turco, al español o al chino:
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)}"
Inicialmente, definimos una funcióntranslate_text. En su cuerpo, establecemos la clave de la API de OpenAI y creamos un mapa de idioma. A continuación, construimos la solicitud de traducción. A continuación, dentro de un bloque try-except de , enviamos una solicitud al punto final deChatCompletion con una petición del sistema. Al final, devolvemos la primera opción.
Ahora podemos construir la interfaz:
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)
El código es sencillo, como el de las interfaces anteriores, pero introducimos un par de propiedades nuevas:
- tipo de los cuadros de texto cambia el campo de entrada de texto plano a entrada de contraseña, ocultando el texto.
- título y descripción argumentos de Interfaz añade un título H1 y un subtítulo en la parte superior central de la página.
He aquí el resultado:
Puede que te preguntes por qué pedimos la clave API al usuario como parte de la aplicación en lugar de proporcionársela nosotros mismos. La razón tiene que ver con la forma en que Gradio despliega las interfaces de usuario.
Si proporcionáramos nuestra propia clave API como variable de entorno (que es la práctica habitual), la versión de la app que se puede compartir públicamente no funcionaría, ya que no tendría acceso a nuestras variables de entorno. En la sección de despliegue, veremos cómo solucionarlo desplegando nuestras aplicaciones en espacios HuggingFace.
Vamos a construir otra interfaz de usuario para generar imágenes:
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
Creamos una función llamada generar_arte_surrealista que envía una petición a dall-e-3 y devuelve la URL de la imagen generada utilizando una indicación surrealista. A continuación, volveremos a introducir esta función en una clase deinterfaz :
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)
Especificamos dos entradas para la clave API y el concepto que queremos plasmar en una imagen surrealista. A continuación, creamos un componente de salida para la imagen generada con la clase Image. Si estableces su argumento de valor en str, el componente puede descargar y mostrar imágenes de URL, que es justo lo que necesitamos.
Y éste es el resultado:
Construir interfaces para modelos clásicos de ML
Ahora, vamos a construir una interfaz para un modelo de regresión tabular clásico. Utilizaremos el conjunto de datos Diamonds, disponible en Seaborn.
Empieza creando un nuevo directorio de trabajo y un nuevo script llamado app.py dentro. A continuación, pega el código de este gist de GitHub que carga los datos, los procesa utilizando un Scikit-learn Pipeline y entrena un modeloRandomForestRegression.
El siguiente paso es crear una función de procesamiento que acepte el mismo número de entradas que características hay en el conjunto de datos 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 función convierte esas entradas en un DataFrame y lo pasa al método.predict() de la canalización del modelo entrenado. Al final, devuelve una cadena con el precio previsto.
Ahora, la Interfaz debe coincidir con la firma de esta función: nueve componentes de entrada para procesar las características y uno de salida para mostrar el precio 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)
Dentro de la clase, creamos tres desplegables para las características categóricas. Las opciones se rellenan con las categorías únicas de cada función. También creamos seis componentes deslizantes para aceptar características numéricas. Los rangos de los deslizadores están determinados por los valores mínimo y máximo de cada característica.
Todo lo que tenemos que hacer ahora es ejecutar el script para ejecutar y desplegar la aplicación:
$ python app.py
He aquí el resultado:
Para conocer las mejores prácticas y consejos de optimización, pasa a la sección "Mejores prácticas" más abajo.
Desplegar aplicaciones Gradio
Ya hemos visto lo fácil que es desplegar aplicaciones Gradio habilitando un único argumento. Por supuesto, la desventaja de este método es que las demos caducan en 72 horas. Por tanto, el método recomendado para desplegar Gradio es a través de HuggingFace Spaces. HuggingFace adquirió Gradio en 2021, con lo que la integración entre ambas plataformas fue perfecta.
Así que, para este tutorial o cualquier futura aplicación que crees con Gradio, regístrate para obtener una cuenta gratuita en huggingface.co y ve a Configuración > Fichas para generar un token de acceso:
El token sólo se muestra una vez, así que asegúrate de guardarlo en un lugar seguro.
Con este token, puedes desplegar tantas aplicaciones Gradio como quieras con alojamiento permanente en Spaces. Como ejemplo, desplegaremos el modelo de Predicción del Precio del Diamante de la sección anterior, y te resultará sorprendentemente fácil.
Todo lo que tienes que hacer es navegar hasta el directorio con el script de interfaz de usuario y llamar a gradio deploy en el terminal:
El terminal te guía a través de la conversión de tu script en un Espacio CaraAbrazo funcional. Pide detalles como
- El token de acceso que has generado
- Título del espacio: formará parte de la URL del espacio una vez desplegado.
- El nombre del script que contiene el código de la interfaz de usuario de Gradio (app.py por defecto)
- Hardware del espacio; déjalo vacío para utilizar sólo CPUs (libres)
- Cualquier variable de entorno que utilice el script (aquí es donde almacenas las claves API y los secretos de usuario de forma segura)
- Dependencias - introdúcelas una a una pulsando ENTER
Y el terminal te presenta un enlace de Espacio desplegado. Esto es lo que parece:
Otra gran ventaja de este método de despliegue es que Gradio convierte automáticamente la demo en una API REST operativa. Las instrucciones para acceder a ella y consultarla se encuentran siempre en la parte inferior:
Así, de una sola vez, tienes tanto un alojamiento permanente de la interfaz de usuario de tu aplicación para usuarios no técnicos, como una API REST para tus colegas y amigos desarrolladores.
Para más opciones de despliegue y compartición, como incrustar demos en páginas web, añadir autenticación de Google a las aplicaciones, etc., visita la página "Compartir tu aplicación de la documentación de Gradio.
Buenas prácticas y consejos de Gradio
Al desarrollar interfaces de usuario con Gradio, seguir las mejores prácticas puede mejorar significativamente la experiencia del usuario y la mantenibilidad de tu aplicación. He aquí algunas recomendaciones clave:
1. Utiliza guiones para organizar y mantener
Organiza las aplicaciones de Gradio en scripts de Python para mejorar el control de versiones, la colaboración y el despliegue.
2. Optimizar la asignación de espacio para los componentes
Utiliza herramientas adecuadas de dimensionamiento y diseño (por ejemplo, gr.Column(), gr.Row()) para garantizar una interfaz equilibrada y receptiva.
3. Proporcionar información completa
Utiliza los atributos "info" y "label" para dar instrucciones claras y el contexto de cada componente.
4. Maneja grandes conjuntos de características de forma eficiente
Para modelos con muchas funciones, utiliza entradas de archivos (CSV, JSON) para permitir predicciones por lotes y simplificar la interfaz.
5. Gestionar correctamente las variables de entorno
Utiliza python-dotenv para el desarrollo local y establece variables en Hugging Face Spaces para el despliegue.
6. Implementar el tratamiento de errores y la validación
Valida las entradas, proporciona mensajes de error claros y utiliza bloques try-except para gestionar los errores con elegancia.
7. Optimizar el rendimiento
Implementa el almacenamiento en caché, la carga perezosa para modelos grandes, y utiliza gr.LoadingStatus() para tareas de larga duración.
8. Diseñar para la accesibilidad
Asegúrate de que el contraste sea alto, proporciona texto alternativo para las imágenes y habilita la navegación mediante teclado para todos los elementos interactivos.
9. Aplicar la divulgación progresiva
Utiliza acordeones o pestañas para organizar interfaces complejas, revelando opciones avanzadas según sea necesario.
10. Actualiza y mantén regularmente
Mantén actualizadas las dependencias, controla los errores y mejora continuamente basándote en los comentarios de los usuarios.
11. Aprovechar los recursos de HuggingFace
Utiliza las herramientas y recursos de HuggingFace para una integración perfecta con Gradio, incluidos los repositorios de modelos y conjuntos de datos.
12. Acoger modelos grandes en HuggingFace Hub
Para modelos tabulares grandes, cárgalos en HuggingFace Hub y cárgalos directamente en tu script de Gradio para mejorar el rendimiento y reducir los requisitos de almacenamiento local.
13. Utilizar los conjuntos de datos de HuggingFace
Para grandes conjuntos de datos, cárgalos en HuggingFace Hub y accede a ellos directamente en tu aplicación Gradio para agilizar la gestión de datos y mejorar los tiempos de carga.
Conclusión y otros recursos
En este artículo, hemos aprendido los fundamentos de la creación de interfaces de usuario para aplicaciones de IA utilizando Gradio. Acabamos de sumergirnos en la superficie, ya que Gradio ofrece muchas más funciones para construir interfaces complejas. Por ejemplo interfaz estado permite que tu aplicación recuerde las salidas de una llamada de función a otra. Interfaces reactivas cambian dinámicamente la interfaz de usuario en cuanto cambia la entrada del usuario. Con Bloquespuedes crear aplicaciones con diseños personalizados.
Del mismo modo, consulta estos recursos relacionados para obtener más contenido:
Los mejores cursos de DataCamp
programa
Desarrollar grandes modelos lingüísticos
curso
Desarrollar aplicaciones LLM con LangChain
![An AI juggles tasks](https://media.datacamp.com/legacy/v1682075442/An_AI_juggles_tasks_9641a41756.png?w=750)
blog
Cinco proyectos que puedes crear con modelos de IA generativa (con ejemplos)
![](https://media.datacamp.com/legacy/v1706534343/datarhys_an_absurdist_oil_painting_of_a_male_coder_sat_at_their_55e951a0_e02d_4eb9_84cc_3c99e1898bac_eff95b11e5.png?w=750)
blog
7 proyectos de IA para todos los niveles
tutorial
Ajuste fino de GPT-3 mediante la API OpenAI y Python
tutorial
Construir un transformador con PyTorch
tutorial
Tutorial sobre cómo crear aplicaciones LLM con LangChain
tutorial