管理您的空间
在本指南中,我们将了解如何使用 huggingface_hub
管理您的空间运行时(密钥、硬件 和 存储)。
一个简单示例:配置密钥和硬件。
以下是一个在 Hub 上创建和设置空间的端到端示例。
1. 在 Hub 上创建空间。
>>> 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")
1.(bis)复制空间。
如果您想从现有空间构建而不是从头开始,这将非常有用。如果您想要控制公共空间的配置/设置,这也很有用。查看 duplicate_space() 获取更多详细信息。
>>> api.duplicate_space("multimodalart/dreambooth-training")
2. 使用您首选的解决方案上传您的代码。
以下是一个将本地文件夹 src/
从您的机器上传到您的空间的示例。
>>> api.upload_folder(repo_id=repo_id, repo_type="space", folder_path="src/")
在此步骤中,您的应用程序应该已经在 Hub 上免费运行!但是,您可能希望使用密钥和升级后的硬件对其进行进一步配置。
3. 配置密钥和变量
您的空间可能需要一些密钥、令牌或变量才能正常工作。查看 文档 获取更多详细信息。例如,HF 令牌可在您从空间生成后将图像数据集上传到 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.delete_space_secret(repo_id=repo_id, key="HF_TOKEN")
>>> api.delete_space_variable(repo_id=repo_id, key="MODEL_REPO_ID")
额外提示:在创建或复制 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_space(
... from_id=repo_id,
... secrets=[{"key"="HF_TOKEN", "value"="hf_api_***"}, ...],
... variables=[{"key"="MODEL_REPO_ID", "value"="user/repo"}, ...],
... )
4. 配置硬件
默认情况下,你的 Space 将在 CPU 环境中免费运行。你可以升级硬件,使其在 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-classic”。
额外提示:在创建或复制 Space 时请求硬件!
升级后的硬件将在 Space 建立后自动分配给你的 Space。
>>> api.create_repo(
... repo_id=repo_id,
... repo_type="space",
... space_sdk="gradio"
... space_hardware="cpu-upgrade",
... space_storage="small",
... space_sleep_time="7200", # 2 hours in secs
... )
>>> api.duplicate_space(
... from_id=repo_id,
... hardware="cpu-upgrade",
... storage="small",
... sleep_time="7200", # 2 hours in secs
... )
5. 暂停和重启你的 Space
默认情况下,如果你的 Space 在升级后的硬件上运行,它将永远不会被停止。但是,为了避免被计费,你可能希望在不使用时暂停它。可以使用 pause_space() 来实现。暂停的 Space 将处于非活动状态,直到 Space 的所有者使用 UI 或通过 API 使用 restart_space() 重新启动它。有关暂停模式的更多详细信息,请参阅 此部分
# 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 建立后自动分配给你的 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_space(
... from_id=repo_id,
... hardware="t4-medium",
... sleep_time="3600",
... )
6. 为你的 Space 添加持久存储
你可以选择你想要的存储层级来访问磁盘空间,这些空间在你的 Space 重启时会持久保留。这意味着你可以像使用传统硬盘一样从磁盘读取和写入。有关更多详细信息,请参阅 文档。
>>> from huggingface_hub import SpaceStorage
>>> api.request_space_storage(repo_id=repo_id, storage=SpaceStorage.LARGE)
你也可以删除你的存储,永久丢失所有数据。
>>> api.delete_space_storage(repo_id=repo_id)
注意:一旦授予空间,你就无法降低空间的存储层级。为此,你必须先删除存储,然后请求新的目标层级。
额外提示:在创建或复制 Space 时请求存储!
>>> api.create_repo(
... repo_id=repo_id,
... repo_type="space",
... space_sdk="gradio"
... space_storage="large",
... )
>>> api.duplicate_space(
... from_id=repo_id,
... storage="large",
... )
更高级:临时升级你的 Space!
Spaces 允许许多不同的用例。有时,你可能想要临时在特定硬件上运行一个 Space,执行一些操作,然后将其关闭。在本节中,我们将探讨如何利用 Spaces 按需微调模型。这只是解决这个问题的一种方法。它应该被视为一种建议,并根据你的用例进行调整。
假设我们有一个用于微调模型的 Space。它是一个 Gradio 应用程序,它接受模型 ID 和数据集 ID 作为输入。工作流程如下:
- (提示用户输入模型和数据集)
- 从 Hub 加载模型。
- 从 Hub 加载数据集。
- 使用数据集微调模型。
- 将新模型上传到 Hub。
步骤 3 需要自定义硬件,但你并不希望你的 Space 始终在付费 GPU 上运行。一个解决方案是为训练动态请求硬件,并在完成后将其关闭。由于请求硬件会重启你的 Space,因此你的应用程序必须以某种方式“记住”它正在执行的当前任务。有多种方法可以做到这一点。在本指南中,我们将看到使用数据集作为“任务调度器”的一种解决方案。
应用程序骨架
以下是你的应用程序的外观。在启动时,检查是否已安排任务,如果是,则在正确的硬件上运行它。完成后,将硬件设置回免费计划的 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)
任务调度器
可以使用多种方法来安排任务。以下是如何使用简单的 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()
)