Hub Python Library documentation
Integrasikan framework ML apa pun dengan Hub
Integrasikan framework ML apa pun dengan Hub
Hugging Face Hub memudahkan hosting dan berbagi model dengan komunitas. Hub mendukung puluhan pustaka dalam ekosistem Open Source. Kami terus bekerja untuk memperluas dukungan ini guna mendorong kemajuan Machine Learning kolaboratif. Pustaka huggingface_hub memainkan peran kunci dalam proses ini, memungkinkan skrip Python mana pun untuk dengan mudah mendorong dan memuat file.
Ada empat cara utama untuk mengintegrasikan pustaka dengan Hub:
- Push to Hub: implementasikan metode untuk mengunggah model ke Hub. Ini mencakup bobot model, serta model card dan informasi atau data lain yang relevan yang diperlukan untuk menjalankan model (misalnya, log pelatihan). Metode ini sering disebut sebagai
push_to_hub(). - Unduh dari Hub: implementasikan metode untuk memuat model dari Hub. Metode ini harus mengunduh konfigurasi/berat model dan memuat model. Metode ini sering disebut
from_pretrainedatauload_from_hub(). - Widget: menampilkan widget di halaman pendaratan model Anda di Hub. Ini memungkinkan pengguna untuk dengan cepat mencoba model dari browser.
Dalam panduan ini, kami akan berfokus pada dua topik pertama. Kami akan menyajikan dua pendekatan utama yang dapat Anda gunakan untuk mengintegrasikan sebuah pustaka, beserta kelebihan dan kekurangannya. Semua hal dirangkum di akhir panduan untuk membantu Anda memilih di antara keduanya. Harap diingat bahwa ini hanyalah pedoman yang dapat Anda sesuaikan dengan kebutuhan Anda.
Jika Anda tertarik dengan Inference dan Widgets, Anda dapat mengikuti panduan ini. Dalam kedua kasus tersebut, Anda dapat menghubungi kami jika Anda mengintegrasikan pustaka dengan Hub dan ingin terdaftar dalam dokumentasi kami.
Pendekatan yang fleksibel: helper
Pendekatan pertama untuk mengintegrasikan pustaka ke Hub adalah dengan mengimplementasikan metode push_to_hub dan from_pretrained secara mandiri. Hal ini memberikan fleksibilitas penuh atas file yang perlu diunggah/diunduh dan cara menangani input yang spesifik untuk framework Anda. Anda dapat merujuk pada panduan upload files dan download files untuk mempelajari lebih lanjut tentang cara melakukannya. Misalnya, integrasi FastAI diimplementasikan dengan cara ini (lihat push_to_hub_fastai() dan from_pretrained_fastai()).
Implementasi dapat berbeda antar pustaka, tetapi alur kerja sering kali serupa.
from_pretrained
Berikut adalah tampilan umum metode from_pretrained:
def from_pretrained(model_id: str) -> MyModelClass:
# Download model from Hub
cached_model = hf_hub_download(
repo_id=model_id,
filename="model.pkl",
library_name="fastai",
library_version=get_fastai_version(),
)
# Load model
return load_model(cached_model)push_to_hub
Metode push_to_hub sering kali memerlukan sedikit kompleksitas tambahan untuk menangani pembuatan repo, menghasilkan model card, dan menyimpan weights.
Pendekatan yang umum adalah menyimpan semua file ini di folder sementara, mengunggahnya, lalu menghapusnya.
def push_to_hub(model: MyModelClass, repo_name: str) -> None:
api = HfApi()
# Create repo if not existing yet and get the associated repo_id
repo_id = api.create_repo(repo_name, exist_ok=True)
# Save all files in a temporary directory and push them in a single commit
with TemporaryDirectory() as tmpdir:
tmpdir = Path(tmpdir)
# Save weights
save_model(model, tmpdir / "model.safetensors")
# Generate model card
card = generate_model_card(model)
(tmpdir / "README.md").write_text(card)
# Save logs
# Save figures
# Save evaluation metrics
# ...
# Push to hub
return api.upload_folder(repo_id=repo_id, folder_path=tmpdir)Tentu saja, ini hanyalah contoh. Jika Anda tertarik dengan manipulasi yang lebih kompleks (menghapus file jarak jauh, mengunggah bobot secara langsung, menyimpan bobot secara lokal, dll.), silakan merujuk ke panduan upload files.
Keterbatasan
Meskipun fleksibel, pendekatan ini memiliki beberapa kekurangan, terutama dalam hal pemeliharaan. Pengguna Hugging Face sering kali
terbiasa dengan fitur tambahan saat bekerja dengan huggingface_hub. Misalnya, saat memuat file dari Hub,
umumnya disediakan parameter seperti:
token: untuk mengunduh dari repositori privatrevision: untuk mengunduh dari cabang tertentucache_dir: untuk meng-cache file di direktori tertentuforce_download/local_files_only: untuk menggunakan ulang cache atau tidakproxies: konfigurasikan sesi HTTP
Saat mendorong model, parameter serupa didukung:
commit_message: pesan commit kustomprivate: buat repositori privat jika tidak adacreate_pr: buat PR alih-alih push kemainbranch: push ke cabang alih-alih cabangmainallow_patterns/ignore_patterns: memfilter file mana yang akan diunggahtoken- …
Semua parameter ini dapat ditambahkan ke implementasi yang kita lihat di atas dan diteruskan ke metode huggingface_hub.
Namun, jika sebuah parameter berubah atau fitur baru ditambahkan, Anda perlu memperbarui paket Anda. Mendukung parameter-parameter tersebut juga berarti ada lebih banyak dokumentasi yang harus Anda rawat. Untuk melihat cara memitigasi keterbatasan ini, mari kita lanjut ke bagian berikutnya warisan kelas.
Pendekatan yang lebih kompleks: pewarisan kelas
Seperti yang kita lihat di atas, ada dua metode utama yang perlu disertakan di pustaka Anda untuk mengintegrasikannya dengan Hub: mengunggah file (push_to_hub) dan mengunduh file (from_pretrained). Anda dapat mengimplementasikan metode tersebut sendiri, tetapi hal ini memiliki beberapa catatan. Untuk mengatasi hal ini, huggingface_hub menyediakan alat yang menggunakan pewarisan kelas. Mari kita lihat bagaimana cara kerjanya!
Dalam banyak kasus, sebuah pustaka sudah mengimplementasikan modelnya menggunakan kelas Python. Kelas tersebut berisi properti model serta metode untuk memuat, menjalankan, melatih, dan mengevaluasinya. Pendekatan kami adalah memperluas kelas ini untuk mencakup fitur unggah dan unduh menggunakan mixin. Mixin adalah kelas yang dimaksudkan untuk memperluas kelas yang sudah ada dengan seperangkat fitur spesifik menggunakan pewarisan ganda. huggingface_hub menyediakan mixin-nya sendiri, yaitu ModelHubMixin. Kuncinya di sini adalah memahami perilakunya dan cara untuk menyesuaikannya.
Kelas ModelHubMixin mengimplementasikan 3 metode publik (push_to_hub, save_pretrained dan from_pretrained). Metode-metode tersebut adalah yang akan dipanggil oleh pengguna Anda untuk memuat/menyimpan model dengan pustaka Anda. ModelHubMixin juga mendefinisikan 2 metode privat (_save_pretrained dan _from_pretrained). Metode-metode inilah yang harus Anda implementasikan. Jadi, untuk mengintegrasikan pustaka Anda, Anda harus:
- Buat kelas Model Anda mewarisi dari ModelHubMixin.
- Implementasikan metode privat berikut:
- _save_pretrained(): metode yang menerima path ke direktori sebagai input dan menyimpan model ke direktori tersebut. Anda harus menulis semua logika untuk menumpahkan model Anda di metode ini: model card, bobot model, file konfigurasi, log pelatihan, dan gambar. Semua informasi yang relevan untuk model ini harus ditangani oleh metode ini. Model Cards sangat penting untuk mendeskripsikan model Anda. Lihat panduan implementasi kami untuk detail lebih lanjut.
- _from_pretrained(): metode kelas yang menerima
model_idsebagai input dan mengembalikan model yang telah diinstansiasi. Metode ini harus mengunduh file yang relevan dan memuatnya.
- Anda sudah selesai!
Keuntungan menggunakan ModelHubMixin adalah bahwa begitu Anda mengurus serialisasi/pemuatan file, Anda siap untuk memulai. Anda tidak perlu khawatir tentang hal-hal seperti pembuatan repo, commit, PR, atau revisi. ModelHubMixin juga memastikan metode publik terdokumentasi dan berannotasi tipe, dan Anda akan dapat melihat jumlah unduhan model Anda di Hub. Semua ini ditangani oleh ModelHubMixin dan tersedia untuk pengguna Anda.
Contoh konkret: PyTorch
Contoh yang baik dari apa yang kita lihat di atas adalah PyTorchModelHubMixin, integrasi kami untuk framework PyTorch. Ini adalah integrasi yang siap digunakan.
Bagaimana cara menggunakannya?
Berikut adalah cara pengguna memuat/menyimpan model PyTorch dari/ke Hub:
>>> import torch
>>> import torch.nn as nn
>>> from huggingface_hub import PyTorchModelHubMixin
# Define your Pytorch model exactly the same way you are used to
>>> class MyModel(
... nn.Module,
... PyTorchModelHubMixin, # multiple inheritance
... library_name="keras-nlp",
... tags=["keras"],
... repo_url="https://github.com/keras-team/keras-nlp",
... docs_url="https://keras.io/keras_nlp/",
... # ^ optional metadata to generate model card
... ):
... def __init__(self, hidden_size: int = 512, vocab_size: int = 30000, output_size: int = 4):
... super().__init__()
... self.param = nn.Parameter(torch.rand(hidden_size, vocab_size))
... self.linear = nn.Linear(output_size, vocab_size)
... def forward(self, x):
... return self.linear(x + self.param)
# 1. Create model
>>> model = MyModel(hidden_size=128)
# Config is automatically created based on input + default values
>>> model.param.shape[0]
128
# 2. (optional) Save model to local directory
>>> model.save_pretrained("path/to/my-awesome-model")
# 3. Push model weights to the Hub
>>> model.push_to_hub("my-awesome-model")
# 4. Initialize model from the Hub => config has been preserved
>>> model = MyModel.from_pretrained("username/my-awesome-model")
>>> model.param.shape[0]
128
# Model card has been correctly populated
>>> from huggingface_hub import ModelCard
>>> card = ModelCard.load("username/my-awesome-model")
>>> card.data.tags
["keras", "pytorch_model_hub_mixin", "model_hub_mixin"]
>>> card.data.library_name
"keras-nlp"Implementasi
Implementasinya sebenarnya sangat sederhana, dan implementasi lengkapnya dapat ditemukan di sini.
- Pertama, wariskan kelas Anda dari
ModelHubMixin:
from huggingface_hub import ModelHubMixin
class PyTorchModelHubMixin(ModelHubMixin):
(...)- Implementasikan metode
_save_pretrained:
from huggingface_hub import ModelHubMixin
class PyTorchModelHubMixin(ModelHubMixin):
(...)
def _save_pretrained(self, save_directory: Path) -> None:
"""Save weights from a Pytorch model to a local directory."""
save_model_as_safetensor(self.module, str(save_directory / SAFETENSORS_SINGLE_FILE))
- Implementasikan metode
_from_pretrained:
class PyTorchModelHubMixin(ModelHubMixin):
(...)
@classmethod # Must be a classmethod!
def _from_pretrained(
cls,
*,
model_id: str,
revision: str,
cache_dir: str,
force_download: bool,
local_files_only: bool,
token: Union[str, bool, None],
map_location: str = "cpu", # additional argument
strict: bool = False, # additional argument
**model_kwargs,
):
"""Load Pytorch pretrained weights and return the loaded model."""
model = cls(**model_kwargs)
if os.path.isdir(model_id):
print("Loading weights from local directory")
model_file = os.path.join(model_id, SAFETENSORS_SINGLE_FILE)
return cls._load_as_safetensor(model, model_file, map_location, strict)
model_file = hf_hub_download(
repo_id=model_id,
filename=SAFETENSORS_SINGLE_FILE,
revision=revision,
cache_dir=cache_dir,
force_download=force_download,
token=token,
local_files_only=local_files_only,
)
return cls._load_as_safetensor(model, model_file, map_location, strict)Dan selesai! Perpustakaan Anda kini memungkinkan pengguna untuk mengunggah dan mengunduh file ke dan dari Hub.
Penggunaan lanjutan
Pada bagian di atas, kita telah membahas secara singkat cara kerja ModelHubMixin. Pada bagian ini, kita akan melihat beberapa fitur lanjutan yang dapat meningkatkan integrasi pustaka Anda dengan Hugging Face Hub.
Kartu model
ModelHubMixin membuat kartu model untuk Anda. Kartu model adalah file yang menyertai model dan menyediakan informasi penting tentang model tersebut. Di balik layar, kartu model adalah file Markdown sederhana dengan metadata tambahan. Kartu model sangat penting untuk keterdapatannya, reproduktibilitas, dan berbagi! Lihat panduan Kartu Model untuk detail lebih lanjut.
Membuat kartu model secara semi-otomatis adalah cara yang baik untuk memastikan bahwa semua model yang diunggah dengan pustaka Anda berbagi metadata umum: library_name, tags, license, pipeline_tag, dll. Hal ini membuat semua model yang didukung oleh pustaka Anda mudah dicari di Hub dan menyediakan beberapa tautan sumber daya bagi pengguna yang mendarat di Hub. Anda dapat mendefinisikan metadata secara langsung saat mewarisi dari ModelHubMixin:
class UniDepthV1(
nn.Module,
PyTorchModelHubMixin,
library_name="unidepth",
repo_url="https://github.com/lpiccinelli-eth/UniDepth",
docs_url=...,
pipeline_tag="depth-estimation",
license="cc-by-nc-4.0",
tags=["monocular-metric-depth-estimation", "arxiv:1234.56789"]
):
...Secara default, kartu model generik akan dibuat dengan informasi yang Anda berikan (contoh: pyp1/VoiceCraft_giga830M). Namun, Anda juga dapat mendefinisikan template kartu model Anda sendiri!
Pada contoh ini, semua model yang diunggah dengan kelas VoiceCraft akan secara otomatis menyertakan bagian sitasi dan detail lisensi. Untuk detail lebih lanjut tentang cara mendefinisikan templat kartu model, silakan periksa panduan Model Cards.
MODEL_CARD_TEMPLATE = """
---
# For reference on model card metadata, see the spec: https://github.com/huggingface/hub-docs/blob/main/modelcard.md?plain=1
# Doc / guide: https://huggingface.co/docs/hub/model-cards
{{ card_data }}
---
This is a VoiceCraft model. For more details, please check out the official Github repo: https://github.com/jasonppy/VoiceCraft. This model is shared under a Attribution-NonCommercial-ShareAlike 4.0 International license.
## Citation
@article{peng2024voicecraft,
author = {Peng, Puyuan and Huang, Po-Yao and Li, Daniel and Mohamed, Abdelrahman and Harwath, David},
title = {VoiceCraft: Zero-Shot Speech Editing and Text-to-Speech in the Wild},
journal = {arXiv},
year = {2024},
}
"""
class VoiceCraft(
nn.Module,
PyTorchModelHubMixin,
library_name="voicecraft",
model_card_template=MODEL_CARD_TEMPLATE,
...
):
...Terakhir, jika Anda ingin memperluas proses pembuatan kartu model dengan nilai dinamis, Anda dapat menimpa metode generate_model_card():
from huggingface_hub import ModelCard, PyTorchModelHubMixin
class UniDepthV1(nn.Module, PyTorchModelHubMixin, ...):
(...)
def generate_model_card(self, *args, **kwargs) -> ModelCard:
card = super().generate_model_card(*args, **kwargs)
card.data.metrics = ... # add metrics to the metadata
card.text += ... # append section to the modelcard
return cardKonfigurasi
ModelHubMixin menangani konfigurasi model untuk Anda. Ia secara otomatis memeriksa nilai input saat Anda menginstansiasi model dan memserialisasikannya ke dalam file config.json. Hal ini memberikan 2 manfaat:
- Pengguna akan dapat memuat ulang model dengan parameter yang persis sama dengan Anda.
- Memiliki file
config.jsonsecara otomatis mengaktifkan analitik di Hub (yaitu jumlah “downloads”).
Namun, bagaimana cara kerjanya dalam praktiknya? Beberapa aturan membuat proses ini semulus mungkin dari sudut pandang pengguna:
- jika metode
__init__Anda mengharapkan inputconfig, input tersebut akan disimpan secara otomatis di repo sebagaiconfig.json. - jika parameter input
configdiannotasi dengan tipe dataclass (mis.config: Optional[MyConfigClass] = None), maka nilaiconfigakan dideserialisasi dengan benar untuk Anda. - semua nilai yang diberikan saat inisialisasi juga akan disimpan dalam file konfigurasi. Artinya, Anda tidak harus mengharapkan input
configuntuk dapat memanfaatkannya.
Contoh:
class MyModel(ModelHubMixin):
def __init__(value: str, size: int = 3):
self.value = value
self.size = size
(...) # implement _save_pretrained / _from_pretrained
model = MyModel(value="my_value")
model.save_pretrained(...)
# config.json contains passed and default values
{"value": "my_value", "size": 3}Bagaimana jika sebuah nilai tidak dapat diserialisasi sebagai JSON? Secara default, nilai tersebut akan diabaikan saat menyimpan file konfigurasi. Namun, dalam beberapa kasus, pustaka Anda sudah mengharapkan objek kustom sebagai input yang tidak dapat diserialisasi, dan Anda tidak ingin memperbarui logika internal Anda untuk mengubah tipenya. Tenang! Anda dapat meneruskan encoder/decoder kustom untuk tipe apa pun saat mewarisi dari ModelHubMixin. Ini sedikit lebih banyak kerja, tetapi memastikan logika internal Anda tetap utuh saat mengintegrasikan pustaka Anda dengan Hub.
Berikut adalah contoh konkret di mana sebuah kelas mengharapkan konfigurasi argparse.Namespace sebagai input:
class VoiceCraft(nn.Module):
def __init__(self, args):
self.pattern = self.args.pattern
self.hidden_size = self.args.hidden_size
...Salah satu solusinya adalah memperbarui tanda tangan __init__ menjadi def __init__(self, pattern: str, hidden_size: int) dan memperbarui semua cuplikan kode yang menginstansiasi kelas Anda. Ini adalah cara yang sepenuhnya valid untuk memperbaikinya, tetapi mungkin merusak aplikasi hilir yang menggunakan pustaka Anda.
Solusi lain adalah menyediakan encoder/decoder sederhana untuk mengonversi argparse.Namespace menjadi dictionary.
from argparse import Namespace
class VoiceCraft(
nn.Module,
PyTorchModelHubMixin, # inherit from mixin
coders={
Namespace : (
lambda x: vars(x), # Encoder: how to convert a `Namespace` to a valid jsonable value?
lambda data: Namespace(**data), # Decoder: how to reconstruct a `Namespace` from a dictionary?
)
}
):
def __init__(self, args: Namespace): # annotate `args`
self.pattern = self.args.pattern
self.hidden_size = self.args.hidden_size
...Pada cuplikan di atas, baik logika internal maupun tanda tangan __init__ dari kelas tersebut tidak berubah. Ini berarti semua cuplikan kode yang ada untuk pustaka Anda akan terus berfungsi. Untuk mencapai hal ini, kami harus:
- Warisi dari mixin (
PytorchModelHubMixindalam kasus ini). - Lewatkan parameter
codersdalam pewarisan. Ini adalah kamus di mana kuncinya adalah tipe kustom yang ingin Anda proses. Nilainya adalah tuple(encoder, decoder).- Encoder mengharapkan objek dari tipe yang ditentukan sebagai input dan mengembalikan nilai yang dapat di-json-kan. Ini akan digunakan saat menyimpan model dengan
save_pretrained. - Decoder mengharapkan data mentah (biasanya berupa kamus) sebagai input dan merekonstruksi objek awal. Ini akan digunakan saat memuat model dengan
from_pretrained.
- Encoder mengharapkan objek dari tipe yang ditentukan sebagai input dan mengembalikan nilai yang dapat di-json-kan. Ini akan digunakan saat menyimpan model dengan
- Tambahkan anotasi tipe pada tanda tangan
__init__. Hal ini penting agar mixin mengetahui tipe yang diharapkan oleh kelas dan, dengan demikian, decoder mana yang harus digunakan.
Demi kesederhanaan, fungsi encoder/decoder dalam contoh di atas tidak dirancang secara robust. Untuk implementasi yang konkret, Anda kemungkinan besar harus menangani kasus-kasus tepi (corner cases) dengan tepat.
Perbandingan cepat
Mari kita ringkas dengan cepat dua pendekatan yang kita lihat beserta kelebihan dan kekurangannya. Tabel di bawah ini hanya bersifat indikatif. Framework Anda mungkin memiliki beberapa kekhasan yang perlu Anda tangani. Panduan ini hanya ada untuk memberikan pedoman dan ide tentang cara menangani integrasi. Dalam hal apa pun, jangan ragu untuk menghubungi kami jika Anda memiliki pertanyaan!
| Integrasi | Menggunakan helper | Menggunakan ModelHubMixin |
|---|---|---|
| Pengalaman pengguna | model = load_from_hub(...)push_to_hub(model, ...) | model = MyModel.from_pretrained(...)model.push_to_hub(...) |
| Fleksibilitas | Sangat fleksibel. Anda sepenuhnya mengontrol implementasinya. | Kurang fleksibel. Framework Anda harus memiliki kelas model. |
| Pemeliharaan | Lebih banyak pemeliharaan untuk menambahkan dukungan konfigurasi, dan fitur baru. Mungkin juga memerlukan perbaikan masalah yang dilaporkan oleh pengguna. | Perawatan lebih sedikit karena sebagian besar interaksi dengan Hub diimplementasikan di huggingface_hub. |
| Dokumentasi / Anotasi tipe | Akan ditulis secara manual. | Sebagian ditangani oleh huggingface_hub. |
| Penghitung unduhan | Untuk ditangani secara manual. | Diaktifkan secara default jika kelas memiliki atribut config. |
| Kartu model | Untuk ditangani secara manual | Dihasilkan secara default dengan library_name, tags, dll. |