Hub Python Library documentation
Gestiona tu Space
Gestiona tu Space
En esta guía, veremos cómo gestionar el tiempo de ejecución de tu Space (secrets, hardware y volúmenes) usando huggingface_hub.
Buscar en Spaces
Puedes buscar Spaces en el Hub mediante búsqueda semántica con search_spaces(). Esto utiliza búsqueda basada en embeddings para consultas de varias palabras y búsqueda de texto completo para consultas de una sola palabra.
>>> 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, ...)Puedes filtrar los resultados por SDK o etiquetas:
>>> results = search_spaces("chatbot", sdk="gradio", filter="mcp-server")O mediante la CLI:
>>> hf spaces search "generate image"
>>> hf spaces search "chatbot" --sdk gradio --limit 5Un ejemplo sencillo: configurar secretos y hardware.
A continuación se muestra un ejemplo de principio a fin para crear y configurar un Space en el Hub.
Crear un Space en el 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")Los Spaces estáticos son gratuitos para todos. Los Spaces de Gradio y Docker se ejecutan en hardware de cómputo: en el hardware gratuito
cpu-basic, requieren una suscripción (PRO para usuarios, Team o Enterprise para organizaciones), mientras que el hardware de pago solo requiere facturación (un método de pago y créditos prepagados). Sin una suscripción, crear, duplicar o mover un Space de Gradio o Docker encpu-basicfalla con un error de pago (HTTP 402). Consulte precios para más detalles.
Crear un Space a partir de una plantilla
En lugar de empezar desde un Space vacío, puede iniciar un nuevo Space a partir de una de las plantillas oficiales ofrecidas en el Hub (p. ej. JupyterLab, un chatbot de Gradio, una aplicación de Streamlit, etc.). Enumere las plantillas disponibles con list_space_templates() y, a continuación, pase el repo_id de una plantilla (o su name abreviado) como space_template a create_repo(). Tenga en cuenta que space_sdk sigue siendo obligatorio: la plantilla inicia los archivos, mientras que el SDK establece los metadatos de la tarjeta.
>>> 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")Algunas plantillas se recomiendan como privadas (p. ej., JupyterLab). Si no estableces la visibilidad de forma explícita, dichos Spaces se crean como privados automáticamente.
Desde la CLI, lo mismo está disponible a través de hf spaces templates y 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 jupyterlabDuplicar un Space
Esto puede resultar útil si deseas construir a partir de un Space existente en lugar de empezar desde cero. También es útil si deseas tener control sobre la configuración/ajustes de un Space público. Consulta duplicate_repo() para más detalles.
>>> api.duplicate_repo("multimodalart/dreambooth-training", repo_type="space")Sube tu código usando la solución que prefieras
A continuación se muestra un ejemplo para subir la carpeta local src/ de su máquina a su Space:
>>> api.upload_folder(repo_id=repo_id, repo_type="space", folder_path="src/")En este paso, tu aplicación ya debería estar funcionando en el Hub. Sin embargo, es posible que desees configurarla aún más con secretos y hardware mejorado.
Configurar secretos y variables
Tu Space puede requerir algunas claves secretas, tokens o variables para funcionar. Consulta la documentación para más detalles. Por ejemplo, un token de HF para subir un conjunto de datos de imágenes al Hub una vez que se genere desde tu Space.
>>> 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")Puedes listar los secretos y variables existentes. Los valores de los secretos son de solo escritura, por lo que solo se devuelven las claves, las descripciones y las marcas de tiempo de actualización:
>>> 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=...)}Los secretos y las variables también se pueden eliminar:
>>> api.delete_space_secret(repo_id=repo_id, key="HF_TOKEN")
>>> api.delete_space_variable(repo_id=repo_id, key="MODEL_REPO_ID")Desde tu Space, los secretos están disponibles como variables de entorno (o Streamlit Secrets Management si usas Streamlit). ¡No es necesario obtenerlos a través de la API!
Cualquier cambio en la configuración de tu Space (secrets o hardware) provocará un reinicio de tu aplicación.
Bonus: configura secretos y variables al crear o duplicar el Space.
Los secretos y las variables se pueden establecer al crear o duplicar un espacio:
>>> 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"}, ...],
... )Configura el hardware
Por defecto, tu Space se ejecuta en el hardware gratuito cpu-basic (que requiere una suscripción para Spaces de Gradio y Docker, ver arriba). Puedes actualizar el hardware para ejecutarlo en GPUs. Se requiere un método de pago y créditos prepagados (o una subvención de la comunidad) para actualizar tu Space. Consulta la documentación para más detalles.
# 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")Las actualizaciones de hardware no se realizan de inmediato, ya que tu Space debe recargarse en nuestros servidores. En cualquier momento, puedes consultar en qué hardware se está ejecutando tu Space para ver si se ha atendido tu solicitud.
>>> runtime = api.get_space_runtime(repo_id=repo_id)
>>> runtime.stage
"RUNNING_BUILDING"
>>> runtime.hardware
"cpu-basic"
>>> runtime.requested_hardware
"t4-medium"Ahora tienes un Space completamente configurado. Asegúrate de cambiar tu Space de vuelta a cpu-basic cuando termines de usarlo.
Bonus: solicita hardware al crear o duplicar el Space.
El hardware actualizado se asignará automáticamente a tu Space una vez que se haya construido.
>>> 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
... )Controla tu cuota de ZeroGPU
Los Spaces de ZeroGPU se ejecutan en GPUs compartidas asignadas bajo demanda. Cada vez que usas un Space de ZeroGPU (desde la interfaz de usuario o a través de su API), se descuenta parte del tiempo de GPU de tu cuota personal, que se restablece periódicamente. Si estás construyendo una aplicación, un agente o un servidor MCP sobre Spaces de ZeroGPU, puedes hacer un seguimiento de tu uso con get_zero_gpu_quota(). Los valores se expresan en segundos de 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 es None si no has usado ZeroGPU desde el último reinicio. Si usas un token de grano fino, debe tener el permiso “Billing > Read billing usage and payment method status”. La misma información está disponible desde la CLI con hf spaces zero-gpu quota.
Una vez agotada la cuota, los usuarios PRO, Team y Enterprise pueden seguir usando los Spaces de ZeroGPU consumiendo créditos prepagados. Puedes comprar créditos desde tus configuraciones de facturación. Consulta Extender la cuota con créditos para más detalles.
Pausar y reanudar tu Space
Por defecto, si tu Space se ejecuta en hardware actualizado, nunca se detendrá. Sin embargo, para evitar cargos, es posible que desees pausarlo cuando no lo estés usando. Esto es posible mediante pause_space(). Un Space pausado permanecerá inactivo hasta que el propietario del Space lo reinicie, ya sea a través de la interfaz de usuario o mediante la API usando restart_space(). Para más detalles sobre el modo pausado, consulta esta sección
# 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)Otra posibilidad es establecer un tiempo de espera para tu Space. Si tu Space permanece inactivo durante más tiempo que la duración del tiempo de espera, pasará a modo de suspensión. Cualquier visitante que acceda a tu Space lo volverá a iniciar. Puedes establecer un tiempo de espera usando set_space_sleep_time(). Para más detalles sobre el modo de suspensión, consulta esta sección.
# Put your Space to sleep after 1h of inactivity
>>> api.set_space_sleep_time(repo_id=repo_id, sleep_time=3600)Nota: si estás usando un hardware ‘cpu-basic’, no puedes configurar un tiempo de suspensión personalizado. Tu Space se pausará automáticamente después de 48h de inactividad.
Bonus: establecer un tiempo de espera al solicitar hardware
El hardware actualizado se asignará automáticamente a tu Space una vez que se haya construido.
>>> api.request_space_hardware(repo_id=repo_id, hardware=SpaceHardware.T4_MEDIUM, sleep_time=3600)Bonus: ¡establece un tiempo de espera al crear o duplicar el 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",
... )Depurar un Space que falla leyendo sus registros
Cuando un Space no se compila o se detiene de forma inesperada en tiempo de ejecución, los registros que normalmente se ven en el navegador también están disponibles de forma programática mediante fetch_space_logs(). Esto resulta especialmente útil en scripts o flujos de trabajo agénticos donde abrir un navegador no es una opción.
# 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="")La misma funcionalidad está disponible desde la CLI:
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 onlyConectarse a un Space mediante SSH (modo de desarrollo)
Dev Mode te permite acceder por SSH a un contenedor de Space en ejecución para depurar y desarrollar en vivo. Usa hf spaces ssh para abrir una sesión directamente desde la terminal. Si Dev Mode aún no está habilitado en el Space, la CLI te pedirá que lo habilites (o pasa --auto para omitir la solicitud).
Tu clave pública SSH debe estar registrada en tus ajustes.
# 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_ed25519También puedes activar el modo de desarrollo sin SSH usando hf spaces dev-mode, que imprime las instrucciones de conexión para SSH, VS Code, Cursor y Windsurf:
hf spaces dev-mode username/my-space
Activar el modo de desarrollo requiere un plan PRO o Team & Enterprise. Desactivarlo siempre está permitido, por ejemplo, si tu suscripción ha expirado mientras el modo de desarrollo estaba activado:
hf spaces dev-mode username/my-space --stop
Montar volúmenes en tu Space
Puedes montar recursos del Hub (modelos, conjuntos de datos o cubos de almacenamiento) como volúmenes en el contenedor de tu Space. Esto le da a tu Space acceso directo al sistema de archivos de estos recursos sin necesidad de descargarlos en tu código. Los volúmenes se pueden configurar directamente al crear o duplicar un 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"),
... ],
... )Puede comprobar qué volúmenes están montados actualmente a través del runtime de 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), ...]Si necesitas actualizar los volúmenes en un Space existente, usa set_space_volumes(). Ten en cuenta que esto reemplaza todos los volúmenes montados previamente.
>>> 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"),
... ],
... )Para eliminar todos los volúmenes de tu Space:
>>> api.delete_space_volumes(repo_id=repo_id)Los modelos, conjuntos de datos y Spaces siempre se montan en modo de solo lectura. Solo los buckets de almacenamiento admiten montajes de lectura y escritura.
Establecer volúmenes reemplaza cualquier volumen montado previamente. Para agregar un volumen a una lista existente, primero lea los volúmenes actuales desde el runtime e inclúyalos en la nueva lista.
Todas las operaciones de volumen también están disponibles desde la 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-spaceMás avanzado: ¡actualiza temporalmente tu Space!
Spaces permiten muchos casos de uso diferentes. A veces, es posible que quieras ejecutar un Space temporalmente en un hardware específico, realizar una tarea y luego apagarlo. En esta sección, exploraremos cómo aprovechar Spaces para ajustar un modelo bajo demanda. Esta es solo una forma de resolver este problema en particular. Debe tomarse como una sugerencia y adaptarse a tu caso de uso.
Supongamos que tenemos un Space para afinar un modelo. Es una aplicación de Gradio que toma como entrada un id de modelo y un id de dataset. El flujo de trabajo es el siguiente:
- (Solicitar al usuario un modelo y un conjunto de datos)
- Cargue el modelo desde el Hub.
- Cargue el conjunto de datos desde el Hub.
- Ajusta el modelo en el conjunto de datos.
- Sube el nuevo modelo al Hub.
Paso 3. requiere un hardware personalizado, pero no quieres que tu Space se ejecute todo el tiempo en una GPU de pago. Una solución es solicitar hardware dinámicamente para el entrenamiento y apagarlo después. Dado que solicitar hardware reinicia tu Space, tu aplicación debe “recordar” de alguna manera la tarea actual que está realizando. Hay varias formas de hacer esto. En esta guía veremos una solución que utiliza un Dataset como “planificador de tareas”.
Esqueleto de la aplicación
Así se vería su aplicación. Al iniciar, compruebe si hay una tarea programada y, en caso afirmativo, ejecútela en el hardware correcto. Una vez finalizada, devuelva el hardware al CPU cpu-basic libre y solicite al usuario una nueva tarea.
Este flujo de trabajo no admite el acceso concurrente como las demostraciones normales. En particular, la interfaz se deshabilitará cuando se produzca el entrenamiento. Es preferible configurar su repositorio como privado para asegurarse de que usted es el único usuario.
# 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)Planificador de tareas
La programación de tareas se puede realizar de muchas maneras. A continuación se muestra un ejemplo de cómo hacerlo utilizando un simple CSV almacenado como un Dataset.
# 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()
)