Mục lục
Mục tiêu bài học
Sau bài này bạn sẽ:
- ✅ Hiểu HF Spaces hoạt động như thế nào (git repo + hosted runner)
- ✅ Tạo Space mới và chọn đúng SDK cho app
- ✅ Viết đúng
README.mdfrontmatter để Space build thành công - ✅ Push code bằng git (bao gồm xử lý file lớn với git-lfs)
- ✅ Quản lý secrets — không hard-code API key vào code
- ✅ Biết giới hạn của free tier và khi nào cần upgrade hardware
Hugging Face Spaces là gì
Hugging Face Spaces là platform hosting demo ML. Mỗi Space là một git repository — push code lên là HF tự build và chạy app, không cần cấu hình server.
Spaces hỗ trợ 4 SDK:
- Gradio — chạy
app.pyvớidemo.launch() - Streamlit — chạy
app.pyvớistreamlit run - Docker — bạn tự viết
Dockerfile, HF build và chạy container - Static — hosting HTML/CSS/JS thuần, không có server-side Python
URL của một Space có dạng:
https://huggingface.co/spaces/<username>/<space-name>
App chạy ở cùng URL đó (không phải subdomain riêng).
Free tier
CPU Basic (miễn phí):
- 2 vCPU
- 16 GB RAM
- Space phải public (private cần Pro plan $9/tháng)
- App tự sleep sau 48 giờ không có request — lần truy cập tiếp theo phải cold start (~30-60 giây)
Free tier đủ dùng cho demo model nhỏ (embedding, classification, text generation với model ≤ 7B đã quantize). Nếu app cần GPU, phải upgrade hardware (trả tiền theo giờ).
Tạo Space mới
- Đăng nhập tại
https://huggingface.co/login. - Nhấn nút New Space (góc phải trên, hoặc từ profile menu).
- Điền thông tin:
- Owner: username hoặc organization
- Space name: slug dùng trong URL, chỉ chứa chữ cái, số, dấu gạch ngang
- SDK: chọn Gradio hoặc Streamlit tùy app bạn đã build ở bài 9-10
- SDK version: khuyến nghị chọn version cụ thể khớp với local (tránh breaking change)
- Hardware: CPU basic (free)
- License: apache-2.0, mit, hoặc other
- Visibility: Public (free) hoặc Private (Pro)
- Nhấn Create Space.
Sau khi tạo, HF tạo git repo rỗng với README.md mẫu. Bước tiếp theo là đẩy code lên.
Cấu trúc file trong Space
Cấu trúc tối thiểu cho Gradio hoặc Streamlit Space:
my-space/
├── app.py # Entry point bắt buộc
├── requirements.txt # Dependencies — HF tự pip install
└── README.md # Bắt buộc có YAML frontmatter
Nếu có thêm module phụ hoặc assets:
my-space/
├── app.py
├── utils.py
├── requirements.txt
├── README.md
├── .gitignore
└── assets/
└── sample.jpg # File ví dụ, ảnh mẫu, ...
README.md — YAML frontmatter
HF đọc metadata từ YAML block ở đầu README.md. Nếu thiếu hoặc sai field, build sẽ fail:
---
title: My Gradio App
emoji: 🤖
colorFrom: blue
colorTo: purple
sdk: gradio
sdk_version: "4.44.0"
app_file: app.py
pinned: false
license: apache-2.0
---
# My Gradio App
Mô tả ngắn về Space này...
Các field quan trọng:
sdk:gradio,streamlit,docker, hoặcstaticsdk_version: version cụ thể, phải là string (để trong dấu ngoặc kép). Nếu bỏ trống, HF dùng version mới nhất — có thể gây breaking change khi Gradio hoặc Streamlit release major version mới.app_file: đường dẫn tới entry point, mặc định làapp.pypinned:trueđể Space luôn hiển thị ở đầu profile
Với Streamlit, frontmatter giống hệt, chỉ đổi sdk: streamlit và sdk_version tương ứng (ví dụ "1.36.0").
Push code — web UI và git
Cách 1: Upload qua web UI
Vào trang Space → tab Files → nút Add file → drag-drop hoặc chọn file. Phù hợp khi chỉ có vài file nhỏ hoặc cần sửa nhanh một file cụ thể.
Cách 2: Git (khuyến nghị)
Space là git repo, push code như mọi git repo khác. Mỗi lần push → HF tự trigger build:
# Cài git-lfs nếu chưa có (cần cho file > 10MB)
git lfs install
# Clone repo của Space về local
git clone https://huggingface.co/spaces/<username>/<space-name>
cd <space-name>
# Thêm/sửa file
cp /path/to/your/app.py .
cp /path/to/your/requirements.txt .
# Sửa README.md frontmatter cho đúng
git add app.py requirements.txt README.md
git commit -m "add initial app"
git push
Nếu cần xác thực khi push, có hai cách:
- HTTPS + token: dùng HF access token thay mật khẩu (tạo token tại
https://huggingface.co/settings/tokens) - SSH: thêm SSH key tại
https://huggingface.co/settings/keys, rồi clone quagit clone [email protected]:spaces/<username>/<space-name>
File lớn và git-lfs
HF Spaces dùng git-lfs để lưu file > 10MB (model weights, dataset, ảnh lớn). File không theo dõi bởi lfs sẽ bị từ chối nếu vượt giới hạn 10MB của git thông thường:
# Track file theo extension
git lfs track "*.bin"
git lfs track "*.pt"
git lfs track "*.safetensors"
# .gitattributes sẽ được tạo/cập nhật tự động
git add .gitattributes
git add model.bin
git commit -m "add model weights"
git push
Model lớn (> 1-2GB) không nên lưu trong Space repo. Thay vào đó, load runtime từ HF Hub bằng from_pretrained() — xem mục 11.
Build và run lifecycle
Mỗi lần push code, HF chạy build pipeline theo thứ tự:
- Detect SDK: đọc
sdkfield trongREADME.mdfrontmatter - Install dependencies: chạy
pip install -r requirements.txt - Start app: với Gradio →
python app.py; với Streamlit →streamlit run app.py --server.port 7860 --server.address 0.0.0.0 - Reverse proxy: HF expose app ra HTTPS — port 7860 (Gradio) hoặc 8501 (Streamlit) bên trong container được map tới URL public
Để xem log build và runtime, vào tab Logs trong trang Space. Log cập nhật real-time. Nếu build fail, lỗi thường ở bước install dependency (package không tồn tại, conflict version) hoặc import error khi start app.
Build timeout
HF giới hạn build tối đa 1 giờ. Nếu cài dependency mất quá lâu (pytorch với CUDA index, các package C++ extension lớn), build sẽ bị kill. Giải pháp: dùng Docker SDK để tự kiểm soát build environment, hoặc tối giản requirements.txt (dùng CPU-only torch nếu không cần GPU).
CPU-only PyTorch
Cài PyTorch đầy đủ CUDA trên CPU-only Space sẽ download ~2GB, dễ timeout. Dùng CPU wheel riêng:
# requirements.txt — cài torch CPU-only để build nhanh hơn
--extra-index-url https://download.pytorch.org/whl/cpu
torch==2.3.0+cpu
torchvision==0.18.0+cpu
Ví dụ đầy đủ — Gradio image classifier
Ví dụ này deploy một image classifier ResNet-50 lên HF Spaces. Gồm 3 file.
app.py
import gradio as gr
from PIL import Image
import torch
from torchvision import models, transforms
import json
import urllib.request
# ---- Load class labels ----
LABELS_URL = (
"https://raw.githubusercontent.com/anishathalye/imagenet-simple-labels"
"/master/imagenet-simple-labels.json"
)
with urllib.request.urlopen(LABELS_URL) as r:
IMAGENET_LABELS: list[str] = json.loads(r.read())
# ---- Load model (1 lần khi container khởi động) ----
model = models.resnet50(weights=models.ResNet50_Weights.DEFAULT)
model.eval()
preprocess = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225],
),
])
def classify(img: Image.Image) -> dict[str, float]:
tensor = preprocess(img).unsqueeze(0)
with torch.no_grad():
logits = model(tensor)
probs = torch.softmax(logits[0], dim=0)
top5 = probs.topk(5)
return {
IMAGENET_LABELS[idx.item()]: round(prob.item(), 4)
for prob, idx in zip(top5.values, top5.indices)
}
demo = gr.Interface(
fn=classify,
inputs=gr.Image(type="pil"),
outputs=gr.Label(num_top_classes=5),
title="ResNet-50 Image Classifier",
description="Upload ảnh để xem top-5 predictions.",
)
# HF Spaces chạy app.py trực tiếp, không cần if __name__ == "__main__"
# nhưng để tương thích local thì thêm vào cũng được
demo.launch()
requirements.txt
--extra-index-url https://download.pytorch.org/whl/cpu
gradio==4.44.0
torch==2.3.0+cpu
torchvision==0.18.0+cpu
pillow
README.md
---
title: ResNet50 Image Classifier
emoji: 🖼️
colorFrom: green
colorTo: blue
sdk: gradio
sdk_version: "4.44.0"
app_file: app.py
pinned: false
license: apache-2.0
---
# ResNet-50 Image Classifier
Demo phân loại ảnh với ResNet-50 pretrained trên ImageNet.
Model chạy trên CPU — inference mỗi ảnh ~1-2 giây.
Push và kiểm tra
git clone https://huggingface.co/spaces/<your-username>/resnet50-demo
cd resnet50-demo
# Copy 3 file vào thư mục
git add app.py requirements.txt README.md
git commit -m "init: resnet50 image classifier"
git push
Sau khi push, vào tab Logs của Space để theo dõi. Build thường mất 2-5 phút (download torch CPU wheel ~200MB, cài gradio). Khi log in dòng cuối Running on public URL hoặc You can now view your Streamlit app, app đã online.
Secrets và environment variables
Space repo là public (ở free tier) — bất kỳ ai cũng xem được code. Không được hard-code API key, token hay credential vào app.py.
HF Spaces cung cấp hai loại biến môi trường, cấu hình tại Settings → Variables and secrets:
| Loại | Hiển thị trong Settings | Log khi build/run | Dùng cho |
|---|---|---|---|
| Variable | Có (public) | Có thể xuất hiện | Config không nhạy cảm: MODEL_NAME, MAX_TOKENS, DEBUG |
| Secret | Không (ẩn sau khi save) | Không log | API key, token: OPENAI_API_KEY, HF_TOKEN |
Đọc trong code
Cả Variable và Secret đều đọc qua os.environ:
import os
from openai import OpenAI
# Secret: không hard-code, đọc từ env
api_key = os.environ.get("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY chưa được set trong Space Secrets")
client = OpenAI(api_key=api_key)
HF_TOKEN — download model private
Khi dùng from_pretrained() để load model từ HF Hub mà model đó private hoặc gated (yêu cầu accept license), cần set HF_TOKEN trong Secrets:
import os
from transformers import AutoTokenizer, AutoModelForCausalLM
# HF Spaces tự đọc HF_TOKEN từ env nếu set trong Secrets
# transformers >= 4.x tự dùng token này khi download
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
Nếu không set HF_TOKEN, download model từ gated repo sẽ fail với 401 Unauthorized hoặc bị rate limit khi anonymous.
Persistent storage
Mặc định, filesystem của Space là ephemeral — file ghi trong lúc runtime (ví dụ log user, kết quả đã cache) bị mất khi Space restart hoặc sau sleep.
Persistent storage (paid)
HF Spaces có tính năng Persistent Storage (mount disk) dạng trả phí, cấu hình tại Settings → Persistent storage. Disk được mount vào /data bên trong container.
Workaround miễn phí: HF Datasets làm storage
Nếu cần lưu data giữa các session mà không muốn trả phí persistent disk, dùng HF Datasets repo như một "database đơn giản" qua thư viện huggingface_hub:
import os
from huggingface_hub import CommitOperationAdd, HfApi
api = HfApi(token=os.environ["HF_TOKEN"])
def save_feedback(user_input: str, model_output: str, rating: int):
"""Ghi feedback vào HF Dataset repo."""
# Append vào file CSV
content = f'"{user_input}","{model_output}",{rating}\n'
api.upload_file(
path_or_fileobj=content.encode(),
path_in_repo="feedback.csv",
repo_id="<username>/my-feedback-dataset",
repo_type="dataset",
commit_message="add feedback",
)
Cách này có giới hạn: write operation chậm (~1-2s mỗi lần commit), không phù hợp ghi nhiều request đồng thời. Chỉ dùng cho feedback form, logging không critical.
Hardware tiers
Upgrade hardware tại Settings → Hardware. Tính tiền theo giờ thực sự sử dụng (không tính giờ Space đang sleep).
| Tier | Specs | Giá | Dùng cho |
|---|---|---|---|
| CPU Basic | 2 vCPU, 16 GB RAM | Miễn phí | Demo nhỏ, model đã quantize chạy CPU |
| CPU Upgrade | 8 vCPU, 32 GB RAM | ~$0.03/h | App cần nhiều CPU hơn, inference song song |
| T4 Small | T4 GPU 16 GB VRAM, 4 vCPU, 15 GB RAM | ~$0.40/h | SLM 7B với 4-bit quantization (llama.cpp, bitsandbytes) |
| T4 Medium | T4 GPU 16 GB VRAM, 8 vCPU, 30 GB RAM | ~$0.60/h | Model 13B quantize hoặc pipeline inference nặng |
| A10G Small | A10G 24 GB VRAM, 4 vCPU, 15 GB RAM | ~$1.05/h | Model 13-30B, image generation (SD) |
| A100 Large | A100 80 GB VRAM, 12 vCPU, 142 GB RAM | ~$4.13/h | Fine-tuning nhỏ, model 70B |
Giá trên tính đến Q2 2025, có thể thay đổi. Kiểm tra trang https://huggingface.co/pricing trước khi dùng.
Sleep when inactive
Free CPU Space tự sleep sau 48 giờ không có request. Space paid cũng có thể cấu hình sleep để tiết kiệm chi phí — vào Settings → Sleep time. Khi Space sleep, billing dừng; khi có request mới, Space wake up (cold start ~30-60 giây trên CPU, lâu hơn trên GPU).
Limits và gotchas
1. Build timeout 1 giờ
Nếu pip install mất hơn 1 giờ (thường do pytorch + CUDA), build bị kill. Giải pháp:
- Dùng CPU-only torch wheel (xem mục 6)
- Chuyển sang Docker SDK để pre-build image với layer cache
- Chỉ cài package thực sự cần — tránh cài cả
transformers[all]khi chỉ cần base
2. Model lớn trong repo → chậm và tốn quota
Không lưu model weights (file .bin, .safetensors hàng GB) trong Space repo. Load runtime từ HF Hub thay vào đó:
from transformers import pipeline
# Load từ HF Hub, tự cache trong /root/.cache/huggingface
# Lần đầu chạy sẽ download, lần sau dùng cache
pipe = pipeline(
"text-classification",
model="distilbert-base-uncased-finetuned-sst-2-english",
)
Nhược điểm: cold start lần đầu phải download, mất thêm thời gian. Với model lớn và Space free, mỗi lần restart đều download lại (cache ephemeral).
3. Anonymous download bị rate limit
Khi Space tải model mà không có HF_TOKEN, HF tính là anonymous request và rate limit chặt hơn. Set HF_TOKEN trong Secrets dù model là public — authenticated request có rate limit cao hơn.
4. Port cố định
HF Spaces chỉ expose port 7860. Không thể bind app ra port khác. Gradio mặc định đúng port này. Streamlit cần cấu hình tường minh:
# Không cần, HF tự truyền args khi start Streamlit
# Nhưng nếu chạy local cần port khác thì:
# streamlit run app.py --server.port 7860
Với Docker SDK, phải EXPOSE 7860 và bind app vào port 7860.
5. Không có outbound internet restrictions (nhưng có giới hạn tốc độ)
Space có thể gọi external API (OpenAI, Anthropic, ...). Tốc độ network outbound trên CPU Basic tương đối chậm — nếu app cần download model lớn khi runtime, dùng GPU tier sẽ có bandwidth tốt hơn.
6. Docker image size
Với Docker SDK, nếu image sau build vượt khoảng 10-15 GB, build có thể fail hoặc rất chậm. Dùng multi-stage build và chỉ copy artifacts cần thiết vào final stage.
Alternatives
Ngoài HF Spaces, có ba lựa chọn phổ biến khác:
- Streamlit Community Cloud (
streamlit.io/cloud) — miễn phí cho app Streamlit, link trực tiếp GitHub repo. Chỉ hỗ trợ Streamlit, không hỗ trợ Gradio hay Docker. - Modal Labs (
modal.com) — serverless GPU, phù hợp cho workload inference nặng hoặc app cần scale linh hoạt hơn. Cần viết decorator@app.functionvà deploy khác với Gradio/Streamlit thông thường. - Render / Railway — general-purpose hosting, hỗ trợ mọi loại Python app. Phù hợp khi muốn deploy FastAPI + Gradio cùng một service (bài 36-37 sẽ đề cập chi tiết).
HF Spaces ưu điểm rõ ở điểm không cần cấu hình infrastructure, phù hợp nhất khi app là pure demo ML và không cần custom domain hay scale phức tạp.
Tóm tắt
- ✅ Space = git repo, push code = deploy — không cần cấu hình server
- ✅
README.mdYAML frontmatter bắt buộc:sdk,sdk_version,app_file - ✅ File > 10MB dùng git-lfs; model lớn load runtime từ HF Hub thay vì lưu trong repo
- ✅ API key và token — set trong Secrets, đọc qua
os.environ, không hard-code - ✅
HF_TOKENtrong Secrets để tránh rate limit khi download model từ Hub - ✅ Free tier: CPU 2 vCPU / 16 GB RAM, sleep sau 48h không request; T4 Small ($0.40/h) đủ cho SLM 7B 4-bit
- ✅ Build timeout 1 giờ — dùng CPU-only torch wheel để build nhanh hơn
- ✅ Persistent storage mặc định ephemeral; workaround miễn phí là dùng HF Datasets repo
