Hub Python Library documentation

管理您的 Space

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v2.4.0).
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