Hub Python Library documentation

Exécuter et gérer des Jobs

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Exécuter et gérer des Jobs

Le Hugging Face Hub fournit de la puissance de calcul pour les flux de travail d'IA et de données via Jobs.

Pour un aperçu général des Jobs et de la tarification, consultez la documentation Hub Jobs.

Un job s’exécute sur l’infrastructure de Hugging Face et est défini par une commande à exécuter (par exemple, une commande python), une image Docker issue de Hugging Face Spaces ou de Docker Hub, et un type de matériel (CPU, GPU, TPU). Ce guide vous montre comment interagir avec les Jobs sur le Hub, notamment :

  • Lancer un job.
  • Vérifier l'état du travail.
  • Sélectionnez le matériel.
  • Configurez les variables d’environnement et les secrets.
  • Exécuter des scripts UV.

Si vous souhaitez exécuter et gérer un job sur le Hub, votre machine doit être connectée. Si ce n'est pas le cas, veuillez consulter cette section. Dans la suite de ce guide, nous supposerons que votre machine est connectée.

Hugging Face Jobs est disponible pour tout utilisateur ou toute organisation disposant d'un solde de crédits positif. Consultez tarification et facturation des Jobs pour plus de détails.

Interface en ligne de commande des Jobs

Utilisez le hf jobs CLI pour exécuter des Jobs depuis la ligne de commande, et passez --flavor pour spécifier votre matériel.

hf jobs run exécute des Jobs à l’aide d’une image Docker et d’une commande, avec une interface familière, semblable à celle de Docker. Pensez à docker run, mais pour exécuter du code sur n’importe quel matériel :

>>> 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())"

Utilisez hf jobs uv run pour exécuter des scripts UV locaux ou distants :

>>> 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"

Les scripts UV sont des scripts Python qui incluent leurs dépendances directement dans le fichier à l'aide d'une syntaxe de commentaire spéciale définie dans la documentation UV.

Le reste de ce guide vous présente l'API Python. Si vous souhaitez plutôt consulter toutes les commandes et options disponibles de hf jobs, reportez-vous au guide sur l'interface en ligne de commande hf jobs.

Besoin d'une machine interactive plutôt que d'un job « fire-and-forget » — par exemple pour exécuter du code généré par IA, avec exécution de commandes et transfert de fichiers ? Consultez Sandboxes, construites sur la base de Jobs.

Lancer un Job

Exécuter des Jobs de calcul définis par une commande et une image Docker sur l’infrastructure de Hugging Face (y compris les GPU et les TPU).

Vous ne pouvez gérer que les Jobs dont vous êtes propriétaire (sous l’espace de noms de votre nom d’utilisateur) ou ceux des organisations pour lesquelles vous disposez de droits d’écriture. Cette fonctionnalité est facturée à l’usage : vous ne payez que les secondes utilisées.

run_job() vous permet d’exécuter n’importe quelle commande sur l’infrastructure de Hugging Face :

# 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")

Important : Les jobs ont un délai d'expiration par défaut (30 minutes), après lequel ils s'arrêtent automatiquement. Pour les tâches de longue durée comme l'entraînement de modèles, assurez-vous de définir un délai d'expiration personnalisé à l'aide du paramètre timeout. Consultez Configurer le délai d'expiration du job pour plus de détails.

run_job() renvoie le JobInfo qui contient l’URL du Job sur Hugging Face, où vous pouvez consulter l’état du Job et les journaux. Enregistrez l’identifiant du Job depuis JobInfo pour gérer le job :

>>> 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

Les tâches s’exécutent en arrière-plan. La section suivante vous guide à travers inspect_job() pour connaître l’état d’une tâche, fetch_job_logs() pour afficher les journaux et fetch_job_metrics() pour surveiller l’utilisation des ressources.

Réessayer et relancer un Job

Utilisez attempts pour relancer un Job en échec. Ce nombre inclut la tentative initiale, de sorte que attempts=3 autorise jusqu'à deux nouvelles tentatives. Cela fonctionne également avec run_uv_job, create_scheduled_job et create_scheduled_uv_job.

>>> 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 démarre un Job distinct avec un nouvel identifiant. Il fonctionne pour les Jobs terminés ou en échec et réutilise la spécification enregistrée, y compris les secrets et les paramètres matériels. Vous pouvez également exécuter hf jobs rerun <job_id>.

Vérifier l'état du Job

# 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)

Attendez la fin des Jobs

Utilisez wait_for_job() pour bloquer jusqu’à ce qu’un Job atteigne une étape terminale (COMPLETED, CANCELED, ERROR ou DELETED). Le JobInfo final est toujours renvoyé — un Job en échec ne lève pas d’exception — il faut donc vérifier job.status.stage pour agir en fonction du résultat. Transmettez une liste d’identifiants de Job pour attendre un lot entier d’un coup.

