# 运行和管理任务

Hugging Face Hub 通过 Jobs 为 AI 和数据工作流提供计算资源。

**有关 Jobs 和定价的总体概述，请参阅 [Hub Jobs 文档](https://huggingface.co/docs/hub/jobs)。**

任务在 Hugging Face 基础设施上运行，其定义包括要执行的命令（例如 python 命令）、来自 Hugging Face Spaces 或 Docker Hub 的 Docker 镜像，以及硬件类型（CPU、GPU、TPU）。本指南将展示如何与 Hub 上的任务进行交互，特别是：

- 运行一个任务。
- 检查任务状态。
- 选择硬件。
- 配置环境变量和密钥。
- 运行 UV 脚本。

如果您想在 Hub 上运行和管理任务，您的机器必须处于已登录状态。如果尚未登录，请参阅[此部分](../quick-start#authentication)。在本指南的其余部分中，我们将假设您的机器已登录。

> [!TIP]
> **Hugging Face Jobs** 面向任何拥有正数[信用余额](https://huggingface.co/settings/billing)的用户或组织。有关详细信息，请参阅[Jobs 定价与计费](https://huggingface.co/docs/hub/jobs-pricing)。

## Jobs 命令行界面

使用 [`hf jobs` CLI](./cli#hf-jobs) 从命令行运行 Jobs，并传入 `--flavor` 以指定您的硬件。

`hf jobs run` 使用 Docker 镜像和命令来运行 Jobs，其界面与 Docker 类似。可以将其理解为 `docker run`，但用于在任意硬件上运行代码：

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

使用 `hf jobs uv run` 运行本地或远程的 UV 脚本：

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

UV 脚本是 Python 脚本，它们使用 [UV 文档](https://docs.astral.sh/uv/guides/scripts/)中定义的特殊注释语法，直接在文件内包含其依赖项。

接下来，本指南的其余部分将向您介绍 Python API。如果您想查看所有可用的 `hf jobs` 命令和选项，请参阅 [`hf jobs` 命令行界面指南](./cli#hf-jobs)。

> [!TIP]
> 如果需要一台*交互式*机器，而不是即发即忘的任务——例如，为了运行 AI 生成的代码，并支持命令执行和文件传输？请查看基于 Jobs 构建的[Sandboxes](./sandbox)。

## 运行任务

在 Hugging Face 基础设施（包括 GPU 和 TPU）上运行使用命令和 Docker Image 定义的 compute Jobs。

您只能管理您自己拥有的任务（位于您的用户名命名空间下）或您拥有写入权限的组织中的任务。此功能按使用量计费：您只需为实际使用的秒数付费。

[run_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.run_job) 允许您在 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]
> **重要**：任务具有默认超时时间（30 分钟），超时后将自动停止。对于模型训练等长时间运行的任务，请确保使用 `timeout` 参数设置自定义超时时间。详情请参阅 [配置任务超时](#configure-job-timeout)。

[run_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.run_job) 返回 [JobInfo](/docs/huggingface_hub/v2.4.0/zh/package_reference/jobs#huggingface_hub.JobInfo)，其中包含 Hugging Face 上该 Job 的 URL，您可以在此查看 Job 状态和日志。请保存 [JobInfo](/docs/huggingface_hub/v2.4.0/zh/package_reference/jobs#huggingface_hub.JobInfo) 中的 Job ID 以管理该任务：

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

任务在后台运行。下一节将指导您使用 [inspect_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.inspect_job) 查看任务状态，使用 [fetch_job_logs()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.fetch_job_logs) 查看日志，以及使用 [fetch_job_metrics()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.fetch_job_metrics) 监控资源使用情况。

## 重试并重新运行 Job

使用 `attempts` 来重试失败的 Job。该数值包含初始尝试，因此 `attempts=3` 允许最多两次重试。它同样适用于 `run_uv_job`、`create_scheduled_job` 和 `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` 会启动一个具有新 ID 的独立 Job。它适用于已完成或失败的 Job，并会复用已保存的 spec，包括 secrets 和硬件设置。你也可以运行 `hf jobs rerun <job_id>`。

## 检查任务状态

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

## 等待任务完成

使用 [wait_for_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.wait_for_job) 阻塞，直到 Job 到达终止阶段（`COMPLETED`、`CANCELED`、`ERROR` 或 `DELETED`）。始终会返回最终的 [JobInfo](/docs/huggingface_hub/v2.4.0/zh/package_reference/jobs#huggingface_hub.JobInfo) —— 失败的 Job 不会引发异常 —— 因此请检查 `job.status.stage` 以根据结果采取行动。传入 Job ID 列表可一次性等待整个批次。

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

CLI 中同样提供了 `hf jobs wait`，它仅在所有 Job 均成功完成时以退出码 0 结束——非常适合在 shell 脚本或 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
```

请注意，未分离的 `hf jobs run`（或 `hf jobs uv run`）在 Job 失败时也会以非零代码退出，因此 `hf jobs run ... && next-step` 可以正确链接，无需显式等待。

## 选择硬件

在以下多种场景中，在 GPU 上运行 Jobs 非常有用：

- **模型训练**：在 GPU（T4、A10G、A100）上微调或训练模型，无需管理基础设施
- **合成数据生成**：在高性能硬件上使用 LLM 生成大规模数据集
- **数据处理**：使用高 CPU 配置处理大规模数据集，以应对并行工作负载
- **批量推理**：使用优化的 GPU 配置对数千个样本运行离线推理
- **实验与基准测试**：在一致的硬件上运行机器学习实验，以获得可复现的结果
- **开发与调试**：无需本地 CUDA 环境即可测试 GPU 代码

使用 `flavor` 参数在 GPU 或 TPU 上运行任务。例如，要在 A10G GPU 上运行 PyTorch 任务：

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

运行此命令将显示以下输出！

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

使用此命令通过 UV 运行微调脚本，例如 [trl/scripts/sft.py](https://github.com/huggingface/trl/blob/main/trl/scripts/sft.py)：

```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]
> 如需了解如何在 Hugging Face 基础设施上使用 TRL 运行模型训练任务的全面指南，请参阅 [TRL Jobs 训练文档](https://huggingface.co/docs/trl/main/en/jobs_training)。该文档涵盖了微调方案、硬件选择以及高效训练模型的最佳实践。

以下是可用于运行 Jobs 的完整硬件列表：

| name | 友好名称 | cpu | ram | 存储 | accelerator | 成本/分钟 | 每小时成本 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `cpu-basic` | CPU 基础 | 2 个 vCPU | 16 GB | 50 GB | - | $0.0002 | $0.01 |
| `cpu-upgrade` | CPU 升级 | 8 个 vCPU | 32 GB | 50 GB | - | $0.0005 | $0.03 |
| `cpu-performance` | 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 - 小型 | 4 个 vCPU | 15 GB | 50 GB | 1x T4 (16 GB) | $0.0067 | $0.40 |
| `t4-medium` | Nvidia T4 - 中等 | 8 个 vCPU | 30 GB | 100 GB | 1x T4 (16 GB) | $0.0100 | $0.60 |
| `a10g-small` | Nvidia A10G - 小型 | 4 个 vCPU | 15 GB | 110 GB | 1x A10G (24 GB) | $0.0167 | $1.00 |
| `a10g-large` | Nvidia A10G - 大型 | 12 个 vCPU | 46 GB | 200 GB | 1x A10G (24 GB) | $0.0250 | $1.50 |
| `a10g-largex2` | 2x Nvidia A10G - 大型 | 24 个 vCPU | 92 GB | 1000 GB | 2x A10G (48 GB) | $0.0500 | $3.00 |
| `a10g-largex4` | 4x Nvidia A10G - 大型 | 48 个 vCPU | 184 GB | 2000 GB | 4x A10G (96 GB) | $0.0833 | $5.00 |
| `a100-large` | Nvidia A100 - 大型 | 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 |

您可以通过运行以下命令以编程方式获取此列表：

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

或者使用 Python API：

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

就是这样！你现在已经在 Hugging Face 的基础设施上运行代码了。

## 挂载卷

使用 [Volume](/docs/huggingface_hub/v2.4.0/zh/package_reference/jobs#huggingface_hub.Volume) 列表在 Jobs 的磁盘上挂载一个卷。

您可以挂载任何 Hugging Face 仓库（模型/数据集/空间）或 [存储桶](/docs/hub/storage-buckets)。例如：

* 挂载模型仓库：`Volume(type="model", source="openai/gpt-oss-120b", mount_path="/model")`
* 挂载数据集仓库：`Volume(type="dataset", source="HuggingFaceFW/fineweb", mount_path="/data")`
* 挂载存储桶：`Volume(type="bucket", source="username/my-bucket", mount_path="/mnt")`

然后，您可以将挂载的卷用作本地目录：

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

您也可以将数据写入已挂载的存储桶，例如在训练模型时保存检查点：

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

默认情况下，已挂载的存储桶具有读写权限。这对于存储桶尤其有用，因为它们为频繁变更的数据提供了快速、可变的存储——文件可以就地覆盖或删除。

使用 `read_only=True` 启用只读模式：`Volume(type="bucket", read_only=True, ...)`。

### 挂载本地数据

要在本地机器上的数据上运行 Job，请使用 [sync_job_volume()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.sync_job_volume)：它会将本地目录同步到您的 `jobs-artifacts` [Storage Bucket](https://huggingface.co/docs/hub/storage-buckets)（如有需要会自动创建），并返回一个可直接挂载的 [Volume](/docs/huggingface_hub/v2.4.0/zh/package_reference/jobs#huggingface_hub.Volume)：

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

每个目录在存储桶中都有自己独立的稳定文件夹：对同一目录重新运行 [sync_job_volume()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.sync_job_volume) 只会上传新增或已修改的文件。卷默认以只读方式挂载。

要获取由 Job 写入的文件，请挂载一个可读写卷（一个空的输出目录也可以），并在 Job 结束后将其同步回来：

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

在 CLI 中，只需将本地目录作为 `-v` 的源端传入即可：

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

## 公开任务端口

传入 `expose` 以通过 Jobs 代理使容器端口可访问。访问需要具有该 Job 命名空间读取权限的 HF token。若要允许无需身份验证即可访问，请改用 `expose_public`：

```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` 和 `expose_public` 可以组合使用。`update_job_expose` 可以在不重启的情况下替换正在运行的 Job 的完整端口配置：不在任一列表中的端口将被关闭。在创建 UV 和定时 Job 时，这两个选项也可用。

## SSH 到作业

将 `ssh=True` 传递给 [run_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.run_job)（或 [run_uv_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.run_uv_job)），即可通过 SSH 访问该 Job 的容器。SSH 端点可在 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'
```

在终端中使用 `hf jobs ssh <job_id>`（或直接使用 `ssh <job_id>@ssh.hf.jobs`）进行连接：

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

只有对 Job 命名空间具有写入权限的用户（即 Job 创建者或所有者组织的成员）才被允许进入，并通过在 https://huggingface.co/settings/keys 注册的 SSH 公钥进行身份验证。

## 网络组

将 `network_group="<name>"` 传递给 [run_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.run_job)（或 [run_uv_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.run_uv_job)），以便同一命名空间和资源组中的 Jobs 能够在所有端口上相互访问。在每个成员内部，`HF_NETWORK_GROUP_HOSTNAME` 会解析为组内的所有 Job，而 `${HF_NETWORK_GROUP_PREFIX}<alias>` 则解析为通过 `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'])
```

成员在就绪之前即可解析，因此连接时需使用重试机制。组名称和别名仅包含小写字母、数字和连字符，最大长度分别为 46 个字符和 34 个字符。

## 配置任务超时

任务具有默认超时时间（30 分钟），超时后会自动停止。在运行模型训练等长时间任务时，了解这一点非常重要。

### 设置自定义超时

在运行作业时，可以使用 `timeout` 参数指定自定义的超时值。超时值可以通过以下两种方式指定：

1. **作为数字**（解释为秒）：
```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. **作为带时间单位的字符串**：
```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
```

支持的时间单位：
- `s` - 秒
- `m` - 分钟
- `h` - 小时
- `d` - 天

### 在 UV 作业中使用 timeout

对于 UV 任务，你还可以指定超时时间：

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

> [!WARNING]
> 如果未指定超时时间，系统将为您提交的任务应用默认超时时间。对于可能需要数小时的长时间运行任务（例如模型训练），请务必设置合适的超时时间，以避免任务意外终止。

### 监控任务时长

在运行长时间任务时，良好的做法是：
- 估算任务的预期运行时长，并设置一个带有一定缓冲的超时时间
- 通过日志监控您的任务进度
- 检查任务状态，确保其未超时

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

有关 timeout 参数的更多详细信息，请参阅 [`run_job` API 参考](https://huggingface.co/docs/huggingface_hub/package_reference/hf_api#huggingface_hub.HfApi.run_job.timeout)。

## 传递环境变量和密钥

您可以使用 `env` 和 `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"},
... )
```

### 内置环境变量

在作业容器内部，以下环境变量会自动可用：

| 变量 | 描述 |
|----------|-------------|
| `JOB_ID` | 当前作业的唯一标识符。使用此标识符以编程方式引用该作业，例如将输出存储到具有唯一名称的数据集中。 |
| `ACCELERATOR` | 可用的加速器类型（例如，`t4-medium`、`a10g-small`、`a100x4`）。如果没有加速器，则为空。 |
| `CPU_CORES` | 作业可用的 CPU 核心数（例如，`2`、`4`、`8`）。 |
| `MEMORY` | 作业可用的内存量（例如，`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')}")
... """],
... )
```

这些变量在您需要为输出创建唯一标识符、根据可用硬件调整代码或记录资源信息时非常有用。

## 标签

标签是键值对，用于为 Job 附加元数据：

使用 `name` 可以更轻松地在 UI 中查找和识别 Job。名称是可选的，且无需唯一：

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

在 CLI 中，创建 Job 时传入 `--name`，或通过 labels 命令为现有 Job 命名：

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

`hf jobs ls` 会显示 `NAME` 列，并支持按名称过滤（即 `--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"},
... )
```

如果未传入名称，系统会自动从 Docker 镜像或脚本派生一个名称，并附加一个短哈希值（例如 `python:3.12 foo --truc` → `python-3-12-1a2b3c4d`）。在 CLI 中，该哈希值涵盖命令*以及*解析后的运行时设置（flavor、超时、环境变量值等），因此相同的配置始终生成相同的名称，而更改任何设置——包括来自脚本 `[tool.hf-jobs]` 头的设置——都会改变该名称。在 Python API 中，哈希值仅涵盖命令。

### 更新标签

使用 [update_job_labels()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.update_job_labels) 来替换现有作业的标签。这将替换所有现有的用户提供的标签：

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

对于使用 [update_scheduled_job_labels()](/docs/huggingface_hub/v2.4.0/zh/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"})
```

从命令行：

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

要删除所有标签，请传入 `--clear`：

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

## UV 脚本（实验性）

> [!TIP]
> 正在寻找现成的 UV 脚本？请查看 Hugging Face Hub 上的 [uv-scripts 组织](https://huggingface.co/uv-scripts)，它提供了一个社区脚本合集，涵盖模型训练、合成数据生成、数据处理等多种任务。

在 HF 基础设施上运行 UV 脚本（带有内联依赖项的 Python 脚本）：

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

UV 脚本是 Python 脚本，它使用特殊的注释语法将依赖项直接包含在文件中。这使得它们非常适合无需复杂项目配置的自包含任务。有关 UV 脚本的更多信息，请参阅 [UV 文档](https://docs.astral.sh/uv/guides/scripts/)。

#### 将启动配置与脚本一起发布

仅在特定运行时上才能正确运行的脚本，可以在其 PEP 723 头部的可选 `[tool.hf-jobs]` 表中携带该运行时：

```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` 随后会以正确的镜像、硬件和解释器启动，并且 `--flavor`、`-e` 等参数仍然会覆盖脚本中声明的内容。完整的键列表和合并规则请参阅 [CLI 指南](./cli#ship-the-launch-config-with-the-script)。

> [!WARNING]
> The table is read by the `hf` CLI only: [run_uv_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.run_uv_job) and [create_scheduled_uv_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.create_scheduled_uv_job) ignore it and use exactly the arguments they are given. In other words `run_uv_job("ocr.py")` and `hf jobs uv run ocr.py` do **not** run the same Job — the Python API needs `image=`, `flavor=`, ... to be passed explicitly.

#### 用于 UV 脚本的 Docker 镜像

虽然 UV 脚本可以内联指定其依赖项，但机器学习工作负载通常具有复杂的依赖关系。使用已预装这些库的预构建 Docker 镜像可以显著加快任务启动速度，并避免依赖项问题。

默认情况下，运行 `hf jobs uv run` 时会使用 `astral-sh/uv:python3.12-bookworm` 镜像。该镜像基于 Python 3.12 Bookworm 发行版，并预装了 uv。

您可以使用 `--image` 标志指定不同的镜像：

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

上述命令将使用 `vllm/vllm-openai:latest` 镜像运行。如果您使用 vLLM 进行合成数据生成，这种方法可能很有用。

> [!TIP]
> 许多推理框架都提供了经过优化的 docker 镜像。随着 uv 在 Python 生态系统中被越来越广泛地采用，这些镜像也将越来越多地预装 uv，这意味着在使用 hf jobs uv run 时它们可以正常工作。

### 计划任务

计划和将在 HF 基础设施上运行的任务。

使用 [create_scheduled_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.create_scheduled_job) 或 [create_scheduled_uv_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.create_scheduled_uv_job)，并设置计划为 `@annually`、`@yearly`、`@monthly`、`@weekly`、`@daily`、`@hourly`，或 CRON 计划表达式（例如，`"0 9 * * 1"` 表示每周一上午 9 点）：

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

使用与 [run_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.run_job) 和 [run_uv_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.run_uv_job) 相同的参数来传递环境变量、密钥、超时等。

使用 [list_scheduled_jobs()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.list_scheduled_jobs)、[inspect_scheduled_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.inspect_scheduled_job)、[suspend_scheduled_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.suspend_scheduled_job)、[resume_scheduled_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.resume_scheduled_job)、[update_scheduled_job_schedule()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.update_scheduled_job_schedule)、[trigger_scheduled_job()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.trigger_scheduled_job) 和 [delete_scheduled_job()](/docs/huggingface_hub/v2.4.0/zh/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)
```

### 通过 Webhook 触发任务

Webhooks 允许你监听特定仓库上的新变更，或监听属于特定用户/组织集合的所有仓库（不仅限于你自己的仓库，而是任意仓库）。

使用 [create_webhook()](/docs/huggingface_hub/v2.4.0/zh/package_reference/hf_api#huggingface_hub.HfApi.create_webhook) 创建一个 webhook，当 Hugging Face 仓库中发生更改时触发 Job：

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

Webhook 会触发 Job，并将 webhook 负载存储在环境变量 `WEBHOOK_PAYLOAD` 中。有关 webhook 的更多信息，请参阅 [Webhooks 文档](./webhooks)。

