# Kontribusi

Transformers mendukung banyak metode kuantisasi seperti QLoRA, GPTQ, LLM.int8, dan AWQ. Namun, masih ada banyak pendekatan kuantisasi lain yang belum terintegrasi. Untuk memudahkan penambahan dan penggunaan metode kuantisasi ini dengan Transformers, gunakan kelas [HfQuantizer](/docs/transformers/main/id/main_classes/quantization#transformers.quantizers.HfQuantizer). [HfQuantizer](/docs/transformers/main/id/main_classes/quantization#transformers.quantizers.HfQuantizer) dirancang sebagai kelas helper internal untuk menambahkan metode kuantisasi, bukan sesuatu yang diterapkan ke setiap modul PyTorch.

Panduan ini akan menunjukkan cara mengintegrasikan metode kuantisasi baru dengan [HfQuantizer](/docs/transformers/main/id/main_classes/quantization#transformers.quantizers.HfQuantizer).

## Persyaratan

Sebelum mengintegrasikan metode kuantisasi baru ke dalam Transformers, pastikan metode tersebut memenuhi persyaratan berikut. Hanya metode kuantisasi yang dapat dijalankan dengan modul PyTorch yang didukung.

- Metode kuantisasi tersedia melalui paket Python yang dapat diinstal via pip (tidak masalah jika Anda hanya dapat menginstal paket dari sumber). Idealnya, kernel yang sudah dikompilasi sebelumnya disertakan dalam paket pip.
- Metode ini dapat dijalankan pada perangkat keras yang umum digunakan (CPU, GPU, dll.).
- Metode ini dibungkus dalam [nn.Module](https://pytorch.org/docs/stable/generated/torch.nn.Module.html) (`~bitsandbytes.nn.Linear8bitLt`, `~bitsandbytes.nn.Linear4bit`), dan lapisan linear terkuantisasi harus memiliki definisi berikut.

  ```py
  class Linear4bit(nn.Module):
      def __init__(self, ...):
          ...

      def forward(self, x):
          return my_4bit_kernel(x, self.weight, self.bias)
  ```

  Dengan cara ini, model Transformers dapat dikuantisasi dengan mudah dengan mengganti instance [nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html) dengan kelas target.

- Metode kuantisasi harus dapat diserialisasi. Anda dapat menyimpan bobot terkuantisasi secara lokal atau mengirimkannya ke Hub.
- Pastikan paket yang berisi kernel/primitif kuantisasi sudah stabil (tidak ada perubahan yang sering merusak kompatibilitas).

Beberapa metode kuantisasi mungkin memerlukan "pre-kuantisasi" model melalui kalibrasi data (AWQ). Dalam kasus ini, kami lebih memilih untuk hanya mendukung inferensi di Transformers dan membiarkan pustaka pihak ketiga yang dipelihara oleh komunitas ML menangani kuantisasi model itu sendiri.

## Buat kelas HFQuantizer baru

0. Titik awal terbaik adalah dengan melihat metode kuantisasi lain seperti Finegrained Fp8. Anda harus memperbarui atau membuat tiga file secara total: [file konfigurasi](https://github.com/huggingface/transformers/blob/main/src/transformers/utils/quantization_config.py), [file integrasi](https://github.com/huggingface/transformers/blob/main/src/transformers/integrations/finegrained_fp8.py), dan [file kuantizer](https://github.com/huggingface/transformers/blob/main/src/transformers/quantizers/quantizer_finegrained_fp8.py).

1. Buat kelas konfigurasi kuantisasi baru di dalam [src/transformers/utils/quantization_config.py](https://github.com/huggingface/transformers/blob/abbffc4525566a48a9733639797c812301218b83/src/transformers/utils/quantization_config.py). Tambahkan konfigurasi kuantisasi baru ke [\_import_structure](https://github.com/huggingface/transformers/blob/abbffc4525566a48a9733639797c812301218b83/src/transformers/__init__.py#L1088) di dalam file [src/transformers/\_\_init\_\_.py](https://github.com/huggingface/transformers/blob/abbffc4525566a48a9733639797c812301218b83/src/transformers/__init__.py) Transformers.

2. Buat file baru di dalam [src/transformers/quantizers/](https://github.com/huggingface/transformers/tree/abbffc4525566a48a9733639797c812301218b83/src/transformers/quantizers) bernama `quantizer_your_method.py`, dan buat file tersebut mewarisi dari [`~quantizers.HfQuantizer]. Pastikan untuk menambahkan quantizer dan quantization config baru ke dalam auto-mapping quantization di [src/transformers/quantizers/auto.py](https://github.com/huggingface/transformers/blob/abbffc4525566a48a9733639797c812301218b83/src/transformers/quantizers/auto.py).

3. Definisikan atribut kelas dan metode properti berikut untuk metode kuantisasi Anda:

   - `requires_calibration`: Apakah metode kuantisasi memerlukan proses kalibrasi data. Jika disetel ke `True`, Anda hanya dapat mendukung inferensi (dengan bobot terkuantisasi) dan bukan inferensi serta kuantisasi.
   - `is_serializable`: Metode properti untuk menentukan apakah metode tersebut dapat diserialisasi atau tidak.
   - `is_trainable`: Metode properti untuk menentukan apakah Anda dapat melakukan fine-tuning model di atas metode kuantisasi (dengan atau tanpa pendekatan PEFT).

4. Tulis metode `validate_environment` dan `update_dtype`. Metode-metode ini dipanggil sebelum membuat model terkuantisasi untuk memastikan pengguna menggunakan konfigurasi yang tepat. Lihat implementasi pada quantizer lain sebagai contoh.

5. Tulis metode `_process_model_before_weight_loading`. Di Transformers, model terkuantisasi diinisialisasi terlebih dahulu pada perangkat `"meta"` sebelum memuat bobot. Artinya, metode `_process_model_before_weight_loading` bertugas memanipulasi kerangka model untuk mengganti beberapa modul ([nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html)) dengan modul target (modul kuantisasi).

Anda dapat mendefinisikan logika penggantian modul atau metode utilitas lainnya dengan membuat file baru di [transformers/src/integrations/](https://github.com/huggingface/transformers/tree/abbffc4525566a48a9733639797c812301218b83/src/transformers/integrations) dan mengekspos metode yang relevan di file `__init__.py` folder tersebut.

6. Tambahkan metode `get_quantize_ops` ke kelas quantizer jika kuantisasi mendukung kuantisasi on the fly. Di transformers, kami materialisasi setiap tensor dan menerapkan serangkaian operasi yang berbeda pada tensor tersebut. Dalam kasus kami, operasi kuantisasi terjadi di akhir. Anda perlu membuat `XXXQuantize`, yaitu subclass dari `ConversionOps`, dan menambahkan metode `convert`. Di dalam metode `convert`, Anda perlu mengkuantisasi bobot dan mengembalikan dictionary berisi parameter yang telah dikuantisasi.

7. Tambahkan metode `get_weight_conversions` ke kelas quantizer jika kuantisasi mendukung pemuatan bobot yang sudah dikuantisasi. Di transformers, kita dapat mengumpulkan beberapa tensor dan menerapkan operasi pada tensor tersebut. Hal ini sangat berguna ketika kita memiliki tensor di checkpoint yang perlu dikelompokkan kembali untuk membuat ulang tensor yang telah dikuantisasi.

8. Tulis metode `_process_model_after_weight_loading` jika diperlukan. Metode ini memungkinkan implementasi fitur tambahan yang memerlukan manipulasi model setelah pemuatan bobot.

9. Dokumentasikan semuanya! Pastikan metode kuantisasi Anda terdokumentasi dengan menambahkan file baru di bawah `docs/source/en/quantization`.

10. Anda sebaiknya menambahkan tes dengan menambahkan paket tersebut ke Dockerfile nightly kami di dalam `docker/transformers-quantization-latest-gpu`, lalu menambahkan file tes baru di `tests/quantization/xxx`. Silakan periksa metode kuantisasi yang sudah ada untuk melihat bagaimana implementasinya.

## Ikhtisar file

| File                                         | Tujuan                                                                                          |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `utils/quantization_config.py`               | Definisikan `YourMethodConfig` yang mewarisi dari `QuantizationConfigMixin`                              |
| `quantizers/quantizer_your_method.py`        | Implementasikan `YourMethodHfQuantizer` yang mewarisi dari `HfQuantizer`                                  |
| `integrations/your_method.py`                | Implement subclass `ConversionOps` dan fungsi bantu                                        |
| `quantizers/auto.py`                         | Daftarkan quantizer dan config di `AUTO_QUANTIZER_MAPPING` dan `AUTO_QUANTIZATION_CONFIG_MAPPING` |
| `docs/source/en/quantization/your_method.md` | Dokumentasikan penggunaan untuk pengguna                                                                         |
| `tests/quantization/your_method/`            | Tambahkan uji integrasi                                                                            |

## Memahami `get_quantize_ops` vs `get_weight_conversions`

Dua metode ini menangani skenario yang berbeda untuk memuat bobot. Memahami kapan harus menggunakan masing-masing metode sangat penting.

### `get_quantize_ops` — Kuantisasi secara langsung

Gunakan ini saat memuat **checkpoint non-kuantisasi** (misalnya, bobot float16/bfloat16) dan melakukan kuantisasi saat pemuatan.

```text
Checkpoint: model.safetensors (float16 weights for example)
     ↓
get_quantize_ops → YourQuantize.convert()
     ↓
Result: Quantized weights in memory
```

Metode `convert` menerima satu tensor pada satu waktu, melakukan kuantisasi, dan dapat mengembalikan kamus parameter terkuantisasi, misalnya:

```py
class YourQuantize(ConversionOps):
    def convert(self, input_dict, model, full_layer_name, missing_keys, **kwargs):
        # input_dict = {"layer.weight": <float16 tensor>}
        value = list(input_dict.values())[0]
        module, tensor_name = get_module_from_name(model, full_layer_name)

        # Quantize and assign
        quantized, scale, zero_point = your_quantize_fn(value)
        return {full_layer_name: quantized, full_layer_name + ".scale": scale, full_layer_name + ".zero_point": zero_point}
```

### `get_weight_conversions` — Muat checkpoint yang sudah dikuantisasi

Gunakan ini saat memuat **checkpoint yang sudah dikuantisasi** di mana bobot terkuantisasi disimpan sebagai beberapa komponen terpisah (seperti data, skala, dan titik nol), dan komponen-komponen ini perlu digabungkan menjadi satu tensor saat dimuat. Tidak semua metode kuantisasi memerlukan langkah rekonstruksi ini: misalnya, beberapa metode seperti FP8 hanya memuat bobot dan skala apa adanya, tanpa menggabungkannya. Metode lain, seperti torchao, memang memerlukan perakitan ulang tensor terkuantisasi dari beberapa komponen tersimpannya.

```text
Checkpoint: model.safetensors (quantized components)
  - layer._weight_qdata
  - layer._weight_scale
  - layer._weight_zero_point
     ↓
get_weight_conversions → WeightConverter + YourDeserialize.convert()
     ↓
Result: Reconstructed quantized tensor → layer.weight
```

`WeightConverter` mengumpulkan tensor terkait berdasarkan `source_patterns`, lalu meneruskannya ke metode `convert` Anda:

```py
def get_weight_conversions(self):
    if self.pre_quantized:
        return [
            WeightConverter(
                source_patterns=["_weight_qdata", "_weight_scale", "_weight_zero_point"],
                target_patterns="weight",
                operations=[YourDeserialize(self)],
            ),
        ]
    return []

class YourDeserialize(ConversionOps):
    def convert(self, input_dict, model, full_layer_name, **kwargs):
        # input_dict contains all collected tensors
        # Reconstruct the quantized tensor from components
        reconstructed_tensor = reconstruct_from_components(input_dict)
        return {full_layer_name: reconstructed_tensor}
```