>>> 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)

La même fonctionnalité est disponible dans l’interface en ligne de commande avec hf jobs wait, qui se termine avec le code 0 uniquement si tous les Jobs ont abouti avec succès — pratique pour enchaîner des commandes dans des scripts shell ou des pipelines CI :

# 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

Notez qu'un hf jobs run non détaché (ou hf jobs uv run) se termine également avec un code non nul si le Job échoue, de sorte que hf jobs run ... && next-step s'enchaîne correctement sans attente explicite.

Sélectionner le matériel

Il existe de nombreux cas où l’exécution de Jobs sur des GPU est utile :

  • Entraînement de modèles : Ajustez finement ou entraînez des modèles sur des GPU (T4, A10G, A100) sans gérer l'infrastructure
  • Génération de données synthétiques : générer des jeux de données à grande échelle à l'aide de LLM sur du matériel puissant
  • Prétraitement des données : Traitez des jeux de données massifs avec des configurations à forte puissance CPU pour des charges de travail parallèles
  • Inférence par lots : Exécuter une inférence hors ligne sur des milliers d'échantillons à l'aide de configurations GPU optimisées
  • Expériences et benchmarks : Exécutez des expériences ML sur un matériel cohérent pour des résultats reproductibles
  • Développement et débogage : Testez le code GPU sans configuration CUDA locale

Exécutez des tâches sur des GPU ou des TPU à l’aide de l’argument flavor. Par exemple, pour exécuter une tâche PyTorch sur un GPU A10G :

# 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",
... )

L'exécution de ce code affichera la sortie suivante !

This code ran with the following GPU: NVIDIA A10G

Utilisez ceci pour exécuter un script de fine-tuning comme trl/scripts/sft.py avec UV :

>>> 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",
... )

Pour un guide complet sur l’exécution de tâches d’entraînement de modèles avec TRL sur l’infrastructure Hugging Face, consultez la documentation TRL Jobs Training. Elle aborde les recettes de fine-tuning, le choix du matériel et les bonnes pratiques pour entraîner efficacement les modèles.

Voici la liste complète du matériel disponible pour exécuter des Jobs :

namenom affichécpuramstockageacceleratorcoût/mincoût/heure
cpu-basicCPU de base2 vCPU16 Go50 Go-$0.0002$0.01
cpu-upgradeMise à niveau du CPU8 vCPU32 Go50 Go-$0.0005$0.03
cpu-performancePerformance CPU32 vCPU256 Go1024 Go-$0.0317$1.90
cpu-xlCPU XL16 vCPU124 Go1000 Go-$0.0167$1.00
t4-smallNvidia T4 - petit4 vCPU15 Go50 Go1x T4 (16 Go)$0.0067$0.40
t4-mediumNvidia T4 - moyen8 vCPU30 Go100 Go1x T4 (16 Go)$0.0100$0.60
a10g-smallNvidia A10G - petit4 vCPU15 Go110 Go1x A10G (24 Go)$0.0167$1.00
a10g-largeNvidia A10G - grande12 vCPU46 Go200 Go1x A10G (24 Go)$0.0250$1.50
a10g-largex22x Nvidia A10G - grand24 vCPU92 Go1000 Go2x A10G (48 Go)$0.0500$3.00
a10g-largex44x Nvidia A10G - grand48 vCPU184 Go2000 Go4x A10G (96 Go)$0.0833$5.00
a100-largeNvidia A100 - grande12 vCPU142 Go1000 Go1x A100 (80 Go)$0.0417$2.50
a100x44x Nvidia A10048 vCPU568 Go4000 Go4x A100 (320 Go)$0.1667$10.00
a100x88x Nvidia A10096 vCPU1136 Go8000 Go8x A100 (640 Go)$0.3333$20.00
h200Nvidia H20023 vCPU256 Go3000 Go1x H200 (141 Go)$0.0833$5.00
h200x2Nvidia H20046 vCPU512 Go6000 Go2x H200 (282 Go)$0.1667$10.00
h200x4Nvidia H20092 vCPU1024 Go12000 Go4x H200 (564 Go)$0.3333$20.00
h200x8Nvidia H200184 vCPU2048 Go24000 Go8x H200 (1128 Go)$0.6667$40.00
rtx-pro-6000Nvidia RTX PRO 600023 vCPU256 Go475 Go1x RTX PRO 6000 (96 Go)$0.0458$2.75
rtx-pro-6000x2Nvidia RTX PRO 600046 vCPU512 Go950 Go2x RTX PRO 6000 (192 Go)$0.0917$5.50
rtx-pro-6000x4Nvidia RTX PRO 600092 vCPU1024 Go1900 Go4x RTX PRO 6000 (384 Go)$0.1833$11.00
rtx-pro-6000x8Nvidia RTX PRO 6000184 vCPU2048 Go3800 Go8x RTX PRO 6000 (768 Go)$0.3667$22.00
l4x11x Nvidia L48 vCPU30 Go400 Go1x L4 (24 Go)$0.0133$0.80
l4x44x Nvidia L448 vCPU186 Go3200 Go4x L4 (96 Go)$0.0633$3.80
l40sx11x Nvidia L40S8 vCPU62 Go380 Go1x L40S (48 Go)$0.0300$1.80
l40sx44x Nvidia L40S48 vCPU382 Go3200 Go4x L40S (192 Go)$0.1383$8.30
l40sx88x Nvidia L40S192 vCPU1534 Go6500 Go8x L40S (384 Go)$0.3917$23.50

