Hub Python Library documentation
Exécuter et gérer des Jobs
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
687f911eaea852de79c4a50aLes 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 waitNotez 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 :
| name | nom affiché | cpu | ram | stockage | accelerator | coût/min | coût/heure |
|---|---|---|---|---|---|---|---|
cpu-basic | CPU de base | 2 vCPU | 16 Go | 50 Go | - | $0.0002 | $0.01 |
cpu-upgrade | Mise à niveau du CPU | 8 vCPU | 32 Go | 50 Go | - | $0.0005 | $0.03 |
cpu-performance | Performance CPU | 32 vCPU | 256 Go | 1024 Go | - | $0.0317 | $1.90 |
cpu-xl | CPU XL | 16 vCPU | 124 Go | 1000 Go | - | $0.0167 | $1.00 |
t4-small | Nvidia T4 - petit | 4 vCPU | 15 Go | 50 Go | 1x T4 (16 Go) | $0.0067 | $0.40 |
t4-medium | Nvidia T4 - moyen | 8 vCPU | 30 Go | 100 Go | 1x T4 (16 Go) | $0.0100 | $0.60 |
a10g-small | Nvidia A10G - petit | 4 vCPU | 15 Go | 110 Go | 1x A10G (24 Go) | $0.0167 | $1.00 |
a10g-large | Nvidia A10G - grande | 12 vCPU | 46 Go | 200 Go | 1x A10G (24 Go) | $0.0250 | $1.50 |
a10g-largex2 | 2x Nvidia A10G - grand | 24 vCPU | 92 Go | 1000 Go | 2x A10G (48 Go) | $0.0500 | $3.00 |
a10g-largex4 | 4x Nvidia A10G - grand | 48 vCPU | 184 Go | 2000 Go | 4x A10G (96 Go) | $0.0833 | $5.00 |
a100-large | Nvidia A100 - grande | 12 vCPU | 142 Go | 1000 Go | 1x A100 (80 Go) | $0.0417 | $2.50 |
a100x4 | 4x Nvidia A100 | 48 vCPU | 568 Go | 4000 Go | 4x A100 (320 Go) | $0.1667 | $10.00 |
a100x8 | 8x Nvidia A100 | 96 vCPU | 1136 Go | 8000 Go | 8x A100 (640 Go) | $0.3333 | $20.00 |
h200 | Nvidia H200 | 23 vCPU | 256 Go | 3000 Go | 1x H200 (141 Go) | $0.0833 | $5.00 |
h200x2 | Nvidia H200 | 46 vCPU | 512 Go | 6000 Go | 2x H200 (282 Go) | $0.1667 | $10.00 |
h200x4 | Nvidia H200 | 92 vCPU | 1024 Go | 12000 Go | 4x H200 (564 Go) | $0.3333 | $20.00 |
h200x8 | Nvidia H200 | 184 vCPU | 2048 Go | 24000 Go | 8x H200 (1128 Go) | $0.6667 | $40.00 |
rtx-pro-6000 | Nvidia RTX PRO 6000 | 23 vCPU | 256 Go | 475 Go | 1x RTX PRO 6000 (96 Go) | $0.0458 | $2.75 |
rtx-pro-6000x2 | Nvidia RTX PRO 6000 | 46 vCPU | 512 Go | 950 Go | 2x RTX PRO 6000 (192 Go) | $0.0917 | $5.50 |
rtx-pro-6000x4 | Nvidia RTX PRO 6000 | 92 vCPU | 1024 Go | 1900 Go | 4x RTX PRO 6000 (384 Go) | $0.1833 | $11.00 |
rtx-pro-6000x8 | Nvidia RTX PRO 6000 | 184 vCPU | 2048 Go | 3800 Go | 8x RTX PRO 6000 (768 Go) | $0.3667 | $22.00 |
l4x1 | 1x Nvidia L4 | 8 vCPU | 30 Go | 400 Go | 1x L4 (24 Go) | $0.0133 | $0.80 |
l4x4 | 4x Nvidia L4 | 48 vCPU | 186 Go | 3200 Go | 4x L4 (96 Go) | $0.0633 | $3.80 |
l40sx1 | 1x Nvidia L40S | 8 vCPU | 62 Go | 380 Go | 1x L40S (48 Go) | $0.0300 | $1.80 |
l40sx4 | 4x Nvidia L40S | 48 vCPU | 382 Go | 3200 Go | 4x L40S (192 Go) | $0.1383 | $8.30 |
l40sx8 | 8x Nvidia L40S | 192 vCPU | 1534 Go | 6500 Go | 8x L40S (384 Go) | $0.3917 | $23.50 |
Vous pouvez obtenir cette liste de manière programmatique en exécutant :
>>> hf jobs hardwareOu 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.pyExposer 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 68498e23210b3a4f4e6e2a23Seuls 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 :
- 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
... )- 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 secondsUnités de temps prises en charge :
s- secondesm- minutesh- heuresd- 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 :
| Variable | Description |
|---|---|
JOB_ID | L'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. |
ACCELERATOR | Le type d'accélérateur disponible (par exemple, t4-medium, a10g-small, a100x4). Vide si aucun accélérateur. |
CPU_CORES | Le nombre de cœurs CPU disponibles pour le travail (par exemple, 2, 4, 8). |
MEMORY | La 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-reporthf 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=stagingPour supprimer tous les libellés, passez --clear :
>>> hf jobs labels <job_id> --clearScripts 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")ethf jobs uv run ocr.pyne lancent pas le même Job — l’API Python nécessite queimage=,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.