Hub Python Library documentation

管理您的 Space

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

管理您的 Space

在本指南中,我们将了解如何使用 huggingface_hub 管理您的 Space 运行时(secrets、hardware 和卷)。

搜索 Spaces

您可以使用 search_spaces() 在 Hub 上通过语义搜索查找 Spaces。对于多词查询,它使用基于嵌入的搜索;对于单词查询,则使用全文搜索。

>>> from huggingface_hub import search_spaces
>>> results = list(search_spaces("generate image"))
>>> results[0]
SpaceSearchResult(id='mrfakename/Z-Image-Turbo', title='Z Image Turbo', sdk='gradio', likes=2867, ...)

您可以按 SDK 或标签筛选结果:

>>> results = search_spaces("chatbot", sdk="gradio", filter="mcp-server")

或通过 CLI:

>>> hf spaces search "generate image"
>>> hf spaces search "chatbot" --sdk gradio --limit 5

一个简单的示例:配置密钥和硬件。

下面是一个端到端的示例,用于在 Hub 上创建并配置一个 Space。

在 Hub 上创建一个 Space

>>> from huggingface_hub import HfApi
>>> repo_id = "Wauplin/my-cool-training-space"
>>> api = HfApi()

# For example with a Gradio SDK
>>> api.create_repo(repo_id=repo_id, repo_type="space", space_sdk="gradio")

静态 Spaces 对所有人免费。Gradio 和 Docker Spaces 在计算资源上运行:在免费的 cpu-basic 硬件上,它们需要订阅(用户为 PRO,组织为 Team 或 Enterprise),而付费硬件仅需账单(一种支付方式和预付费额度)。如果没有订阅,在 cpu-basic 上创建、复制或移动 Gradio 或 Docker Space 会因支付错误(HTTP 402)而失败。有关更多详细信息,请参阅 定价。

从模板创建 Space

与其从空的 Space 开始,您可以使用 Hub 上提供的官方模板(例如 JupyterLab、Gradio 聊天机器人、Streamlit 应用等)来初始化一个新的 Space。使用 list_space_templates() 列出可用模板,然后将模板的 repo_id(或其简短的 name)作为 space_template 传递给 create_repo()。请注意,space_sdk 仍然是必需的:模板用于初始化文件,而 SDK 用于设置卡片元数据。

>>> from huggingface_hub import HfApi
>>> api = HfApi()

# List available templates
>>> for template in api.list_space_templates():
...     print(f"{template.name} ({template.repo_id})")
Streamlit (streamlit/streamlit-template-space)
JupyterLab (SpacesExamples/jupyterlab)
chatbot (gradio-templates/chatbot)
...

# Create a Space from a template, by repo id or by short name
>>> api.create_repo(repo_id=repo_id, repo_type="space", space_template="SpacesExamples/jupyterlab")
>>> api.create_repo(repo_id=repo_id, repo_type="space", space_template="JupyterLab")

某些模板建议设置为私有(例如 JupyterLab)。如果您未显式设置可见性,此类 Spaces 将自动创建为私有。

在 CLI 中,也可以通过 hf spaces templates 和 hf repos create --template 使用相同的功能:

# List available templates
>>> hf spaces templates
NAME            REPO_ID                                        SDK    PREFERRED_PRIVATE
--------------- ---------------------------------------------- ------ -----------------
Streamlit       streamlit/streamlit-template-space             docker
JupyterLab      SpacesExamples/jupyterlab                      docker ✔
Argilla         argilla/argilla-template-space                 docker
Livebook        livebook-dev/livebook                          docker
...

# Create a Space from a template
>>> hf repos create my-jupyterlab --type space --template jupyterlab

复制一个 Space

如果您希望基于现有的 Space 进行构建,而不是从头开始,这会非常有用。 如果您希望控制公共 Space 的配置/设置,这也很有用。有关更多详细信息,请参阅 duplicate_repo()。

>>> api.duplicate_repo("multimodalart/dreambooth-training", repo_type="space")

使用您首选的方案上传您的代码

以下是一个示例,用于将您机器上的本地文件夹 src/ 上传到您的 Space:

>>> api.upload_folder(repo_id=repo_id, repo_type="space", folder_path="src/")