Vous pouvez obtenir cette liste de manière programmatique en exécutant :

>>> hf jobs hardware

Ou en utilisant l'API Python :

>>> from huggingface_hub import list_jobs_hardware
>>> list_jobs_hardware()

C’est tout ! Vous exécutez désormais du code sur l’infrastructure de Hugging Face.

Monter un volume

Monter un volume sur le disque des Jobs à l’aide d’une liste de Volume.

Vous pouvez monter n'importe quel dépôt Hugging Face (modèle/jeu de données/espace) ou Storage Bucket. Par exemple :

  • monter un dépôt de modèle : Volume(type="model", source="openai/gpt-oss-120b", mount_path="/model")
  • monter un dépôt de jeu de données : Volume(type="dataset", source="HuggingFaceFW/fineweb", mount_path="/data")
  • monter un bucket de stockage : Volume(type="bucket", source="username/my-bucket", mount_path="/mnt")

Vous pouvez ensuite utiliser le volume monté comme un répertoire local :

>>> 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")],
... )

Vous pouvez également écrire dans un bucket monté, par exemple pour enregistrer des points de contrôle lors de l’entraînement d’un modèle :

>>> 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])

Par défaut, les buckets de stockage montés disposent de capacités de lecture et d'écriture. C'est particulièrement utile pour les buckets de stockage, qui offrent un stockage rapide et mutable pour des données qui changent fréquemment — les fichiers peuvent être écrasés ou supprimés sur place.

Utilisez read_only=True pour activer le mode lecture seule : Volume(type="bucket", read_only=True, ...).

Monter des données locales

Pour exécuter un Job sur des données de votre machine, utilisez sync_job_volume() : il synchronise un répertoire local avec votre Storage Bucket jobs-artifacts (créé automatiquement si nécessaire) et renvoie un Volume prêt à être monté :

>>> 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])

Chaque répertoire possède son propre dossier stable dans le bucket : relancer sync_job_volume() sur le même répertoire ne téléverse que les nouveaux fichiers ou les fichiers modifiés. Le volume est monté en lecture seule par défaut.

Pour récupérer les fichiers écrits par un Job, montez un volume en lecture-écriture (un répertoire de sortie vide convient également) et synchronisez-le une fois le Job terminé :

>>> 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")

Dans l'interface en ligne de commande, passez simplement un répertoire local comme source pour -v :

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

Exposer les ports du Job

Passez expose pour rendre un port de conteneur accessible via le proxy des Jobs. L’accès nécessite un jeton HF avec un accès en lecture à l’espace de noms du Job. Utilisez plutôt expose_public pour autoriser l’accès sans authentification :

>>> 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 et expose_public peuvent être combinés. update_job_expose remplace la configuration complète des ports sur un Job en cours d’exécution sans le redémarrer : les ports qui ne figurent dans aucune des deux listes sont fermés. Les deux options sont également disponibles lors de la création de Jobs UV et planifiés.

Se connecter à un Job via SSH

Passez ssh=True à run_job() (ou run_uv_job()) pour rendre le conteneur du Job accessible via SSH. Le point de terminaison SSH est disponible dans l’état du Job :

>>> 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'

Connectez-vous depuis un terminal avec hf jobs ssh <job_id> (ou directement avec ssh <job_id>@ssh.hf.jobs) :

>>> hf jobs ssh 68498e23210b3a4f4e6e2a23

