Hub Python Library documentation

Integrasikan framework ML apa pun dengan Hub

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

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:

  1. 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().
  2. 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_pretrained atau load_from_hub().
  3. 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 privat
  • revision: untuk mengunduh dari cabang tertentu
  • cache_dir: untuk meng-cache file di direktori tertentu
  • force_download/local_files_only: untuk menggunakan ulang cache atau tidak
  • proxies: konfigurasikan sesi HTTP

Saat mendorong model, parameter serupa didukung:

  • commit_message: pesan commit kustom
  • private: buat repositori privat jika tidak ada
  • create_pr: buat PR alih-alih push ke main
  • branch: push ke cabang alih-alih cabang main
  • allow_patterns/ignore_patterns: memfilter file mana yang akan diunggah
  • token
  • …

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:

  1. Buat kelas Model Anda mewarisi dari ModelHubMixin.
  2. 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_id sebagai input dan mengembalikan model yang telah diinstansiasi. Metode ini harus mengunduh file yang relevan dan memuatnya.
  3. 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.

  1. Pertama, wariskan kelas Anda dari ModelHubMixin:
from huggingface_hub import ModelHubMixin

class PyTorchModelHubMixin(ModelHubMixin):
   (...)
  1. 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))
  1. 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 card

Konfigurasi

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:

  1. Pengguna akan dapat memuat ulang model dengan parameter yang persis sama dengan Anda.
  2. Memiliki file config.json secara 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 input config, input tersebut akan disimpan secara otomatis di repo sebagai config.json.
  • jika parameter input config diannotasi dengan tipe dataclass (mis. config: Optional[MyConfigClass] = None), maka nilai config akan dideserialisasi dengan benar untuk Anda.
  • semua nilai yang diberikan saat inisialisasi juga akan disimpan dalam file konfigurasi. Artinya, Anda tidak harus mengharapkan input config untuk 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:

  1. Warisi dari mixin (PytorchModelHubMixin dalam kasus ini).
  2. Lewatkan parameter coders dalam 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.
  3. 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!

IntegrasiMenggunakan helperMenggunakan ModelHubMixin
Pengalaman penggunamodel = load_from_hub(...)
push_to_hub(model, ...)
model = MyModel.from_pretrained(...)
model.push_to_hub(...)
FleksibilitasSangat fleksibel.
Anda sepenuhnya mengontrol implementasinya.
Kurang fleksibel.
Framework Anda harus memiliki kelas model.
PemeliharaanLebih 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 tipeAkan ditulis secara manual.Sebagian ditangani oleh huggingface_hub.
Penghitung unduhanUntuk ditangani secara manual.Diaktifkan secara default jika kelas memiliki atribut config.
Kartu modelUntuk ditangani secara manualDihasilkan secara default dengan library_name, tags, dll.
Update on GitHub