在此步骤中,您的应用应该已经在 Hub 上运行了!不过,您可能希望使用密钥和升级的硬件对其进行进一步配置。

配置密钥和变量

您的 Space 可能需要一些密钥、令牌或变量才能正常运行。 有关更多详细信息,请参阅 文档。 例如,一个 HF 令牌,用于将您的 Space 生成的图像数据集上传到 Hub。

>>> api.add_space_secret(repo_id=repo_id, key="HF_TOKEN", value="hf_api_***")
>>> api.add_space_variable(repo_id=repo_id, key="MODEL_REPO_ID", value="user/repo")

您可以列出已有的密钥和变量。密钥的值是只写的,因此仅返回键、描述和更新时间戳:

>>> api.get_space_secrets(repo_id=repo_id)
{'HF_TOKEN': SpaceSecret(key='HF_TOKEN', description=None, updated_at=datetime.datetime(...))}
>>> api.get_space_variables(repo_id=repo_id)
{'MODEL_REPO_ID': SpaceVariable(key='MODEL_REPO_ID', value='user/repo', description=None, updated_at=...)}

Secrets 和变量也可以被删除:

>>> api.delete_space_secret(repo_id=repo_id, key="HF_TOKEN")
>>> api.delete_space_variable(repo_id=repo_id, key="MODEL_REPO_ID")

在您的 Space 内部,密钥可作为环境变量使用(如果使用 Streamlit,则通过 Streamlit Secrets Management 管理)。无需通过 API 获取它们!

对您的 Space 配置(密钥或硬件)的任何更改都会触发您的应用重启。

额外提示:在创建或复制 Space 时设置密钥和变量!

在创建或复制空间时,可以设置密钥和变量:

>>> api.create_repo(
...     repo_id=repo_id,
...     repo_type="space",
...     space_sdk="gradio",
...     space_secrets=[{"key": "HF_TOKEN", "value": "hf_api_***"}, ...],
...     space_variables=[{"key": "MODEL_REPO_ID", "value": "user/repo"}, ...],
... )
>>> api.duplicate_repo(
...     from_id=repo_id,
...     repo_type="space",
...     space_secrets=[{"key": "HF_TOKEN", "value": "hf_api_***"}, ...],
...     space_variables=[{"key": "MODEL_REPO_ID", "value": "user/repo"}, ...],
... )

配置硬件

默认情况下,您的 Space 运行在免费的 cpu-basic 硬件上(Gradio 和 Docker Spaces 需要订阅,详见上文)。您可以升级硬件以在 GPU 上运行。升级 Space 需要支付方式以及预付费额度(或社区资助)。有关更多详细信息,请参阅 文档。

# Use `SpaceHardware` enum
>>> from huggingface_hub import SpaceHardware
>>> api.request_space_hardware(repo_id=repo_id, hardware=SpaceHardware.T4_MEDIUM)

# Or simply pass a string value
>>> api.request_space_hardware(repo_id=repo_id, hardware="t4-medium")

硬件更新不会立即生效,因为您的 Space 需要在我们的服务器上重新加载。 您可以随时查看您的 Space 正在运行的硬件,以确认您的请求是否已得到满足。

>>> runtime = api.get_space_runtime(repo_id=repo_id)
>>> runtime.stage
"RUNNING_BUILDING"
>>> runtime.hardware
"cpu-basic"
>>> runtime.requested_hardware
"t4-medium"

您现在已经拥有一个完全配置好的 Space。使用完毕后,请务必将您的 Space 降级回 cpu-basic。

额外提示:在创建或复制 Space 时请求硬件!

硬件升级后,您的 Space 构建完成时会自动分配。

>>> api.create_repo(
...     repo_id=repo_id,
...     repo_type="space",
...     space_sdk="gradio",
...     space_hardware="cpu-upgrade",
...     space_sleep_time="7200", # 2 hours in secs
... )
>>> api.duplicate_repo(
...     from_id=repo_id,
...     repo_type="space",
...     space_hardware="cpu-upgrade",
...     space_sleep_time="7200", # 2 hours in secs
... )

跟踪您的 ZeroGPU 配额