Seuls les utilisateurs disposant d'un accès en écriture à l'espace de noms du Job (le créateur du Job ou les membres de l'organisation propriétaire) sont autorisés à y accéder, authentifiés par une clé publique SSH enregistrée sur https://huggingface.co/settings/keys.

Groupes de réseaux

Passez network_group="<name>" à run_job() (ou run_uv_job()) pour permettre aux Jobs du même espace de noms et du même groupe de ressources de se joindre sur tous les ports. Au sein de chaque membre, HF_NETWORK_GROUP_HOSTNAME se résout vers tous les Jobs du groupe, et ${HF_NETWORK_GROUP_PREFIX}<alias> vers les membres qui ont réclamé un alias avec network_aliases=[...] :

>>> 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'])

Les membres sont résolubles avant d’être prêts, il est donc recommandé d’établir la connexion avec des tentatives répétées. Les noms de groupe et les alias sont des chaînes alphanumériques minuscules et des tirets, avec un maximum de 46 et 34 caractères respectivement.

Configurer le délai d’expiration du travail

Les jobs ont un délai d'expiration par défaut (30 minutes), après lequel ils s'arrêtent automatiquement. C'est un point important à connaître lors de l'exécution de tâches de longue durée, comme l'entraînement de modèles.

Définir un délai d'attente personnalisé

Vous pouvez spécifier une valeur de délai d’attente personnalisée à l’aide du paramètre timeout lors de l’exécution d’un job. Le délai d’attente peut être spécifié de deux manières :

  1. En tant que nombre (interprété en secondes) :
>>> 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
... )
  1. Sous forme de chaîne avec des unités de temps :
>>> # 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

Unités de temps prises en charge :

  • s - secondes
  • m - minutes
  • h - heures
  • d - jours

Utilisation de timeout avec les jobs UV

Pour les tâches UV, vous pouvez également spécifier le délai d’expiration :

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

Si vous ne spécifiez pas de délai d’expiration, un délai par défaut sera appliqué à votre tâche. Pour les tâches de longue durée, comme l’entraînement de modèles qui peut prendre des heures, assurez-vous de définir un délai approprié afin d’éviter les terminaisons inattendues de la tâche.

Surveillance de la durée des tâches

Lors de l’exécution de tâches longues, il est bon de :

  • Estimez la durée prévue de votre tâche et définissez un délai d’expiration avec une marge de sécurité
  • Suivre l’avancement de votre tâche via les journaux
  • Vérifiez l'état de la tâche pour vous assurer qu'elle n'a pas expiré
>>> 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)

Pour plus de détails sur le paramètre timeout, consultez la référence de l'API run_job.

Passer les variables d’environnement et les secrets

Vous pouvez passer des variables d’environnement à votre tâche à l’aide de env et secrets :

# 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"},
... )
# 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 d'environnement intégrées

À l'intérieur du conteneur de tâche, les variables d'environnement suivantes sont automatiquement disponibles :

