# ModularPipeline

[ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline) mengubah [ModularPipelineBlocks](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks) menjadi pipeline yang dapat dieksekusi, yang memuat model dan melakukan langkah-langkah komputasi yang didefinisikan dalam blok-blok tersebut. Ini adalah antarmuka utama untuk menjalankan pipeline, dan API-nya sangat mirip dengan [DiffusionPipeline](/docs/diffusers/v0.43.0/id/api/pipelines/overview#diffusers.DiffusionPipeline) tetapi dengan beberapa perbedaan utama.

- **Pemmuatan bersifat lazy.** Dengan [DiffusionPipeline](/docs/diffusers/v0.43.0/id/api/pipelines/overview#diffusers.DiffusionPipeline), [from_pretrained()](/docs/diffusers/v0.43.0/id/api/pipelines/overview#diffusers.DiffusionPipeline.from_pretrained) membuat pipeline dan memuat semua model secara bersamaan. Dengan [ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline), pembuatan dan pemmuatan adalah dua langkah terpisah: [from_pretrained()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.from_pretrained) membaca konfigurasi dan mengetahui dari mana setiap komponen harus dimuat, tetapi tidak benar-benar memuat bobot model. Anda memuat model kemudian dengan [load_components()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.load_components), di mana Anda meneruskan argumen pemmuatan seperti `dtype` dan `quantization_config`.

- **Dua cara membuat pipeline.** Anda dapat menggunakan [from_pretrained()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.from_pretrained) dengan repositori model diffusers yang sudah ada — ini secara otomatis memetakan ke blok pipeline default dan kemudian mengonversinya menjadi [ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline) tanpa perlu pengaturan tambahan. Anda dapat memeriksa [modular_pipelines_directory](https://github.com/huggingface/diffusers/tree/main/src/diffusers/modular_pipelines) untuk melihat model mana yang saat ini didukung. Anda juga dapat merakit pipeline Anda sendiri dari [ModularPipelineBlocks](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks) dan mengonversinya dengan metode [init_pipeline()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks.init_pipeline) (lihat [Membuat pipeline](#creating-a-pipeline) untuk detail lebih lanjut).

- **Menjalankan pipeline-nya sama saja.** Setelah dimuat, Anda memanggil pipeline dengan argumen yang sama seperti biasa. Satu [ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline) dapat mendukung beberapa alur kerja (teks-ke-gambar, gambar-ke-gambar, inpainting, dll.) ketika blok pipeline menggunakan [`AutoPipelineBlocks`](./auto_pipeline_blocks) untuk secara otomatis memilih alur kerja berdasarkan input Anda.

Berikut adalah contoh lengkap untuk text-to-image, image-to-image, dan inpainting dengan SDXL.

```py
import torch
from diffusers import ModularPipeline

pipeline = ModularPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0")
pipeline.load_components(dtype=torch.float16)
pipeline.to("cuda")  # or "mps", "xpu", "cpu"

image = pipeline(prompt="Astronaut in a jungle, cold color palette, muted colors, detailed, 8k").images[0]
image.save("modular_t2i_out.png")
```

```py
import torch
from diffusers import ModularPipeline
from diffusers.utils import load_image

pipeline = ModularPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0")
pipeline.load_components(dtype=torch.float16)
pipeline.to("cuda")  # or "mps", "xpu", "cpu"

url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/sdxl-text2img.png"
init_image = load_image(url)
prompt = "a dog catching a frisbee in the jungle"
image = pipeline(prompt=prompt, image=init_image, strength=0.8).images[0]
image.save("modular_i2i_out.png")
```

```py
import torch
from diffusers import ModularPipeline
from diffusers.utils import load_image

pipeline = ModularPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0")
pipeline.load_components(dtype=torch.float16)
pipeline.to("cuda")  # or "mps", "xpu", "cpu"

img_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/sdxl-text2img.png"
mask_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/sdxl-inpaint-mask.png"

init_image = load_image(img_url)
mask_image = load_image(mask_url)

prompt = "A deep sea diver floating"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, strength=0.85).images[0]
image.save("modular_inpaint_out.png")
```

Panduan ini akan menunjukkan cara membuat [ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline), mengelola komponen-komponennya, dan menjalankan pipeline.

## Membuat pipeline

Ada dua cara untuk membuat [ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline). Merakit dan membuat pipeline dari [ModularPipelineBlocks](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks) dengan [init_pipeline()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks.init_pipeline), atau memuat pipeline yang sudah ada dengan [from_pretrained()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.from_pretrained).

Anda juga dapat menginisialisasi [`ComponentsManager`](./components_manager) untuk menangani penempatan perangkat dan manajemen memori. Jika Anda tidak memerlukan offloading otomatis, Anda dapat melewati langkah ini dan memindahkan pipeline ke perangkat Anda secara manual dengan `pipeline.to("cuda")`.

> [!TIP]
> Lihat dokumentasi [ComponentsManager](./components_manager) untuk detail lebih lanjut tentang bagaimana komponen dapat dikelola di berbagai alur kerja.

### init_pipeline

[init_pipeline()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks.init_pipeline) mengonversi [ModularPipelineBlocks](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks) apa pun menjadi [ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline).

Mari kita definisikan blok minimal untuk melihat cara kerjanya:

```py
from transformers import CLIPTextModel
from diffusers.modular_pipelines import (
    ComponentSpec,
    ModularPipelineBlocks,
    PipelineState,
)

class MyBlock(ModularPipelineBlocks):
    @property
    def expected_components(self):
        return [
            ComponentSpec(
                name="text_encoder",
                type_hint=CLIPTextModel,
                pretrained_model_name_or_path="openai/clip-vit-large-patch14",
            ),
        ]

    def __call__(self, components, state: PipelineState) -> PipelineState:
        return components, state
```

Panggil [init_pipeline()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks.init_pipeline) untuk mengubahnya menjadi pipeline. Atribut `blocks` pada pipeline adalah blok yang digunakan untuk membuatnya — atribut ini menentukan input, output, dan logika komputasi yang diharapkan.

```py
block = MyBlock()
pipe = block.init_pipeline()
pipe.blocks
```

```
MyBlock {
  "_class_name": "MyBlock",
  "_diffusers_version": "0.37.0.dev0"
}
```

> [!WARNING]
> Blocks bersifat mutable — Anda dapat dengan bebas menambahkan, menghapus, atau mengganti blocks sebelum membuat pipeline. Namun, setelah pipeline dibuat, memodifikasi `pipeline.blocks` tidak akan memengaruhi pipeline karena hal itu mengembalikan salinan. Jika Anda menginginkan struktur block yang berbeda, buat pipeline baru setelah memodifikasi blocks.

Saat Anda memanggil [init_pipeline()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks.init_pipeline) tanpa repositori, ia menggunakan `pretrained_model_name_or_path` yang didefinisikan dalam [ComponentSpec](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_components#diffusers.ComponentSpec) blok untuk menentukan dari mana setiap komponen dimuat. Mencetak pipeline menampilkan konfigurasi pemuatan komponen.

```py
pipe
ModularPipeline {
  "_blocks_class_name": "MyBlock",
  "_class_name": "ModularPipeline",
  "_diffusers_version": "0.37.0.dev0",
  "text_encoder": [
    null,
    null,
    {
      "pretrained_model_name_or_path": "openai/clip-vit-large-patch14",
      "revision": null,
      "subfolder": "",
      "type_hint": [
        "transformers",
        "CLIPTextModel"
      ],
      "variant": null
    }
  ]
}
```

Jika Anda meneruskan repositori ke [init_pipeline()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks.init_pipeline), jalur pemuatan akan ditimpa dengan mencocokkan komponen blok Anda terhadap konfigurasi pipeline di repositori tersebut (`model_index.json` atau `modular_model_index.json`). Lihat [Modular repository](#modular-repository) untuk cara spesifikasi pemuatan dicatat dan disimpan.

Pada contoh di bawah, `pretrained_model_name_or_path` akan diperbarui menjadi `"stabilityai/stable-diffusion-xl-base-1.0"`.

```py
pipe = block.init_pipeline("stabilityai/stable-diffusion-xl-base-1.0")
pipe
ModularPipeline {
  "_blocks_class_name": "MyBlock",
  "_class_name": "ModularPipeline",
  "_diffusers_version": "0.37.0.dev0",
  "text_encoder": [
    null,
    null,
    {
      "pretrained_model_name_or_path": "stabilityai/stable-diffusion-xl-base-1.0",
      "revision": null,
      "subfolder": "text_encoder",
      "type_hint": [
        "transformers",
        "CLIPTextModel"
      ],
      "variant": null
    }
  ]
}
```

Jika komponen dalam blok Anda tidak ada di repositori, komponen tersebut tetap `null` dan dilewati selama [load_components()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.load_components).

### from_pretrained

[from_pretrained()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.from_pretrained) adalah cara yang praktis untuk membuat [ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline) tanpa perlu mendefinisikan blok secara manual.

Itu bekerja dengan tiga jenis repositori.

**Repositori diffusers reguler.** Lemparkan repositori model apa pun yang didukung dan ia akan secara otomatis memetakan ke blok pipeline default. Model yang saat ini didukung termasuk SDXL, Wan, Qwen, Z-Image, Flux, dan Flux2.

```py
from diffusers import ModularPipeline, ComponentsManager

components = ComponentsManager()
pipeline = ModularPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", components_manager=components
)
```

**Repositori modular.** Repositori ini berisi `modular_model_index.json` yang menentukan kelas dari setiap komponen dan dari mana komponen tersebut dimuat, dengan komponen disimpan berdampingan dengannya. Lihat [Repositori modular](#modular-repository) untuk cara membuatnya.

```py
from diffusers import ModularPipeline, ComponentsManager

components = ComponentsManager()
pipeline = ModularPipeline.from_pretrained(
    "MiniMaxAI/MiniMax-H3", components_manager=components
)
```

**Repositori modular dengan kode kustom.** Beberapa repositori menyertakan blok pipeline kustom di samping konfigurasi pemuatan. Tambahkan `trust_remote_code=True` untuk memuatnya. Lihat [Blok kustom](./custom_blocks) untuk cara membuat blok Anda sendiri.

```py
from diffusers import ModularPipeline, ComponentsManager

components = ComponentsManager()
pipeline = ModularPipeline.from_pretrained(
    "diffusers/Florence2-image-Annotator", trust_remote_code=True, components_manager=components
)
```

Ketika blok pipeline mendefinisikan alur kerja (periksa `pipeline.blocks.available_workflows`), berikan `workflow=` untuk hanya mempertahankan blok dari alur kerja tersebut — pemangkasan yang sama dengan [get_workflow()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks.get_workflow). Pipeline kemudian hanya mendeklarasikan komponen yang digunakan oleh alur kerja itu, dan docstring-nya menjelaskan input dari alur kerja tersebut secara persis.

```py
pipeline = ModularPipeline.from_pretrained("Qwen/Qwen-Image", workflow="inpainting")
```

## Memuat komponen

[ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline) tidak secara otomatis menginstansiasi dengan komponen. Ia hanya memuat konfigurasi dan spesifikasi komponen. Anda dapat memuat komponen dengan [load_components()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.load_components).

Ini akan memuat semua komponen yang memiliki spesifikasi pemuatan yang valid.

```py
import torch

pipeline.load_components(dtype=torch.float16)
```

Anda juga dapat memuat komponen tertentu berdasarkan nama. Contoh di bawah ini hanya memuat `text_encoder`.

```py
pipeline.load_components(names=["text_encoder"], dtype=torch.float16)
```

Pada pipeline yang bloknya mendefinisikan alur kerja, `workflow=` hanya memuat komponen yang digunakan oleh alur kerja tersebut. Pipeline tetap mempertahankan semua bloknya, sehingga ini adalah cara yang praktis untuk menjalankan satu pipeline melintasi berbagai alur kerja: setiap pemanggilan hanya menambahkan apa yang masih kurang dari alur kerja baru.

```py
pipeline.load_components(workflow="inpainting", dtype=torch.float16)
```

Setelah dimuat, mencetak pipeline menunjukkan komponen mana yang dimuat — dua field pertama berubah dari `null` menjadi pustaka dan kelas komponen.

```py
pipeline
```

```
# text_encoder is loaded - shows library and class
"text_encoder": [
  "transformers",
  "CLIPTextModel",
  { ... }
]

# unet is not loaded yet - still null
"unet": [
  null,
  null,
  { ... }
]
```

Keyword argument seperti `dtype`, `variant`, `revision`, dan `quantization_config` diteruskan ke `from_pretrained()` untuk setiap komponen. Anda dapat meneruskan satu nilai untuk diterapkan ke semua komponen, atau dict untuk mengatur nilai per komponen.

```py
# apply bfloat16 to all components
pipeline.load_components(dtype=torch.bfloat16)

# different dtypes per component
pipeline.load_components(dtype={"transformer": torch.bfloat16, "default": torch.float32})
```

[load_components()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.load_components) hanya memuat komponen yang belum dimuat dan memiliki spesifikasi pemuatan yang valid. Artinya, jika Anda sudah mengatur komponen pada pipeline, memanggil [load_components()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.load_components) lagi tidak akan memuat ulang komponen tersebut.

## Memperbarui komponen

[update_components()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.update_components) mengganti komponen pada pipeline dengan yang baru. Ketika sebuah komponen diperbarui, spesifikasi pemuatan juga diperbarui dalam konfigurasi pipeline dan [load_components()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.load_components) akan melewatinya pada pemanggilan berikutnya.

### Dari AutoModel

Anda dapat meneruskan objek model yang dimuat dengan `AutoModel.from_pretrained()`. Model yang dimuat dengan cara ini secara otomatis diberi tag dengan informasi pemuatannya.

```py
from diffusers import AutoModel

unet = AutoModel.from_pretrained(
    "RunDiffusion/Juggernaut-XL-v9", subfolder="unet", variant="fp16", dtype=torch.float16
)
pipeline.update_components(unet=unet)
```

### Dari ComponentSpec

Gunakan [get_component_spec()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.get_component_spec) untuk mendapatkan salinan spesifikasi komponen saat ini, memodifikasinya, dan memuat komponen baru.

```py
unet_spec = pipeline.get_component_spec("unet")

# modify to load from a different repository
unet_spec.pretrained_model_name_or_path = "RunDiffusion/Juggernaut-XL-v9"

# load and update
unet = unet_spec.load(dtype=torch.float16)
pipeline.update_components(unet=unet)
```

Anda juga dapat membuat [ComponentSpec](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_components#diffusers.ComponentSpec) dari awal.

Tidak semua komponen dimuat dari bobot pra-terlatih — beberapa dibuat dari konfigurasi (tercantum di bawah `pipeline.config_component_names`). Untuk komponen tersebut, gunakan [create()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_components#diffusers.ComponentSpec.create) alih-alih [load()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_components#diffusers.ComponentSpec.load).

```py
guider_spec = pipeline.get_component_spec("guider")
guider_spec.config = {"guidance_scale": 5.0}
guider = guider_spec.create()
pipeline.update_components(guider=guider)
```

Atau cukup lewati objeknya secara langsung.

```py
from diffusers.guiders import ClassifierFreeGuidance

guider = ClassifierFreeGuidance(guidance_scale=5.0)
pipeline.update_components(guider=guider)
```

Lihat panduan [Guiders](../using-diffusers/guiders) untuk detail lebih lanjut tentang guiders yang tersedia dan cara mengonfigurasinya.

## Membagi pipeline menjadi beberapa tahap

Karena blok bersifat komposabel, Anda dapat membongkar sebuah pipeline dan menyusunnya kembali menjadi pipeline terpisah untuk setiap tahap. Contoh di bawah ini menunjukkan bagaimana kita dapat memisahkan blok text encoder dari bagian lain pipeline, sehingga Anda dapat meng-encode prompt secara independen dan meneruskan embeddings ke pipeline utama.

```py
from diffusers import ModularPipeline, ComponentsManager
import torch

device = "cuda"  # or "mps", "xpu", "cpu"
dtype = torch.bfloat16
repo_id = "black-forest-labs/FLUX.2-klein-4B"

# get the blocks and separate out the text encoder
blocks = ModularPipeline.from_pretrained(repo_id).blocks
text_block = blocks.sub_blocks.pop("text_encoder")

# use ComponentsManager to handle offloading across multiple pipelines
manager = ComponentsManager()
manager.enable_auto_cpu_offload(device=device)

# create separate pipelines for each stage
text_encoder_pipeline = text_block.init_pipeline(repo_id, components_manager=manager)
pipeline = blocks.init_pipeline(repo_id, components_manager=manager)

# encode text
text_encoder_pipeline.load_components(dtype=dtype)
text_embeddings = text_encoder_pipeline(prompt="a cat").get_by_kwargs("denoiser_input_fields")

# denoise and decode
pipeline.load_components(dtype=dtype)
output = pipeline(
    **text_embeddings,
    num_inference_steps=4,
).images[0]
```

[ComponentsManager](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_components#diffusers.ComponentsManager) mengelola memori di antara beberapa pipeline. Berbeda dengan strategi offloading dalam [DiffusionPipeline](/docs/diffusers/v0.43.0/id/api/pipelines/overview#diffusers.DiffusionPipeline) yang mengikuti urutan tetap, [ComponentsManager](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline_components#diffusers.ComponentsManager) membuat keputusan offloading secara dinamis setiap kali model menjalankan forward pass, berdasarkan situasi memori saat itu. Artinya, komponen ini berfungsi terlepas dari berapa banyak pipeline yang Anda buat atau urutan apa pun yang Anda jalankan. Lihat panduan [ComponentsManager](./components_manager) untuk detail lebih lanjut.

Jika tahap pipeline berbagi komponen (misalnya, VAE yang sama digunakan untuk encoding dan decoding), Anda dapat menggunakan [update_components()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.update_components) untuk meneruskan komponen yang sudah dimuat ke pipeline lain daripada memuatnya lagi.

## Repositori modular

Repositori diperlukan jika blok pipeline menggunakan *komponen terlatih sebelumnya*. Repositori menyediakan spesifikasi pemuatan dan metadata.

[ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline) berfungsi dengan repositori diffusers biasa secara bawaan. Namun, Anda juga dapat membuat *repositori modular* untuk fleksibilitas yang lebih besar. Repositori modular berisi file `modular_model_index.json` yang memuat 3 elemen berikut.

- `library` dan `class` menunjukkan pustaka tempat komponen dimuat dan kelasnya. Jika `null`, komponen belum dimuat.
- `loading_specs_dict` berisi informasi yang diperlukan untuk memuat komponen, seperti repositori dan subfolder tempat komponen tersebut dimuat.

```py
from diffusers import ModularPipeline

# load from a regular repo
pipeline = ModularPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0")
pipeline.load_components()

# push as a modular repository
pipeline.save_pretrained("local/path", repo_id="my-username/sdxl-modular", push_to_hub=True)
```

Secara default, [save_pretrained()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.save_pretrained) menulis setiap komponen yang saat ini dimuat dan dapat diserialisasi oleh Diffusers. Komponen yang tidak dimuat, atau tidak dapat diserialisasi, tidak ditulis dan tetap mempertahankan spesifikasi pemuatan yang ada.

### Simpan salinan mandiri

Muat semua komponen, lalu simpan. Setiap spesifikasi menunjuk ke hasil tersebut, sehingga semuanya dimuat ulang dari satu tempat, termasuk secara offline.

```py
pipe = ModularPipeline.from_pretrained("MiniMaxAI/MiniMax-H3")
pipe.load_components()
pipe.save_pretrained("path/to/local-copy")
```

Tujuan yang dicatat dalam `modular_model_index.json` adalah tempat di mana [save_pretrained()](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline.save_pretrained) menulis: `save_directory` untuk penyimpanan lokal, atau `repo_id` ketika Anda meneruskan `push_to_hub=True`.

Memindahkan file dengan cara lain tidak menulis ulang indeks. Salinan yang diunduh dengan `hf download --local-dir` tetap berfungsi: ketika pipeline dimuat dari direktori lokal, setiap komponen yang file-nya hadir di direktori tersebut dimuat dari sana, bukan dari repositori yang tercatat. Salinan yang diunggah dengan `hf upload` tetap menunjuk ke lokasi lama, sehingga dalam kasus tersebut indeks perlu diperbarui secara manual.

Dengan `huggingface_hub>=1.32.0`, file yang didukung Xet dan identik dapat berbagi satu payload cache di antara repositori Hub mana pun. Ini mencakup file individual dalam checkpoint yang dipartisi: shard dengan hash Xet yang sama dapat digunakan kembali bahkan ketika shard lain berbeda. Kedua unduhan harus menggunakan direktori cache Hub yang sama dengan dukungan symlink. Mengubah dtype, serialisasi, atau batas shard dapat mengubah hash file dan mencegah penggunaan kembali. Ini menghemat lalu lintas unduhan dan ruang disk, bukan memori yang digunakan oleh komponen yang dimuat.

Caching bersama bersifat best-effort. Pengaturan `HF_HUB_DISABLE_SHARED_BLOBS=1` tetap mendukung pemuatan, tetapi meng-cache salinan terpisah. Referensi komponen yang ada di `modular_model_index.json` tetap tidak berubah; pertahankan referensi eksternal untuk komponen yang tidak disimpan dalam repositori modular.

### Merujuk komponen di repositori lain

Spesifikasi pemuatan komponen dalam `modular_model_index.json` dapat menunjuk ke repositori lain. Sebagai contoh, [diffusers/flux2-bnb-4bit-modular](https://huggingface.co/diffusers/flux2-bnb-4bit-modular) memuat transformer terkuantisasinya dari `diffusers/FLUX.2-dev-bnb-4bit` dan komponen lainnya dari `black-forest-labs/FLUX.2-dev`.

Kami sangat merekomendasikan repositori yang mandiri: dengan menjaga semua komponen tetap bersama, pipeline menjadi lebih mudah diunduh, dibagikan, dan digunakan secara offline tanpa bergantung pada repositori lain. Gunakan referensi lintas repositori hanya jika Anda memang sengaja ingin komponen dihosting di tempat lain.

Lewati `overwrite_modular_index=False` untuk mempertahankan spesifikasi pemuatan di `modular_model_index.json` apa adanya. Komponen yang disimpan dengan spesifikasi pemuatan kosong tetap diisi dengan tujuan, karena tidak ada yang perlu dipertahankan.

Dengan `huggingface_hub>=1.32.0`, file identik yang didukung Xet dapat berbagi satu payload cache di antara repositori melalui symlink, sehingga menghindari unduhan duplikat dan penggunaan disk. Referensi lintas repositori tidak diperlukan untuk ini. Lihat [Simpan salinan mandiri](#save-a-self-contained-copy) untuk persyaratan dan batasan cache bersama.

#### Perbarui indeks modular yang sudah ada

Referensi yang ada ke repositori asli tetap berfungsi. Jika sebuah referensi hanya digunakan untuk menghindari unduhan duplikat, lebih baik memperbaruinya untuk memuat dari repositori modular setelah file komponen tersedia di sana.

Pertama, periksa bahwa repositori modular berisi konfigurasi komponen yang sama dan semua file bobot yang diperlukan, termasuk indeks bobot dan setiap shard untuk checkpoint yang di-shard. Hash Xet yang cocok menentukan file bobot mana yang dapat menggunakan ulang cache bersama. Simpan referensi ke komponen yang tidak ada atau sengaja dimuat dari checkpoint lain.

Edit hanya spesifikasi pemuatan yang relevan pada salinan lokal dari `modular_model_index.json`. Misalnya, untuk menggunakan VAE yang disimpan di bawah `vae/` di repositori modular dengan varian bobot yang sama:

```py
import json
from pathlib import Path

index_path = Path("path/to/local-copy/modular_model_index.json")
index = json.loads(index_path.read_text())
spec = index["vae"][2]
spec["pretrained_model_name_or_path"] = "my-username/my-modular-repo"
spec.pop("repo", None)
spec["subfolder"] = "vae"
spec["revision"] = None
index_path.write_text(json.dumps(index, indent=2) + "\n")
```

Hal ini juga menghapus field `repo` lama. Revisi dari repositori asal tidak mengidentifikasi revisi di tujuan: gunakan `None` untuk cabang default tujuan, atau tetapkan revisi tujuan yang berisi komponen tersebut. Sesuaikan `subfolder` dan `variant` jika nama filenya berbeda.

Sebelum menerbitkan indeks yang diperbarui, muat dengan `ModularPipeline.from_pretrained("path/to/local-copy")`, panggil `load_components(names="vae")`, dan verifikasi bahwa komponen dimuat dengan parameter yang diharapkan. Unggah hanya indeks yang diedit; menyimpan ulang bobot dapat mengubah hash-nya dan mencegah penggunaan ulang cache.

### Kode kustom

Repositori modular juga dapat memuat blok pipeline kustom sebagai kode Python. Hal ini memungkinkan Anda untuk membagikan blok khusus yang bukan bawaan dari Diffusers. Sebagai contoh, [diffusers/Florence2-image-Annotator](https://huggingface.co/diffusers/Florence2-image-Annotator) memuat blok kustom di samping konfigurasi pemuatan:

```
Florence2-image-Annotator/
├── block.py                    # Custom pipeline blocks implementation
├── config.json                 # Pipeline configuration and auto_map
├── mellon_config.json          # UI configuration for Mellon
└── modular_model_index.json    # Component loading specifications
```

File `config.json` berisi kunci `auto_map` yang memberi tahu [ModularPipeline](/docs/diffusers/v0.43.0/id/api/modular_diffusers/pipeline#diffusers.ModularPipeline) di mana blok kustom dapat ditemukan:

```json
{
  "_class_name": "Florence2AnnotatorBlocks",
  "auto_map": {
    "ModularPipelineBlocks": "block.Florence2AnnotatorBlocks"
  }
}
```

Muat repositori kode kustom dengan `trust_remote_code=True` seperti yang ditunjukkan dalam [from_pretrained](#frompretrained). Lihat [Blok kustom](./custom_blocks) untuk cara membuat dan membagikan blok Anda sendiri.