ZeroGPU Spaces 运行在按需分配的共享 GPU 上。每次您使用 ZeroGPU Space(通过 UI 或其 API)时,都会从您的个人配额中扣除一定的 GPU 时间,该配额会定期重置。如果您正在基于 ZeroGPU Spaces 构建应用、智能体或 MCP 服务器,可以使用 get_zero_gpu_quota() 来跟踪您的使用情况。数值以 GPU 秒为单位表示。

>>> quota = api.get_zero_gpu_quota()
>>> quota
ZeroGpuQuota(base=2400, remaining=1810, resets_at=datetime.datetime(2026, 9, 30, 9, 12, 3, tzinfo=datetime.timezone.utc), overquota_used=0)
>>> if quota.remaining < 60:
...     print(f"Less than 1 minute of ZeroGPU left. Quota resets at {quota.resets_at}.")

resets_at 在自上次重置以来未使用过 ZeroGPU 时为 None。如果使用细粒度令牌,该令牌必须具有“Billing > Read billing usage and payment method status”权限。相同的信息也可以通过 CLI 命令 hf spaces zero-gpu quota 获取。

配额用尽后,PRO、Team 和 Enterprise 用户可以通过消耗预付费额度继续使用 ZeroGPU Spaces。您可以从账单设置中购买额度。有关更多详细信息,请参阅使用额度扩展配额。

暂停并重启您的 Space

默认情况下,如果您的 Space 运行在升级后的硬件上,它将永远不会停止。但为了避免产生费用,您可能希望在未使用时将其暂停。这可以通过 pause_space() 实现。已暂停的 Space 将处于非活动状态,直到 Space 的所有者通过 UI 或使用 restart_space() 通过 API 将其重新启动。有关暂停模式的更多详细信息,请参阅 此部分

# Pause your Space to avoid getting billed
>>> api.pause_space(repo_id=repo_id)
# (...)
# Restart it when you need it
>>> api.restart_space(repo_id=repo_id)

另一种方法是为您的 Space 设置超时时间。如果您的 Space 在超过超时时长后处于非活动状态,它将进入休眠。任何访问您 Space 的用户都会将其重新唤醒。您可以使用 set_space_sleep_time() 来设置超时时间。有关休眠模式的更多详细信息,请参阅 此部分。

# Put your Space to sleep after 1h of inactivity
>>> api.set_space_sleep_time(repo_id=repo_id, sleep_time=3600)

注意:如果您使用的是‘cpu-basic’硬件,则无法配置自定义休眠时间。您的 Space 将在 48 小时无活动后自动暂停。

附加功能:在请求硬件时设置睡眠时间

硬件升级后,您的 Space 构建完成时会自动分配。

>>> api.request_space_hardware(repo_id=repo_id, hardware=SpaceHardware.T4_MEDIUM, sleep_time=3600)

额外提示:在创建或复制 Space 时设置休眠时间!

>>> api.create_repo(
...     repo_id=repo_id,
...     repo_type="space",
...     space_sdk="gradio",
...     space_hardware="t4-medium",
...     space_sleep_time="3600",
... )
>>> api.duplicate_repo(
...     from_id=repo_id,
...     repo_type="space",
...     space_hardware="t4-medium",
...     space_sleep_time="3600",
... )

通过读取日志来调试失败的 Space

当 Space 构建失败或在运行时崩溃时,您通常在浏览器中查看的日志也可以通过 fetch_space_logs() 以编程方式获取。这在无法打开浏览器的脚本或智能体工作流中尤为有用。

# Drain the currently available run logs and return immediately (like `docker logs`)
>>> for line in api.fetch_space_logs(repo_id=repo_id):
...     print(line, end="")

# Read the container build logs instead (useful when the Space is stuck in BUILD_ERROR)
>>> for line in api.fetch_space_logs(repo_id=repo_id, build=True):
...     print(line, end="")

# Stream run logs in real time until the server closes the stream (Ctrl-C to stop)
>>> for line in api.fetch_space_logs(repo_id=repo_id, follow=True):
...     print(line, end="")

相同的功能也可以通过命令行界面使用:

hf spaces logs username/my-space             # drain run logs
hf spaces logs username/my-space --build     # read build logs
hf spaces logs username/my-space -f          # stream in real time
hf spaces logs username/my-space -n 50       # last 50 lines only

通过 SSH 连接到 Space(开发模式)