VariableDescription
JOB_IDL'identifiant unique du travail actuel. Utilisez-le pour référencer le travail de manière programmatique, par exemple pour stocker les sorties dans un jeu de données avec un nom unique.
ACCELERATORLe type d'accélérateur disponible (par exemple, t4-medium, a10g-small, a100x4). Vide si aucun accélérateur.
CPU_CORESLe nombre de cœurs CPU disponibles pour le travail (par exemple, 2, 4, 8).
MEMORYLa quantité de mémoire disponible pour le travail (par exemple, 16Gi, 32Gi).
# 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')}")
... """],
... )

Ces variables sont utiles lorsque vous devez créer des identifiants uniques pour les sorties, adapter votre code en fonction du matériel disponible ou consigner des informations sur les ressources.

Étiquettes

Les étiquettes sont des paires clé=valeur qui associent des métadonnées à un Job :

Utilisez name pour faciliter la recherche et l’identification des Jobs dans l’interface. Les noms sont facultatifs et n’ont pas besoin d’être uniques :

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

Depuis l’interface en ligne de commande, passez --name lors de la création d’un Job, ou nommez un Job existant via la commande labels :

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

hf jobs ls affiche une colonne NAME et permet de filtrer par nom (raccourci pour --label name=NAME) :

>>> hf jobs ls -a --name daily-report
# 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 vous ne passez pas de nom, celui-ci est dérivé automatiquement à partir de l’image Docker ou du script, auquel s’ajoute un court hachage (par ex. python:3.12 foo --truc → python-3-12-1a2b3c4d). Depuis l’interface en ligne de commande, ce hachage couvre la commande et les paramètres d’exécution résolus (variante, délai d’attente, valeurs d’environnement, …), de sorte qu’une même configuration produit toujours le même nom, et qu’une modification d’un paramètre — y compris d’un paramètre issu de l’en-tête [tool.hf-jobs] d’un script — le modifie. Depuis l’API Python, le hachage ne couvre que la commande.

Mettre à jour les étiquettes

Utilisez update_job_labels() pour remplacer les étiquettes d’un travail existant. Cela remplace toutes les étiquettes fournies par l’utilisateur :

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

Cela fonctionne également pour les tâches planifiées avec update_scheduled_job_labels() :

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

Depuis l'interface en ligne de commande :

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

Pour supprimer tous les libellés, passez --clear :

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

Scripts UV (expérimental)

Vous cherchez des scripts UV prêts à l'emploi ? Consultez l'organisation uv-scripts sur le Hugging Face Hub, qui propose une collection communautaire de scripts UV pour des tâches telles que l'entraînement de modèles, la génération de données synthétiques, le traitement de données, et bien plus encore.

Exécuter des scripts UV (scripts Python avec des dépendances intégrées) sur l’infrastructure HF :

# 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"])

Les scripts UV sont des scripts Python qui incluent leurs dépendances directement dans le fichier à l’aide d’une syntaxe de commentaire spéciale. Ils sont donc parfaits pour les tâches autonomes qui ne nécessitent pas de configuration de projet complexe. En savoir plus sur les scripts UV dans la documentation UV.

Inclure la configuration de lancement avec le script

Un script qui ne s’exécute correctement que sur un runtime spécifique peut l’indiquer dans un tableau optionnel [tool.hf-jobs] de son en-tête PEP 723 :

# /// 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 lance ensuite le script avec l’image, le matériel et l’interpréteur appropriés, et --flavor, -e, … continuent de remplacer ce que le script déclare. Consultez le guide CLI pour la liste complète des clés et les règles de fusion.

Le tableau est lu uniquement par le CLI hf : run_uv_job() et create_scheduled_uv_job() l’ignorent et utilisent exactement les arguments qui leur sont fournis. Autrement dit, run_uv_job("ocr.py") et hf jobs uv run ocr.py ne lancent pas le même Job — l’API Python nécessite que image=, flavor=, … soient passés explicitement.

Images Docker pour les scripts UV

Bien que les scripts UV puissent spécifier leurs dépendances en ligne, les charges de travail ML ont souvent des dépendances complexes. L’utilisation d’images Docker préconstruites avec ces bibliothèques déjà installées peut accélérer considérablement le démarrage des tâches et éviter les problèmes de dépendances.

Par défaut, lorsque vous exécutez hf jobs uv run, l’image astral-sh/uv:python3.12-bookworm est utilisée. Cette image est basée sur la distribution Python 3.12 Bookworm avec uv préinstallé.

Vous pouvez spécifier une image différente à l'aide du drapeau --image :

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

La commande ci-dessus s’exécute à l’aide de l’image vllm/vllm-openai:latest. Cette approche peut s’avérer utile si vous utilisez vLLM pour la génération de données synthétiques.

De nombreux frameworks d’inférence fournissent des images docker optimisées. Comme uv est de plus en plus adopté dans l’écosystème Python, un nombre croissant de ces images incluront également uv préinstallé, ce qui signifie qu’elles fonctionneront lors de l’utilisation de hf jobs uv run.

Tâches planifiées

Planifiez et gérez les tâches qui s'exécuteront sur l'infrastructure HF.

Utilisez create_scheduled_job() ou create_scheduled_uv_job() avec un planning de @annually, @yearly, @monthly, @weekly, @daily, @hourly, ou une expression de planning CRON (par exemple, "0 9 * * 1" pour 9 h chaque lundi) :

# 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")

Utilisez les mêmes paramètres que run_job() et run_uv_job() pour transmettre des variables d'environnement, des secrets, un délai d'attente, etc.

Gérez les tâches planifiées à l'aide de list_scheduled_jobs(), inspect_scheduled_job(), suspend_scheduled_job(), resume_scheduled_job(), update_scheduled_job_schedule(), trigger_scheduled_job() et delete_scheduled_job() :

# 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)

Déclencher des tâches avec des webhooks

Les webhooks vous permettent de surveiller les nouvelles modifications sur des dépôts spécifiques ou sur l’ensemble des dépôts appartenant à un ensemble donné d’utilisateurs/organisations (pas seulement vos dépôts, mais n’importe quel dépôt).

Utilisez create_webhook() pour créer un webhook qui déclenche un Job lorsqu'une modification survient dans un dépôt Hugging Face :

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"
)

Le webhook déclenche le Job avec la charge utile du webhook dans la variable d’environnement WEBHOOK_PAYLOAD. Vous trouverez plus d’informations sur les webhooks dans la documentation des webhooks.

Update on GitHub