# Ejecutar y gestionar Jobs

El Hugging Face Hub ofrece recursos de cómputo para flujos de trabajo de IA y datos a través de Jobs.

**Para una visión general de Jobs y precios, consulte la [documentación de Hub Jobs](https://huggingface.co/docs/hub/jobs).**

Un trabajo se ejecuta en la infraestructura de Hugging Face y se define con un comando para ejecutar (por ejemplo, un comando de python), una imagen de Docker de Hugging Face Spaces o Docker Hub, y un tipo de hardware (CPU, GPU, TPU). Esta guía te mostrará cómo interactuar con los trabajos en el Hub, en especial:

- Ejecutar un trabajo.
- Comprueba el estado del trabajo.
- Seleccione el hardware.
- Configure las variables de entorno y los secretos.
- Ejecuta scripts de UV.

Si deseas ejecutar y gestionar un trabajo en el Hub, tu máquina debe estar iniciada sesión. Si no es así, consulta [esta sección](../quick-start#authentication). En el resto de esta guía, asumiremos que tu máquina tiene la sesión iniciada.

> [!TIP]
> **Hugging Face Jobs** están disponibles para cualquier usuario u organización con un [saldo de crédito](https://huggingface.co/settings/billing) positivo. Consulta [Jobs pricing and billing](https://huggingface.co/docs/hub/jobs-pricing) para más detalles.

## Interfaz de línea de comandos de Jobs

Use la CLI [`hf jobs`](./cli#hf-jobs) para ejecutar Jobs desde la línea de comandos y pase `--flavor` para especificar su hardware.

`hf jobs run` ejecuta Jobs con una imagen de Docker y un comando mediante una interfaz similar a la de Docker. Piensa en `docker run`, pero para ejecutar código en cualquier hardware:

```bash
>>> hf jobs run --name hello-world python:3.12 python -c "print('Hello world')"
>>> hf jobs run --name gpu-check --flavor a10g-small pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel python -c "import torch; print(torch.cuda.get_device_name())"
```

Use `hf jobs uv run` para ejecutar scripts UV locales o remotos:

```bash
>>> hf jobs uv run --name my-script my_script.py
>>> hf jobs uv run --name sft-training --flavor a10g-small "https://raw.githubusercontent.com/huggingface/trl/main/trl/scripts/sft.py"
```

Los scripts de UV son scripts de Python que incluyen sus dependencias directamente en el archivo mediante una sintaxis de comentario especial definida en la [documentación de UV](https://docs.astral.sh/uv/guides/scripts/).

Ahora, el resto de esta guía te mostrará la API de python. Si prefieres ver todos los comandos y opciones disponibles de `hf jobs`, consulta la [guía sobre la interfaz de línea de comandos de `hf jobs`](./cli#hf-jobs).

> [!TIP]
> ¿Necesitas una máquina *interactiva* en lugar de un trabajo de ejecución y olvido, por ejemplo, para ejecutar código generado por IA, con ejecución de comandos y transferencia de archivos? Echa un vistazo a [Sandboxes](./sandbox), construido sobre Jobs.

## Ejecutar un trabajo

Ejecuta Jobs de cómputo definidos con un comando y una imagen de Docker en la infraestructura de Hugging Face (incluidas GPUs y TPUs).

Solo puedes gestionar los Jobs que te pertenecen (bajo el espacio de nombres de tu nombre de usuario) o los de organizaciones en las que tienes permisos de escritura. Esta función tiene un modelo de pago por uso: solo pagas por los segundos que utilices.

[run_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.run_job) te permite ejecutar cualquier comando en la infraestructura de Hugging Face:

```python
# Directly run Python code
>>> from huggingface_hub import run_job
>>> run_job(
...     image="python:3.12",
...     command=["python", "-c", "print('Hello from the cloud!')"],
... )

# Use GPUs without any setup
>>> run_job(
...     image="pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel",
...     command=["python", "-c", "import torch; print(torch.cuda.get_device_name())"],
...     flavor="a10g-small",
... )

# Run in an organization account
>>> run_job(
...     image="python:3.12",
...     command=["python", "-c", "print('Running in an org account')"],
...     namespace="my-org-name",
... )

# Run from Hugging Face Spaces
>>> run_job(
...     image="hf.co/spaces/lhoestq/duckdb",
...     command=["duckdb", "-c", "select 'hello world'"],
... )

# Run a Python script with `uv` (experimental)
>>> from huggingface_hub import run_uv_job
>>> run_uv_job("my_script.py")
```

> [!WARNING]
> **Importante**: Los trabajos tienen un tiempo de espera predeterminado (30 minutos), tras el cual se detienen automáticamente. Para tareas de larga duración, como el entrenamiento de modelos, asegúrate de configurar un tiempo de espera personalizado mediante el parámetro `timeout`. Consulta [Configurar el tiempo de espera del trabajo](#configure-job-timeout) para más detalles.

[run_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.run_job) devuelve el [JobInfo](/docs/huggingface_hub/v2.4.0/es/package_reference/jobs#huggingface_hub.JobInfo), que contiene la URL del trabajo en Hugging Face, donde puedes ver el estado del trabajo y los registros. Guarda el ID del trabajo de [JobInfo](/docs/huggingface_hub/v2.4.0/es/package_reference/jobs#huggingface_hub.JobInfo) para gestionar el trabajo:

```python
>>> from huggingface_hub import run_job
>>> job = run_job(
...     image="python:3.12",
...     command=["python", "-c", "print('Hello from the cloud!')"]
... )
>>> job.url
https://huggingface.co/jobs/lhoestq/687f911eaea852de79c4a50a
>>> job.id
687f911eaea852de79c4a50a
```

Los trabajos se ejecutan en segundo plano. La siguiente sección te guía a través de [inspect_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.inspect_job) para conocer el estado de un trabajo, [fetch_job_logs()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.fetch_job_logs) para ver los registros y [fetch_job_metrics()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.fetch_job_metrics) para monitorear el uso de recursos.

## Reintentar y volver a ejecutar un Job

Use `attempts` para reintentar un Job fallido. El número incluye el intento inicial, por lo que `attempts=3` permite hasta dos reintentos. También funciona con `run_uv_job`, `create_scheduled_job` y `create_scheduled_uv_job`.

```python
>>> from huggingface_hub import rerun_job, run_job
>>> job = run_job(image="python:3.12", command=["python", "train.py"], attempts=3)
>>> job.retry
2

# Start a new Job with the same spec, including its retry setting
>>> new_job = rerun_job(job_id=job.id)
```

`rerun_job` inicia un Job separado con un nuevo ID. Funciona con Jobs completados o fallidos y reutiliza la especificación guardada, incluidos los secretos y la configuración de hardware. También puedes ejecutar `hf jobs rerun <job_id>`.

## Comprobar el estado del trabajo

```python
# List your jobs (results are paginated and returned as an iterator)
>>> from huggingface_hub import list_jobs
>>> jobs = list_jobs()
>>> next(iter(jobs))
JobInfo(id='687f911eaea852de79c4a50a', created_at=datetime.datetime(2025, 7, 22, 13, 24, 46, 909000, tzinfo=datetime.timezone.utc), docker_image='python:3.12', space_id=None, command=['python', '-c', "print('Hello from the cloud!')"], arguments=[], environment={}, secrets={}, flavor='cpu-basic', status=JobStatus(stage='COMPLETED', message=None), owner=JobOwner(id='5e9ecfc04957053f60648a3e', name='lhoestq'), endpoint='https://huggingface.co', url='https://huggingface.co/jobs/lhoestq/687f911eaea852de79c4a50a')

# Materialize the iterator into a list
>>> all_jobs = [job for job in list_jobs()]

# List your running jobs
>>> running_jobs = list_jobs(status="RUNNING")

# Filter by one or more statuses and/or labels
>>> list_jobs(status=["RUNNING", "SCHEDULING"], labels={"env": "prod"})

# Inspect the status of a job
>>> from huggingface_hub import inspect_job
>>> inspect_job(job_id=job_id)
JobInfo(id='687f911eaea852de79c4a50a', created_at=datetime.datetime(2025, 7, 22, 13, 24, 46, 909000, tzinfo=datetime.timezone.utc), docker_image='python:3.12', space_id=None, command=['python', '-c', "print('Hello from the cloud!')"], arguments=[], environment={}, secrets={}, flavor='cpu-basic', status=JobStatus(stage='COMPLETED', message=None), owner=JobOwner(id='5e9ecfc04957053f60648a3e', name='lhoestq'), endpoint='https://huggingface.co', url='https://huggingface.co/jobs/lhoestq/687f911eaea852de79c4a50a')

# View logs from a job
>>> from huggingface_hub import fetch_job_logs
>>> for log in fetch_job_logs(job_id=job_id):
...     print(log)
Hello from the cloud!

# View resources usage metrics from a job
>>> from huggingface_hub import fetch_job_metrics
>>> for metrics in fetch_job_metrics(job_id=job_id):
...     print(metrics)
{
    "cpu_usage_pct": 0,
    "cpu_millicores": 2000,
    "memory_used_bytes": 929792,
    "memory_total_bytes": 17179869184,
    "rx_bps": 0,
    "tx_bps": 0,
    "gpus": {},
    "replica": "4dzsh"
}

# Cancel a job
>>> from huggingface_hub import cancel_job
>>> cancel_job(job_id=job_id)
```

## Espera a que los trabajos terminen

Use [wait_for_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.wait_for_job) para bloquear hasta que un Job alcance una etapa terminal (`COMPLETED`, `CANCELED`, `ERROR` o `DELETED`). Siempre se devuelve el [JobInfo](/docs/huggingface_hub/v2.4.0/es/package_reference/jobs#huggingface_hub.JobInfo) final: un Job fallido no lanza una excepción, por lo que debe comprobar `job.status.stage` para actuar según el resultado. Pase una lista de IDs de Job para esperar a un lote completo a la vez.

```python
>>> from huggingface_hub import run_job, wait_for_job
>>> job = run_job(image="python:3.12", command=["python", "-c", "print('hello')"])
>>> wait_for_job(job_id=job.id).status.stage
'COMPLETED'

# Run multiple jobs in parallel and wait for all of them to finish
>>> jobs = [run_job(image=image, command=command) for command in commands]
>>> finished_jobs = wait_for_job(job_id=[job.id for job in jobs], timeout=3600)
```

Lo mismo está disponible en la CLI con `hf jobs wait`, que finaliza con código 0 solo si todos los Jobs se completaron con éxito, lo cual es útil para encadenar comandos en scripts de shell o CI:

```bash
# Chain on success
hf jobs wait <job_id> && hf jobs run --detach python:3.12 python eval.py

# Wait for all currently running jobs
hf jobs ls -q | xargs hf jobs wait
```

Tenga en cuenta que un `hf jobs run` no desvinculado (o `hf jobs uv run`) también finaliza con un código no cero si el Job falla, por lo que `hf jobs run ... && next-step` encadena correctamente sin una espera explícita.

## Selecciona el hardware

Existen numerosos casos en los que resulta útil ejecutar Jobs en GPUs:

- **Entrenamiento de modelos**: Ajuste fino o entrenamiento de modelos en GPUs (T4, A10G, A100) sin gestionar la infraestructura
- **Generación de datos sintéticos**: Genera conjuntos de datos a gran escala utilizando LLMs en hardware potente
- **Procesamiento de datos**: Procesa conjuntos de datos masivos con configuraciones de CPU de alto rendimiento para cargas de trabajo paralelas
- **Inferencia por lotes**: Ejecuta inferencia sin conexión en miles de muestras usando configuraciones de GPU optimizadas
- **Experimentos y benchmarks**: Ejecuta experimentos de ML en hardware consistente para obtener resultados reproducibles
- **Desarrollo y depuración**: Prueba el código de GPU sin configuración local de CUDA

Ejecuta trabajos en GPUs o TPUs con el argumento `flavor`. Por ejemplo, para ejecutar un trabajo de PyTorch en una GPU A10G:

```python
# Use an A10G GPU to check PyTorch CUDA
>>> from huggingface_hub import run_job
>>> run_job(
...     image="pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel",
...     command=["python", "-c", "import torch; print(f'This code ran with the following GPU: {torch.cuda.get_device_name()}')"],
...     flavor="a10g-small",
... )
```

Al ejecutarlo, se mostrará la siguiente salida.

```bash
This code ran with the following GPU: NVIDIA A10G
```

Use esto para ejecutar un script de ajuste fino como [trl/scripts/sft.py](https://github.com/huggingface/trl/blob/main/trl/scripts/sft.py) con UV:

```python
>>> from huggingface_hub import run_uv_job
>>> run_uv_job(
...     "sft.py",
...     script_args=["--model_name_or_path", "Qwen/Qwen2-0.5B", ...],
...     dependencies=["trl"],
...     env={"HF_TOKEN": ...},
...     flavor="a10g-small",
... )
```

> [!TIP]
> Para obtener una guía completa sobre la ejecución de trabajos de entrenamiento de modelos con TRL en la infraestructura de Hugging Face, consulte la [documentación de TRL Jobs Training](https://huggingface.co/docs/trl/main/en/jobs_training). Aborda recetas de ajuste fino, selección de hardware y mejores prácticas para entrenar modelos de manera eficiente.

Esta es la lista completa de hardware disponible para ejecutar Jobs:

| name | nombre | cpu | ram | almacenamiento | accelerator | costo/min | costo/hora |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `cpu-basic` | Básico de CPU | 2 vCPU | 16 GB | 50 GB | - | $0.0002 | $0.01 |
| `cpu-upgrade` | Mejora de CPU | 8 vCPU | 32 GB | 50 GB | - | $0.0005 | $0.03 |
| `cpu-performance` | Rendimiento de la CPU | 32 vCPU | 256 GB | 1024 GB | - | $0.0317 | $1.90 |
| `cpu-xl` | CPU XL | 16 vCPU | 124 GB | 1000 GB | - | $0.0167 | $1.00 |
| `t4-small` | Nvidia T4 - pequeño | 4 vCPU | 15 GB | 50 GB | 1x T4 (16 GB) | $0.0067 | $0.40 |
| `t4-medium` | Nvidia T4 - medio | 8 vCPU | 30 GB | 100 GB | 1x T4 (16 GB) | $0.0100 | $0.60 |
| `a10g-small` | Nvidia A10G - pequeño | 4 vCPU | 15 GB | 110 GB | 1x A10G (24 GB) | $0.0167 | $1.00 |
| `a10g-large` | Nvidia A10G - grande | 12 vCPU | 46 GB | 200 GB | 1x A10G (24 GB) | $0.0250 | $1.50 |
| `a10g-largex2` | 2x Nvidia A10G - grande | 24 vCPU | 92 GB | 1000 GB | 2x A10G (48 GB) | $0.0500 | $3.00 |
| `a10g-largex4` | 4x Nvidia A10G - grande | 48 vCPU | 184 GB | 2000 GB | 4x A10G (96 GB) | $0.0833 | $5.00 |
| `a100-large` | Nvidia A100 - grande | 12 vCPU | 142 GB | 1000 GB | 1x A100 (80 GB) | $0.0417 | $2.50 |
| `a100x4` | 4x Nvidia A100 | 48 vCPU | 568 GB | 4000 GB | 4x A100 (320 GB) | $0.1667 | $10.00 |
| `a100x8` | 8x Nvidia A100 | 96 vCPU | 1136 GB | 8000 GB | 8x A100 (640 GB) | $0.3333 | $20.00 |
| `h200` | Nvidia H200 | 23 vCPU | 256 GB | 3000 GB | 1x H200 (141 GB) | $0.0833 | $5.00 |
| `h200x2` | Nvidia H200 | 46 vCPU | 512 GB | 6000 GB | 2x H200 (282 GB) | $0.1667 | $10.00 |
| `h200x4` | Nvidia H200 | 92 vCPU | 1024 GB | 12000 GB | 4x H200 (564 GB) | $0.3333 | $20.00 |
| `h200x8` | Nvidia H200 | 184 vCPU | 2048 GB | 24000 GB | 8x H200 (1128 GB) | $0.6667 | $40.00 |
| `rtx-pro-6000` | Nvidia RTX PRO 6000 | 23 vCPU | 256 GB | 475 GB | 1x RTX PRO 6000 (96 GB) | $0.0458 | $2.75 |
| `rtx-pro-6000x2` | Nvidia RTX PRO 6000 | 46 vCPU | 512 GB | 950 GB | 2x RTX PRO 6000 (192 GB) | $0.0917 | $5.50 |
| `rtx-pro-6000x4` | Nvidia RTX PRO 6000 | 92 vCPU | 1024 GB | 1900 GB | 4x RTX PRO 6000 (384 GB) | $0.1833 | $11.00 |
| `rtx-pro-6000x8` | Nvidia RTX PRO 6000 | 184 vCPU | 2048 GB | 3800 GB | 8x RTX PRO 6000 (768 GB) | $0.3667 | $22.00 |
| `l4x1` | 1x Nvidia L4 | 8 vCPU | 30 GB | 400 GB | 1x L4 (24 GB) | $0.0133 | $0.80 |
| `l4x4` | 4x Nvidia L4 | 48 vCPU | 186 GB | 3200 GB | 4x L4 (96 GB) | $0.0633 | $3.80 |
| `l40sx1` | 1x Nvidia L40S | 8 vCPU | 62 GB | 380 GB | 1x L40S (48 GB) | $0.0300 | $1.80 |
| `l40sx4` | 4x Nvidia L40S | 48 vCPU | 382 GB | 3200 GB | 4x L40S (192 GB) | $0.1383 | $8.30 |
| `l40sx8` | 8x Nvidia L40S | 192 vCPU | 1534 GB | 6500 GB | 8x L40S (384 GB) | $0.3917 | $23.50 |

Puedes obtener esta lista de forma programática ejecutando:

```bash
>>> hf jobs hardware
```

O usando la API de Python:

```python
>>> from huggingface_hub import list_jobs_hardware
>>> list_jobs_hardware()
```

¡Listo! Ahora estás ejecutando código en la infraestructura de Hugging Face.

## Montar un volumen

Monte un volumen en el disco de los Jobs usando una lista de [Volume](/docs/huggingface_hub/v2.4.0/es/package_reference/jobs#huggingface_hub.Volume).

Puedes montar cualquier Repositorio de Hugging Face (modelo/conjunto de datos/espacio) o [Storage Bucket](/docs/hub/storage-buckets). Por ejemplo:

* montar un repositorio de modelos: `Volume(type="model", source="openai/gpt-oss-120b", mount_path="/model")`
* montar un repositorio de datos: `Volume(type="dataset", source="HuggingFaceFW/fineweb", mount_path="/data")`
* montar un bucket de almacenamiento: `Volume(type="bucket", source="username/my-bucket", mount_path="/mnt")`

Luego, puede usar el volumen montado como un directorio local:

```python
>>> from huggingface_hub import run_job, Volume
>>> job = run_job(
...     image="duckdb/duckdb",
...     command=["duckdb", "-c", "SELECT * FROM '/data/**/*.parquet' LIMIT 5"],
...     volumes=[Volume(type="dataset", source="HuggingFaceFW/fineweb", mount_path="/data")],
... )
```

También puede escribir en un bucket montado, por ejemplo, para guardar puntos de control al entrenar un modelo:

```python
>>> from huggingface_hub import run_uv_job, Volume
>>> script = "my_sft.py"
>>> script_args = ["--output_dir", "/training-outputs/training-v3-final", ...]
>>> checkpoints_bucket = Volume(type="bucket", source="username/my-bucket", mount_path="/training-outputs")
>>> run_uv_job(script, script_args=script_args, volumes=[checkpoints_bucket])
```

Por defecto, los buckets de almacenamiento montados tienen permisos de lectura y escritura. Esto resulta especialmente útil para los buckets de almacenamiento, que proporcionan un almacenamiento rápido y mutable para datos que cambian con frecuencia: los archivos pueden sobrescribirse o eliminarse en su ubicación original.

Use `read_only=True` para habilitar solo lectura: `Volume(type="bucket", read_only=True, ...)`.

### Montar datos locales

Para ejecutar un Job con datos de tu máquina, usa [sync_job_volume()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.sync_job_volume): sincroniza un directorio local con tu [Storage Bucket](https://huggingface.co/docs/hub/storage-buckets) `jobs-artifacts` (creado automáticamente si es necesario) y devuelve un [Volume](/docs/huggingface_hub/v2.4.0/es/package_reference/jobs#huggingface_hub.Volume) listo para montar:

```python
>>> from huggingface_hub import run_uv_job, sync_job_volume

# Upload ./training-data once...
>>> volume = sync_job_volume("./training-data", "/data")

# ...then run as many Jobs as you want against it
>>> run_uv_job("train.py", script_args=["--learning-rate", "0.01"], volumes=[volume])
>>> run_uv_job("train.py", script_args=["--learning-rate", "0.05"], volumes=[volume])
```

Cada directorio obtiene su propia carpeta estable en el bucket: volver a ejecutar [sync_job_volume()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.sync_job_volume) en el mismo directorio solo sube archivos nuevos o modificados. El volumen se monta de solo lectura de forma predeterminada.

Para recuperar los archivos escritos por un Job, monte un volumen de lectura y escritura (también funciona un directorio de salida vacío) y síncronelo de vuelta cuando el Job termine:

```python
>>> from huggingface_hub import run_uv_job, sync_bucket, sync_job_volume

>>> outputs = sync_job_volume("./outputs", "/outputs", read_only=False)
>>> job = run_uv_job("process.py", volumes=[outputs])

# ...once the Job completes, pull back the data:
>>> sync_bucket(f"hf://buckets/{outputs.source}/{outputs.path}", "./outputs")
```

En la CLI, simplemente pase un directorio local como el lado de origen de `-v`:

```bash
>>> hf jobs uv run -v ./pdfs:/input -v ./md-out:/output:rw ocr.py
```

## Exponer los puertos del trabajo

Pase `expose` para hacer que un puerto de contenedor sea accesible a través del proxy de Jobs. El acceso requiere un token de HF con permiso de lectura en el espacio de nombres del Job. Use `expose_public` en su lugar para permitir el acceso sin autenticación:

```python
>>> from huggingface_hub import run_job, update_job_expose
>>> job = run_job(
...     image="python:3.12",
...     command=["python", "-m", "http.server", "8000"],
...     expose_public=[8000],
... )
>>> job.expose_public
[8000]

# Keep the port exposed, but require an HF token from now on
>>> job = update_job_expose(job_id=job.id, expose=[8000])

# Close all exposed ports
>>> job = update_job_expose(job_id=job.id)
```

`expose` y `expose_public` se pueden combinar. `update_job_expose` reemplaza la configuración completa de puertos en un Job en ejecución sin reiniciarlo: los puertos que no están en ninguna de las dos listas se cierran. Ambas opciones también están disponibles al crear Jobs UV y programados.

## Conectarse a un trabajo mediante SSH

Pase `ssh=True` a [run_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.run_job) (o [run_uv_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.run_uv_job)) para que el contenedor del Job sea accesible a través de SSH. El punto de conexión SSH está disponible en el estado del Job:

```python
>>> from huggingface_hub import run_job
>>> job = run_job(
...     image="python:3.12",
...     command=["sleep", "infinity"],
...     ssh=True,
... )
>>> job.status.ssh_url
'ssh://68498e23210b3a4f4e6e2a23@ssh.hf.jobs'
```

Conéctese desde una terminal con `hf jobs ssh <job_id>` (o directamente con `ssh <job_id>@ssh.hf.jobs`):

```bash
>>> hf jobs ssh 68498e23210b3a4f4e6e2a23
```

Solo se permite el acceso a los usuarios con permisos de escritura en el espacio de nombres del Job (el creador del Job o los miembros de la organización propietaria), autenticados mediante una clave pública SSH registrada en https://huggingface.co/settings/keys.

## Grupos de red

Pase `network_group="<name>"` a [run_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.run_job) (o [run_uv_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.run_uv_job)) para que los Jobs en el mismo namespace y grupo de recursos puedan comunicarse entre sí en todos los puertos. Dentro de cada miembro, `HF_NETWORK_GROUP_HOSTNAME` se resuelve a todos los Jobs del grupo, y `${HF_NETWORK_GROUP_PREFIX}<alias>` a los miembros que reclamaron un alias con `network_aliases=[...]`:

```python
>>> from huggingface_hub import run_job
>>> server = run_job(
...     image="python:3.12",
...     command=["python", "-m", "http.server", "8000"],
...     network_group="train",
...     network_aliases=["master"],
... )
>>> client = run_job(
...     image="python:3.12",
...     command=["sh", "-c", 'curl --retry 10 --retry-connrefused "http://${HF_NETWORK_GROUP_PREFIX}master:8000/"'],
...     network_group="train",
... )
>>> server.network
JobNetwork(group='train', aliases=['master'])
```

Los miembros son resolubles antes de estar listos, por lo que debe conectarse con reintentos. Los nombres y alias de grupo son alfanuméricos en minúsculas y guiones, con un máximo de 46 y 34 caracteres, respectivamente.

## Configurar el tiempo de espera del trabajo

Los trabajos tienen un tiempo de espera predeterminado (30 minutos), tras el cual se detienen automáticamente. Es importante tenerlo en cuenta al ejecutar tareas de larga duración, como el entrenamiento de modelos.

### Establecer un tiempo de espera personalizado

Puede especificar un valor de tiempo de espera personalizado usando el parámetro `timeout` al ejecutar un trabajo. El tiempo de espera se puede especificar de dos formas:

1. **Como un número** (interpretado como segundos):
```python
>>> from huggingface_hub import run_job
>>> job = run_job(
...     image="pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel",
...     command=["python", "train_model.py"],
...     flavor="a10g-large",
...     timeout=7200,  # 2 hours in seconds
... )
```

2. **Como una cadena con unidades de tiempo**:
```python
>>> # Using different time units
>>> job = run_job(
...     image="pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel",
...     command=["python", "train_model.py"],
...     flavor="a10g-large",
...     timeout="2h",  # 2 hours
... )

>>> # Other examples:
>>> # timeout="30m"    # 30 minutes
>>> # timeout="1.5h"   # 1.5 hours
>>> # timeout="1d"     # 1 day
>>> # timeout="3600s"  # 3600 seconds
```

Unidades de tiempo admitidas:
- `s` - segundos
- `m` - minutos
- `h` - horas
- `d` - días

### Uso de timeout con trabajos de UV

Para los trabajos de UV, también puedes especificar el tiempo de espera:

```python
>>> from huggingface_hub import run_uv_job
>>> job = run_uv_job(
...     "training_script.py",
...     flavor="a10g-large",
...     timeout="90m",  # 90 minutes
... )
```

> [!WARNING]
> Si no especificas un tiempo de espera, se aplicará un tiempo de espera predeterminado a tu trabajo. Para tareas de larga duración, como el entrenamiento de modelos que pueden llevar horas, asegúrate de establecer un tiempo de espera adecuado para evitar terminaciones inesperadas del trabajo.

### Supervisión de la duración de la tarea

Al ejecutar tareas largas, es buena práctica:
- Estima la duración esperada de tu trabajo y configura un tiempo de espera con un margen de seguridad
- Monitorea el progreso de tu trabajo a través de los registros
- Comprueba el estado del trabajo para asegurarte de que no ha caducado

```python
>>> from huggingface_hub import inspect_job, fetch_job_logs
>>> # Check job status
>>> job_info = inspect_job(job_id=job.id)
>>> if job_info.status.stage == "ERROR":
...     print(f"Job failed: {job_info.status.message}")
...     # Check logs for more details
...     for log in fetch_job_logs(job_id=job.id):
...         print(log)
```

Para más detalles sobre el parámetro de timeout, consulte la [referencia de la API `run_job`](https://huggingface.co/docs/huggingface_hub/package_reference/hf_api#huggingface_hub.HfApi.run_job.timeout).

## Pasar variables de entorno y secretos

Puedes pasar variables de entorno a tu trabajo usando `env` y `secrets`:

```python
# Pass environment variables
>>> from huggingface_hub import run_job
>>> run_job(
...     image="python:3.12",
...     command=["python", "-c", "import os; print(os.environ['FOO'], os.environ['BAR'])"],
...     env={"FOO": "foo", "BAR": "bar"},
... )
```

```python
# Pass secrets - they will be encrypted server side
>>> from huggingface_hub import run_job
>>> run_job(
...     image="python:3.12",
...     command=["python", "-c", "import os; print(os.environ['MY_SECRET'])"],
...     secrets={"MY_SECRET": "psswrd"},
... )
```

### Variables de entorno integradas

Dentro del contenedor del trabajo, las siguientes variables de entorno están disponibles automáticamente:

| Variable | Descripción |
|----------|-------------|
| `JOB_ID` | El identificador único del trabajo actual. Úselo para hacer referencia al trabajo de forma programática, por ejemplo, para almacenar las salidas en un conjunto de datos con un nombre único. |
| `ACCELERATOR` | El tipo de acelerador disponible (p. ej., `t4-medium`, `a10g-small`, `a100x4`). Vacío si no hay acelerador. |
| `CPU_CORES` | El número de núcleos de CPU disponibles para el trabajo (p. ej., `2`, `4`, `8`). |
| `MEMORY` | La cantidad de memoria disponible para el trabajo (p. ej., `16Gi`, `32Gi`). |

```python
# Access job environment information
>>> from huggingface_hub import run_job
>>> run_job(
...     image="python:3.12",
...     command=["python", "-c", """
... import os
... print(f"Job ID: {os.environ.get('JOB_ID')}")
... print(f"Accelerator: {os.environ.get('ACCELERATOR', 'none')}")
... print(f"CPU cores: {os.environ.get('CPU_CORES')}")
... print(f"Memory: {os.environ.get('MEMORY')}")
... """],
... )
```

Estas variables son útiles cuando necesitas crear identificadores únicos para las salidas, adaptar tu código según el hardware disponible o registrar información de recursos.

## Etiquetas

Las etiquetas son pares clave=valor que adjuntan metadatos a un Job:

Usa `name` para facilitar la búsqueda e identificación de los Jobs en la interfaz. Los nombres son opcionales y no tienen que ser únicos:

```python
>>> from huggingface_hub import run_job
>>> run_job(name="daily-report", image="python:3.12", command=["python", "report.py"])
```

Desde la CLI, pasa `--name` al crear un Job, o nombra un Job existente a través del comando labels:

```bash
>>> hf jobs run --name daily-report python:3.12 python report.py
>>> hf jobs labels <job_id> --name daily-report
```

`hf jobs ls` muestra una columna `NAME` y permite filtrar por nombre (un atajo para `--label name=NAME`):

```bash
>>> hf jobs ls -a --name daily-report
```

```python
# Pass extra metadata with Labels
>>> from huggingface_hub import run_job
>>> run_job(
...     image="python:3.12",
...     command=["python", "-c", "import os; print(os.environ['MY_SECRET'])"],
...     labels={"my-label": "my-value", "foo": "bar"},
... )
```

Si no se pasa un nombre, se deriva automáticamente a partir de la imagen de Docker o del script, más un hash corto (p. ej. `python:3.12 foo --truc` → `python-3-12-1a2b3c4d`). Desde la CLI, ese hash cubre el comando *y* la configuración de tiempo de ejecución resuelta (flavor, timeout, valores de entorno, ...), por lo que la misma configuración siempre produce el mismo nombre, y cambiar una configuración —incluida una que provenga del encabezado `[tool.hf-jobs]` de un script— la modifica. Desde la API de Python, el hash solo cubre el comando.

### Actualizar etiquetas

Use [update_job_labels()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.update_job_labels) para reemplazar las etiquetas de un trabajo existente. Esto reemplaza todas las etiquetas proporcionadas por el usuario:

```python
>>> from huggingface_hub import update_job_labels
>>> update_job_labels(job_id=job_id, labels={"env": "prod", "team": "ml"})
```

Esto también funciona para trabajos programados con [update_scheduled_job_labels()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.update_scheduled_job_labels):

```python
>>> from huggingface_hub import update_scheduled_job_labels
>>> update_scheduled_job_labels(scheduled_job_id=scheduled_job_id, labels={"env": "staging"})
```

Desde la CLI:

```bash
>>> hf jobs labels <job_id> --label env=prod --label team=ml
>>> hf jobs scheduled labels <scheduled_job_id> --label env=staging
```

Para eliminar todas las etiquetas, pase `--clear`:

```bash
>>> hf jobs labels <job_id> --clear
```

## UV Scripts (Experimental)

> [!TIP]
> ¿Buscas scripts de UV listos para usar? Consulta la [organización uv-scripts](https://huggingface.co/uv-scripts) en el Hugging Face Hub, que ofrece una colección comunitaria de scripts de UV para tareas como entrenamiento de modelos, generación de datos sintéticos, procesamiento de datos y más.

Ejecuta scripts de UV (scripts de Python con dependencias integradas) en la infraestructura de HF:

```python
# Run a UV script (creates temporary repo)
>>> from huggingface_hub import run_uv_job
>>> run_uv_job("my_script.py")

# Run with GPU
>>> run_uv_job("ml_training.py", flavor="gpu-t4-small")

# Run with dependencies
>>> run_uv_job("inference.py", dependencies=["transformers", "torch"])

# Run a script directly from a URL
>>> run_uv_job("https://huggingface.co/datasets/username/scripts/resolve/main/example.py")

# Run a command
>>> run_uv_job("python", script_args=["-c", "import lighteval"], dependencies=["lighteval"])
```

Los scripts de UV son scripts de Python que incluyen sus dependencias directamente en el archivo mediante una sintaxis de comentario especial. Esto los hace perfectos para tareas autónomas que no requieren configuraciones de proyecto complejas. Obtenga más información sobre los scripts de UV en la [documentación de UV](https://docs.astral.sh/uv/guides/scripts/).

#### Incluya la configuración de lanzamiento con el script

Un script que solo se ejecuta correctamente en un entorno de ejecución específico puede incluir ese entorno en una tabla opcional `[tool.hf-jobs]` de su encabezado PEP 723:

```python
# /// script
# requires-python = ">=3.11"
# dependencies = ["vllm", "datasets"]
#
# [tool.hf-jobs]
# image   = "vllm/vllm-openai:unlimited-ocr"
# flavor  = "l4x1"
# python  = "/usr/bin/python3"
# secrets = ["HF_TOKEN"]
# ///
```

`hf jobs uv run ocr.py` se inicia a continuación con la imagen, el hardware y el intérprete adecuados, y `--flavor`, `-e`, ... siguen sobrescribiendo lo que declara el script. Consulte la [guía de la CLI](./cli#ship-the-launch-config-with-the-script) para obtener la lista completa de claves y las reglas de fusión.

> [!WARNING]
> La tabla solo la lee la CLI `hf`: [run_uv_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.run_uv_job) y [create_scheduled_uv_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.create_scheduled_uv_job) la ignoran y usan exactamente los argumentos que se les pasan. En otras palabras, `run_uv_job("ocr.py")` y `hf jobs uv run ocr.py` no ejecutan **el mismo** Job: la API de Python necesita que se pasen explícitamente `image=`, `flavor=`, ...

#### Imágenes de Docker para scripts de UV

Aunque los scripts de UV pueden especificar sus dependencias de forma inline, las cargas de trabajo de ML suelen tener dependencias complejas. El uso de imágenes de Docker precompiladas con estas bibliotecas ya instaladas puede acelerar significativamente el inicio de los trabajos y evitar problemas de dependencias.

Por defecto, al ejecutar `hf jobs uv run` se utiliza la imagen `astral-sh/uv:python3.12-bookworm`. Esta imagen se basa en la distribución Python 3.12 Bookworm con uv preinstalado.

Puedes especificar una imagen diferente usando la bandera `--image`:

```bash
hf jobs uv run \
 --flavor a10g-large \
 --image vllm/vllm-openai:latest \
...
```

El comando anterior se ejecutará utilizando la imagen `vllm/vllm-openai:latest`. Este enfoque podría ser útil si estás utilizando vLLM para la generación de datos sintéticos.

> [!TIP]
> Muchos marcos de inferencia proporcionan imágenes de docker optimizadas. A medida que uv se adopta cada vez más en el ecosistema de Python, más de estas imágenes también tendrán uv preinstalado, lo que significa que funcionarán al usar hf jobs uv run.

### Tareas programadas

Programa y gestiona trabajos que se ejecutarán en la infraestructura de HF.

Use [create_scheduled_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.create_scheduled_job) o [create_scheduled_uv_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.create_scheduled_uv_job) con un horario de `@annually`, `@yearly`, `@monthly`, `@weekly`, `@daily`, `@hourly` o una expresión de horario CRON (p. ej., `"0 9 * * 1"` para las 9:00 de cada lunes):

```python
# Schedule a job that runs every hour
>>> from huggingface_hub import create_scheduled_job
>>> create_scheduled_job(
...     image="python:3.12",
...     command=["python",  "-c", "print('This runs every hour!')"],
...     schedule="@hourly"
... )

# Use the CRON syntax
>>> create_scheduled_job(
...     image="python:3.12",
...     command=["python",  "-c", "print('This runs every 5 minutes!')"],
...     schedule="*/5 * * * *"
... )

# Schedule with GPU
>>> create_scheduled_job(
...     image="pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel",
...     command=["python",  "-c", 'import torch; print(f"This code ran with the following GPU: {torch.cuda.get_device_name()}")'],
...     schedule="@hourly",
...     flavor="a10g-small",
... )

# Schedule a UV script
>>> from huggingface_hub import create_scheduled_uv_job
>>> create_scheduled_uv_job("my_script.py", schedule="@hourly")
```

Use los mismos parámetros que [run_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.run_job) y [run_uv_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.run_uv_job) para pasar variables de entorno, secretos, timeout, etc.

Gestione los trabajos programados con [list_scheduled_jobs()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.list_scheduled_jobs), [inspect_scheduled_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.inspect_scheduled_job), [suspend_scheduled_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.suspend_scheduled_job), [resume_scheduled_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.resume_scheduled_job), [update_scheduled_job_schedule()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.update_scheduled_job_schedule), [trigger_scheduled_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.trigger_scheduled_job) y [delete_scheduled_job()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.delete_scheduled_job):

```python
# List your active scheduled jobs
>>> from huggingface_hub import list_scheduled_jobs
>>> list_scheduled_jobs()

# Only list scheduled jobs with the given labels
>>> list_scheduled_jobs(labels={"env": "prod"})

# Inspect the status of a job
>>> from huggingface_hub import inspect_scheduled_job
>>> inspect_scheduled_job(scheduled_job_id=scheduled_job_id)

# Suspend (pause) a scheduled job
>>> from huggingface_hub import suspend_scheduled_job
>>> suspend_scheduled_job(scheduled_job_id=scheduled_job_id)

# Resume a scheduled job
>>> from huggingface_hub import resume_scheduled_job
>>> resume_scheduled_job(scheduled_job_id=scheduled_job_id)

# Change future run times without recreating the scheduled job
>>> from huggingface_hub import update_scheduled_job_schedule
>>> updated = update_scheduled_job_schedule(scheduled_job_id=scheduled_job_id, schedule="0 9 * * 1")
>>> updated.schedule
'0 9 * * 1'

# Trigger a scheduled job to run right now (does not change the schedule)
>>> from huggingface_hub import trigger_scheduled_job
>>> job = trigger_scheduled_job(scheduled_job_id=scheduled_job_id)
>>> job.url

# Delete a scheduled job
>>> from huggingface_hub import delete_scheduled_job
>>> delete_scheduled_job(scheduled_job_id=scheduled_job_id)
```

### Activar trabajos con webhooks

Los webhooks le permiten escuchar nuevos cambios en repositorios específicos o en todos los repositorios que pertenecen a un conjunto particular de usuarios u organizaciones (no solo sus repositorios, sino cualquier repositorio).

Use [create_webhook()](/docs/huggingface_hub/v2.4.0/es/package_reference/hf_api#huggingface_hub.HfApi.create_webhook) para crear un webhook que active un Job cuando se produzca un cambio en un repositorio de Hugging Face:

```python
from huggingface_hub import create_webhook

# Example: Creating a webhook that triggers a Job
webhook = create_webhook(
    job_id=job_id,
    watched=[{"type": "user", "name": "your-username"}, {"type": "org", "name": "your-org-name"}],
    domains=["repo", "discussion"],
    secret="your-secret"
)
```

El webhook activa el Job con la carga del webhook en la variable de entorno `WEBHOOK_PAYLOAD`. Puede encontrar más información sobre los webhooks en la [documentación de webhooks](./webhooks).