开发模式允许你通过 SSH 连接到正在运行的 Space 容器,以便进行实时调试和开发。使用 hf spaces ssh 可以直接从终端打开一个会话。如果该 Space 尚未启用开发模式,CLI 会提示你启用它(或者传入 --auto 以跳过提示)。

您的 SSH 公钥必须在您的设置中注册。

# SSH into a Space (enables Dev Mode if needed)
hf spaces ssh username/my-space

# Auto-enable Dev Mode without prompting
hf spaces ssh username/my-space --auto

# Print the SSH command without running it
hf spaces ssh username/my-space --dry-run

# Use a specific SSH key
hf spaces ssh username/my-space -i ~/.ssh/id_ed25519

您也可以在不使用 SSH 的情况下,通过 hf spaces dev-mode 启用开发模式,该命令会打印出用于 SSH、VS Code、Cursor 和 Windsurf 的连接说明:

hf spaces dev-mode username/my-space

启用 Dev Mode 需要 PRO 或 Team & Enterprise 套餐。禁用 Dev Mode 始终被允许,例如,如果在 Dev Mode 开启期间您的订阅已过期:

hf spaces dev-mode username/my-space --stop

在您的 Space 中挂载卷

您可以将 Hub 资源(模型、数据集或存储桶)作为卷挂载到 Space 的容器中。这样,您的 Space 就可以直接通过文件系统访问这些资源,而无需在代码中下载它们。在创建或复制 Space 时,可以直接设置卷:

>>> from huggingface_hub import Volume
>>> api.create_repo(
...     repo_id=repo_id,
...     repo_type="space",
...     space_sdk="gradio",
...     space_volumes=[
...         Volume(type="model", source="username/my-model", mount_path="/models", read_only=True),
...         Volume(type="bucket", source="username/my-bucket", mount_path="/data"),
...     ],
... )
>>> api.duplicate_repo(
...     from_id=repo_id,
...     repo_type="space",
...     space_volumes=[
...         Volume(type="model", source="username/my-model", mount_path="/models", read_only=True),
...         Volume(type="bucket", source="username/my-bucket", mount_path="/data"),
...     ],
... )

您可以通过 Space 运行时检查当前挂载了哪些卷:

>>> runtime = api.get_space_runtime(repo_id=repo_id)
>>> runtime.volumes
[Volume(type='model', source='username/my-model', mount_path='/models', read_only=True), ...]

如果需要更新现有 Space 上的卷,请使用 set_space_volumes()。请注意,此操作会替换所有先前挂载的卷。

>>> api.set_space_volumes(
...     repo_id=repo_id,
...     volumes=[
...         Volume(type="model", source="username/my-model", mount_path="/models", read_only=True),
...         Volume(type="dataset", source="username/my-dataset", mount_path="/data", read_only=True),
...         Volume(type="bucket", source="username/my-bucket", mount_path="/output"),
...     ],
... )

要从您的 Space 中移除所有卷:

>>> api.delete_space_volumes(repo_id=repo_id)

模型、数据集和 Spaces 始终以只读方式挂载。只有存储桶支持读写挂载。

设置卷会替换之前挂载的所有卷。若要向现有列表中添加卷,请先从运行时读取当前卷,并将其包含在新列表中。

所有卷操作也可从命令行界面(CLI)中调用:

# List current volumes
hf spaces volumes ls username/my-space

# Set (replace) volumes
hf spaces volumes set username/my-space \
    -v hf://models/username/my-model:/models \
    -v hf://buckets/username/my-bucket:/data

# Remove all volumes
hf spaces volumes delete username/my-space

更高级的操作:临时升级你的 Space!

Spaces 支持多种不同的使用场景。有时,您可能希望临时在特定硬件上运行一个 Space,完成某些操作后再将其关闭。在本节中,我们将探讨如何利用 Spaces 按需微调模型。这只是解决该特定问题的一种方法,应将其视为一种建议,并根据您的具体使用场景进行调整。

假设我们有一个用于微调模型的 Space。它是一个 Gradio 应用,接收模型 ID 和数据集 ID 作为输入。工作流程如下:

  1. (提示用户输入模型和数据集)
  2. 从 Hub 加载模型。
  3. 从 Hub 加载数据集。
  4. 在数据集上微调模型。
  5. 将新模型上传到 Hub。

