# Entrenamiento con Jobs

[![model badge](https://img.shields.io/badge/All_models-HF_Jobs-blue)](https://huggingface.co/models?other=hf_jobs,trl)

[Hugging Face Jobs](https://huggingface.co/docs/hub/jobs) ejecuta tu entrenamiento en GPUs de Hugging Face. Tú eliges el hardware para cada ejecución y solo pagas por los segundos que se ejecuta. Con `--push_to_hub`, el modelo entrenado se sube al Hub al final.

En esta guía, aprenderás a:

- Lanza un script de entrenamiento de TRL con un solo comando
- Sigue una ejecución y observa sus curvas de pérdida
- Ejecuta tu propio script, con sus ajustes de hardware en el archivo
- Guardar puntos de control y reanudar una ejecución interrumpida
- Entrenar en varias GPU

Para saber cómo funcionan los Jobs en general, incluido el hardware y los precios, consulte la [documentación de Jobs](https://huggingface.co/docs/hub/jobs).

## Requisitos

- Una cuenta de Hugging Face con un [saldo de crédito](https://huggingface.co/settings/billing) positivo. Los trabajos son de pago por uso: solo pagas por los segundos que utilices.
- Iniciado en el Hugging Face Hub (`hf auth login`)

## Una primera ejecución

Este comando realiza el ajuste fino de [Qwen2-0.5B-Instruct](https://huggingface.co/Qwen/Qwen2-0.5B-Instruct) en el conjunto de datos de chat [Capybara](https://huggingface.co/datasets/trl-lib/Capybara) con el script SFT de TRL y luego sube el modelo a tu cuenta:

```bash
hf jobs uv run \
    --flavor a10g-small \
    --timeout 30m \
    --secrets HF_TOKEN \
    -- \
    https://raw.githubusercontent.com/huggingface/trl/refs/heads/main/trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B-Instruct \
    --dataset_name trl-lib/Capybara \
    --max_steps 100 \
    --output_dir Qwen2-0.5B-SFT \
    --push_to_hub
```

```python
from huggingface_hub import run_uv_job

run_uv_job(
    "https://raw.githubusercontent.com/huggingface/trl/refs/heads/main/trl/scripts/sft.py",
    flavor="a10g-small",
    timeout="30m",
    secrets={"HF_TOKEN": "hf_..."},
    script_args=[
        "--model_name_or_path", "Qwen/Qwen2-0.5B-Instruct",
        "--dataset_name", "trl-lib/Capybara",
        "--max_steps", "100",
        "--output_dir", "Qwen2-0.5B-SFT",
        "--push_to_hub",
    ],
)
```

Tarda unos minutos y cuesta mucho menos de 1 dólar en `a10g-small`. Las opciones antes de `--` son para Jobs: el hardware, un límite de tiempo y el token utilizado para publicar el modelo. `--secrets HF_TOKEN` envía el token con el que iniciaste sesión. En Python, pasa el propio token. Los argumentos después de la URL del script van al script. `hf jobs uv run` ejecuta un script de Python con [uv](https://docs.astral.sh/uv/guides/scripts/). `sft.py` lista sus dependencias en un encabezado al inicio del archivo, por lo que Jobs instala TRL antes de que comience el script. El Job se detiene cuando el script termina y la facturación se detiene con él.

`--max_steps 100` mantiene esta primera ejecución breve. Elimínalo para la ejecución completa: tres épocas, el valor predeterminado del script, tardan unas pocas horas en `a10g-small`, por lo que aumente `--timeout` para que coincida, por ejemplo `--timeout 3h`. Jobs detiene una ejecución cuando alcanza su tiempo de espera, que es de 30 minutos por defecto. Una GPU más grande, como `a100-large`, termina antes. Consulte [Hardware](https://huggingface.co/docs/hub/jobs-pricing) para ver los sabores y sus precios.

## Sigue la ejecución

`hf jobs uv run` transmite los registros y mantiene tu terminal abierta hasta que la ejecución termina. Ctrl+C detiene solo el flujo de registros: el Job sigue ejecutándose. Añade `--detach` para obtener el ID del Job de inmediato y luego:

```bash
hf jobs logs -f <job_id>   # stream the logs
hf jobs ps                 # list your running Jobs
hf jobs inspect <job_id>   # status, and the error message if it failed
hf jobs cancel <job_id>    # stop it
```

Consulte [Manage Jobs](https://huggingface.co/docs/hub/jobs-manage) para obtener más información.

Para las curvas de pérdida, TRL registra en [Trackio](trackio_integration). Añade `--env TRACKIO_SPACE_ID=<your-username>/trackio` antes de `--` para nombrar un Space para el panel de control, y `--report_to trackio` después de la URL del script. Trackio crea el Space y un bucket para las métricas si no existen. Ambos son públicos por defecto. También funcionan otros trackers que Transformers admite. Para Weights & Biases, añade `--with wandb --secrets WANDB_API_KEY` antes de `--` y `--report_to wandb` después de la URL del script. `--secrets WANDB_API_KEY` lee el valor de `WANDB_API_KEY` en tu entorno local. Consulta [variables de entorno y secretos](https://huggingface.co/docs/hub/jobs-configuration#user-defined-environment-variables) para otras formas de pasarlos.

## Ejecuta tu propio script

Escribe tu código de entrenamiento en un archivo de Python (por ejemplo, `train.py`). Enumera sus dependencias al inicio del archivo, en un [encabezado de script](https://docs.astral.sh/uv/guides/scripts/#declaring-script-dependencies), de la misma manera que lo hacen los scripts de TRL. Jobs los instala antes de que comience el script:

```python
# /// script
# dependencies = [
#     "trl",
#     "peft",
# ]
# ///

from datasets import load_dataset
from peft import LoraConfig
from trl import SFTConfig, SFTTrainer

dataset = load_dataset("trl-lib/Capybara", split="train")

trainer = SFTTrainer(
    model="Qwen/Qwen2.5-0.5B",
    train_dataset=dataset,
    peft_config=LoraConfig(),
    args=SFTConfig(output_dir="Qwen2.5-0.5B-SFT", max_steps=100),
)
trainer.train()
trainer.push_to_hub()
```

Luego, inícialo con la CLI [`hf jobs`](https://huggingface.co/docs/huggingface_hub/guides/cli#hf-jobs) o la API de Python:

```bash
hf jobs uv run \
    --flavor a10g-small \
    --timeout 30m \
    --secrets HF_TOKEN \
    train.py
```

```python
from huggingface_hub import run_uv_job

run_uv_job(
    "train.py",
    flavor="a10g-small",
    timeout="30m",
    secrets={"HF_TOKEN": "hf_..."},
)
```

Para un script sin encabezado, enumera las dependencias en el momento de la ejecución con `--with`, una vez por paquete: `--with trl --with peft` (`dependencies=["trl", "peft"]` en Python). El script también puede ser una URL, como un enlace raw de GitHub, un Gist o un archivo en un repositorio público de Hub.

La configuración de lanzamiento también puede estar en el script. Una tabla `[tool.hf-jobs]` en la cabecera establece el hardware, el tiempo de espera y los secretos:

```python
# /// script
# dependencies = [
#     "trl",
#     "peft",
# ]
#
# [tool.hf-jobs]
# flavor = "a10g-small"
# timeout = "30m"
# secrets = ["HF_TOKEN"]
# ///
```

`hf jobs uv run train.py` ya no requiere opciones, y una opción que se pase sigue sobrescribiendo al script. El script contiene todo lo necesario para ejecutarse, por lo que se puede compartir o volver a él más adelante sin tener que recordar qué GPU y timeout necesita. `hf jobs uv run --dry-run train.py` muestra la configuración resuelta y marca los valores que provienen del script. La tabla solo la lee la CLI de `hf`: `run_uv_job()` la ignora. Consulte [Definir la configuración de lanzamiento en el script](https://huggingface.co/docs/hub/jobs-configuration#define-the-launch-config-in-the-script).

## Ejecutar cualquier script de TRL

El mismo patrón se aplica a todos los scripts de los entrenadores de TRL (SFT, DPO, GRPO, modelado de recompensas y otros) y a los ejemplos independientes `.py` del [Índice de ejemplos](example_overview#index). Cada uno declara sus dependencias en la cabecera del script. Un ejemplo que lee otros archivos ubicados en la misma carpeta requiere que su carpeta esté montada en el Job. Consulte [Directorios locales](https://huggingface.co/docs/hub/jobs-configuration#local-directories). Los ejemplos exclusivos de notebooks no pueden enviarse de esta manera. Los argumentos del script son los mismos que cuando se ejecuta localmente.

## Conservar puntos de control

El disco de un Job se elimina cuando el Job termina, incluido cuando alcanza su tiempo de espera o falla. Para una ejecución prolongada, guarda los puntos de control fuera del Job para que sobrevivan a su finalización.

La forma más sencilla es enviar cada punto de control al repositorio del modelo de salida a medida que se guarda:

```bash
hf jobs uv run \
    --flavor a10g-small \
    --timeout 3h \
    --secrets HF_TOKEN \
    -- \
    https://raw.githubusercontent.com/huggingface/trl/refs/heads/main/trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B-Instruct \
    --dataset_name trl-lib/Capybara \
    --output_dir Qwen2-0.5B-SFT \
    --push_to_hub \
    --save_steps 500 \
    --hub_strategy checkpoint
```

```python
from huggingface_hub import run_uv_job

run_uv_job(
    "https://raw.githubusercontent.com/huggingface/trl/refs/heads/main/trl/scripts/sft.py",
    flavor="a10g-small",
    timeout="3h",
    secrets={"HF_TOKEN": "hf_..."},
    script_args=[
        "--model_name_or_path", "Qwen/Qwen2-0.5B-Instruct",
        "--dataset_name", "trl-lib/Capybara",
        "--output_dir", "Qwen2-0.5B-SFT",
        "--push_to_hub",
        "--save_steps", "500",
        "--hub_strategy", "checkpoint",
    ],
)
```

Con `--hub_strategy checkpoint`, el punto de control más reciente, incluido el estado del optimizador, se conserva en una carpeta `last-checkpoint` del repositorio. Para continuar una ejecución interrumpida, monte el repositorio en un nuevo Job y reanude desde esa carpeta: lance el mismo comando con `--volume hf://<your-username>/Qwen2-0.5B-SFT:/previous` antes de `--` y `--resume_from_checkpoint /previous/last-checkpoint` después de la URL del script.

Para mantener varios puntos de control fuera del repositorio del modelo, escríbalos en un [Storage Bucket](https://huggingface.co/docs/hub/storage-buckets) en su lugar. Cree uno con `hf buckets create <your-username>/checkpoints --private`, munte el bucket en el Job y apunte `--output_dir` a él:

```bash
hf jobs uv run \
    --flavor a10g-small \
    --timeout 3h \
    --secrets HF_TOKEN \
    --volume hf://buckets/<your-username>/checkpoints:/checkpoints \
    -- \
    https://raw.githubusercontent.com/huggingface/trl/refs/heads/main/trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B-Instruct \
    --dataset_name trl-lib/Capybara \
    --output_dir /checkpoints/Qwen2-0.5B-SFT \
    --save_steps 500
```

```python
from huggingface_hub import Volume, run_uv_job

run_uv_job(
    "https://raw.githubusercontent.com/huggingface/trl/refs/heads/main/trl/scripts/sft.py",
    flavor="a10g-small",
    timeout="3h",
    secrets={"HF_TOKEN": "hf_..."},
    volumes=[Volume(type="bucket", source="<your-username>/checkpoints", mount_path="/checkpoints")],
    script_args=[
        "--model_name_or_path", "Qwen/Qwen2-0.5B-Instruct",
        "--dataset_name", "trl-lib/Capybara",
        "--output_dir", "/checkpoints/Qwen2-0.5B-SFT",
        "--save_steps", "500",
    ],
)
```

Para continuar una ejecución interrumpida, vuelve a lanzar el mismo comando con `--resume_from_checkpoint /checkpoints/Qwen2-0.5B-SFT/checkpoint-<step>`. Consulte [Write to a bucket as you go](https://huggingface.co/docs/hub/jobs-training#after-it-ends) para más información y [Volumes](https://huggingface.co/docs/hub/jobs-configuration#volumes) para las opciones de montaje.

> [!TIP]
> Cada punto de control contiene el estado del modelo y del optimizador, lo que ocupa varias veces el tamaño del modelo. Añade `--save_total_limit 2` para conservar solo los más recientes. Si también pasas `--push_to_hub`, configura `--hub_model_id`, o el repositorio se nombrará según la última parte de la ruta de salida.

## Varias GPU

Un sabor con varias GPUs acorta la ejecución. Para ello, usa `hf jobs run`, que ejecuta un comando en una imagen de Docker en lugar de un script, con la imagen [`huggingface/trl`](https://hub.docker.com/r/huggingface/trl), que tiene TRL y Accelerate instalados. Luego, inicia un proceso por GPU. Esto funciona para los scripts de TRL y para tu propio código de entrenamiento.

### Acelerar un script de TRL

La ejecución de SFT desde el inicio de esta guía, en cuatro GPUs:

```bash
hf jobs run \
    --flavor l4x4 \
    --timeout 30m \
    --secrets HF_TOKEN \
    huggingface/trl \
    -- \
    trl sft --nproc_per_node 4 \
    --model_name_or_path Qwen/Qwen2-0.5B-Instruct \
    --dataset_name trl-lib/Capybara \
    --max_steps 100 \
    --output_dir Qwen2-0.5B-SFT \
    --push_to_hub
```

```python
from huggingface_hub import run_job

run_job(
    image="huggingface/trl",
    command=[
        "trl", "sft", "--nproc_per_node", "4",
        "--model_name_or_path", "Qwen/Qwen2-0.5B-Instruct",
        "--dataset_name", "trl-lib/Capybara",
        "--max_steps", "100",
        "--output_dir", "Qwen2-0.5B-SFT",
        "--push_to_hub",
    ],
    flavor="l4x4",
    timeout="30m",
    secrets={"HF_TOKEN": "hf_..."},
)
```

El [`trl` CLI](clis) pasa `--nproc_per_node` a `torchrun`. Establécelo en el número de GPUs del flavor, en este caso cuatro L4. Cada proceso toma su propio batch, por lo que el tamaño de batch efectivo es cuatro veces el de una ejecución con una sola GPU. Esta ejecución tarda unos minutos. Sin `--max_steps`, los tres epochs completos tardan aproximadamente una hora, así que aumenta `--timeout`, por ejemplo a `2h`.

### Tu propio script

No estás limitado a los scripts de TRL. El código de entrenamiento que se ejecuta con `torchrun` localmente funciona de la misma manera en Jobs, siempre que la imagen tenga los paquetes necesarios. Por ejemplo, guarda un script de GRPO con tu propia función de recompensa como `train_grpo.py` en una carpeta y monta esa carpeta en el Job. Jobs sube la carpeta a un bucket privado y la monta de solo lectura:

```bash
hf jobs run \
    --flavor l4x4 \
    --timeout 30m \
    --secrets HF_TOKEN \
    --volume ./my-project:/code \
    huggingface/trl \
    -- \
    torchrun --nproc_per_node 4 /code/train_grpo.py
```

```python
from huggingface_hub import run_job, sync_job_volume

code = sync_job_volume("./my-project", "/code")
run_job(
    image="huggingface/trl",
    command=["torchrun", "--nproc_per_node", "4", "/code/train_grpo.py"],
    flavor="l4x4",
    timeout="30m",
    secrets={"HF_TOKEN": "hf_..."},
    volumes=[code],
)
```

El script se ejecuta con TRL instalado en la imagen, por lo que no necesita encabezado de script. `GRPOTrainer` genera completados con transformers de forma predeterminada, por lo que esto se ejecuta en un solo Job sin servidor vLLM. Para una generación más rápida, consulte [vLLM Integration](vllm_integration). La siguiente sección explica cómo `hf jobs run` utiliza la imagen.

## Imágenes de Docker

Jobs ejecuta tu script con `uv`, que instala las dependencias declaradas en su cabecera `# /// script` en un entorno nuevo. Por lo tanto, la librería TRL que tu script importa proviene de esa cabecera, no de la imagen, y los ejemplos de `hf jobs uv run` anteriores no necesitan `--image` en absoluto.

Hay una imagen de Docker con TRL preinstalada disponible en [huggingface/trl](https://hub.docker.com/r/huggingface/trl). Al pasarla a `hf jobs uv run`, el trabajo recibe la capa de sistema de la imagen, como su cadena de herramientas CUDA, lo cual es importante para las dependencias que se compilan contra ella:

```bash
hf jobs uv run \
    --flavor a100-large \
    --secrets HF_TOKEN \
    --image huggingface/trl \
    train.py
```

```python
from huggingface_hub import run_uv_job

run_uv_job(
    "train.py",
    flavor="a100-large",
    secrets={"HF_TOKEN": "hf_..."},
    image="huggingface/trl",
)
```

Para ejecutar el TRL que está instalado en la imagen, use `hf jobs run` en su lugar. Ejecuta un comando directamente en la imagen, sin encabezado de script que resolver, por lo que el TRL propio de la imagen es el que se ejecuta. `--` separa el comando de las opciones de Jobs, lo cual es necesario siempre que el propio comando tome opciones:

```bash
hf jobs run \
    --flavor a100-large \
    --secrets HF_TOKEN \
    huggingface/trl \
    -- \
    trl sft --model_name_or_path Qwen/Qwen2-0.5B-Instruct --dataset_name trl-lib/Capybara --output_dir Qwen2-0.5B-SFT
```

```python
from huggingface_hub import run_job

run_job(
    image="huggingface/trl",
    command=[
        "trl", "sft",
        "--model_name_or_path", "Qwen/Qwen2-0.5B-Instruct",
        "--dataset_name", "trl-lib/Capybara",
        "--output_dir", "Qwen2-0.5B-SFT",
    ],
    flavor="a100-large",
    secrets={"HF_TOKEN": "hf_..."},
)
```

La imagen se publica con tres tipos de etiqueta:

| Etiqueta | Contenido |
| --- | --- |
| `X.Y.Z` | La versión de TRL de esa versión, construida cuando se publica esa versión |
| `latest` | La versión más reciente |
| `dev` | La rama `main`, reconstruida en cada fusión |

Use `dev` para ejecutar la versión de desarrollo, que es útil para probar una corrección que ya está en `main` pero que aún no se ha publicado:

```bash
hf jobs run \
    --flavor a100-large \
    --secrets HF_TOKEN \
    huggingface/trl:dev \
    -- \
    trl sft --model_name_or_path Qwen/Qwen2-0.5B-Instruct --dataset_name trl-lib/Capybara --output_dir Qwen2-0.5B-SFT
```

```python
from huggingface_hub import run_job

run_job(
    image="huggingface/trl:dev",
    command=[
        "trl", "sft",
        "--model_name_or_path", "Qwen/Qwen2-0.5B-Instruct",
        "--dataset_name", "trl-lib/Capybara",
        "--output_dir", "Qwen2-0.5B-SFT",
    ],
    flavor="a100-large",
    secrets={"HF_TOKEN": "hf_..."},
)
```

Las etiquetas solo seleccionan lo que está instalado en la imagen, por lo que son relevantes para `hf jobs run`. Con `hf jobs uv run`, la versión proviene del encabezado del script, y la etiqueta no tiene ninguna diferencia en qué TRL se importa.

Combinar ambos, de modo que `uv` resuelva la cabecera del script mientras algunas importaciones siguen provienen de la imagen, requiere banderas adicionales. Consulte [Reutilizar los paquetes de la imagen y añadir dependencias con UV](https://huggingface.co/docs/hub/jobs-images#reuse-the-images-packages-and-add-dependencies-with-uv) para ese formato y las rutas que requiere.

Jobs se ejecuta en una imagen de Docker de Hugging Face Spaces o Docker Hub, por lo que también puedes especificar cualquier imagen personalizada:

```bash
hf jobs uv run \
    --flavor a100-large \
    --secrets HF_TOKEN \
    --image <docker-image> \
    train.py
```

```python
from huggingface_hub import run_uv_job

run_uv_job(
    "train.py",
    flavor="a100-large",
    secrets={"HF_TOKEN": "hf_..."},
    image="<docker-image>",
)
```

> [!NOTE]
> El envoltorio [TRL Jobs](https://github.com/huggingface/trl-jobs) inicia los scripts de TRL en Jobs con configuraciones preestablecidas para algunos modelos, por ejemplo `trl-jobs sft --model_name Qwen/Qwen3-0.6B --dataset_name trl-lib/Capybara`.