步骤 3. 需要自定义硬件,但你又不希望你的 Space 一直在付费 GPU 上运行。一种解决方案是动态请求用于训练的硬件,并在训练结束后将其关闭。由于请求硬件会重启你的 Space,你的应用必须以某种方式“记住”当前正在执行的任务。实现这一点有多种方法。在本指南中,我们将展示一种使用 Dataset 作为“任务调度器”的解决方案。

应用骨架

以下是您的应用运行时的样子。启动时,检查是否有已调度的任务,如果有,则在正确的硬件上运行它。完成后,将硬件重置为空闲的 cpu-basic CPU,并提示用户输入新任务。

此类工作流不支持像普通演示那样进行并发访问。 特别是,在训练发生时,界面将被禁用。 建议将您的仓库设置为私有,以确保您是唯一的使用者。

# Space will need your token to request hardware: set it as a Secret !
HF_TOKEN = os.environ.get("HF_TOKEN")

# Space own repo_id
TRAINING_SPACE_ID = "Wauplin/dreambooth-training"

from huggingface_hub import HfApi, SpaceHardware
api = HfApi(token=HF_TOKEN)

# On Space startup, check if a task is scheduled. If yes, finetune the model. If not,
# display an interface to request a new task.
task = get_task()
if task is None:
    # Start Gradio app
    def gradio_fn(task):
        # On user request, add task and request hardware
        add_task(task)
        api.request_space_hardware(repo_id=TRAINING_SPACE_ID, hardware=SpaceHardware.T4_MEDIUM)

    gr.Interface(fn=gradio_fn, ...).launch()
else:
    runtime = api.get_space_runtime(repo_id=TRAINING_SPACE_ID)
    # Check if Space is loaded with a GPU.
    if runtime.hardware == SpaceHardware.T4_MEDIUM:
        # If yes, finetune base model on dataset !
        train_and_upload(task)

        # Then, mark the task as "DONE"
        mark_as_done(task)

        # DO NOT FORGET: set back CPU hardware
        api.request_space_hardware(repo_id=TRAINING_SPACE_ID, hardware=SpaceHardware.CPU_BASIC)
    else:
        api.request_space_hardware(repo_id=TRAINING_SPACE_ID, hardware=SpaceHardware.T4_MEDIUM)

任务调度器

任务调度可以通过多种方式实现。下面是一个使用以 Dataset 形式存储的简单 CSV 文件来完成任务调度的示例。

# Dataset ID in which a `tasks.csv` file contains the tasks to perform.
# Here is a basic example for `tasks.csv` containing inputs (base model and dataset)
# and status (PENDING or DONE).
#     multimodalart/sd-fine-tunable,Wauplin/concept-1,DONE
#     multimodalart/sd-fine-tunable,Wauplin/concept-2,PENDING
TASK_DATASET_ID = "Wauplin/dreambooth-task-scheduler"

def _get_csv_file():
    return hf_hub_download(repo_id=TASK_DATASET_ID, filename="tasks.csv", repo_type="dataset", token=HF_TOKEN)

def get_task():
    with open(_get_csv_file()) as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        for row in csv_reader:
            if row[2] == "PENDING":
                return row[0], row[1] # model_id, dataset_id

def add_task(task):
    model_id, dataset_id = task
    with open(_get_csv_file()) as csv_file:
        with open(csv_file, "r") as f:
            tasks = f.read()

    api.upload_file(
        repo_id=repo_id,
        repo_type=repo_type,
        path_in_repo="tasks.csv",
        # Quick and dirty way to add a task
        path_or_fileobj=(tasks + f"\n{model_id},{dataset_id},PENDING").encode()
    )

def mark_as_done(task):
    model_id, dataset_id = task
    with open(_get_csv_file()) as csv_file:
        with open(csv_file, "r") as f:
            tasks = f.read()

    api.upload_file(
        repo_id=repo_id,
        repo_type=repo_type,
        path_in_repo="tasks.csv",
        # Quick and dirty way to set the task as DONE
        path_or_fileobj=tasks.replace(
            f"{model_id},{dataset_id},PENDING",
            f"{model_id},{dataset_id},DONE"
        ).encode()
    )
Update on GitHub