Hub documentation
DDUF
DDUF
๊ฐ์
DDUF(Diffusion Diffusion Unified Format)๋ ๋ค์ํ ๋ชจ๋ธ ๋ฐฐํฌ ๋ฐฉ์๊ณผ ๊ฐ์ค์น ์ ์ฅ ํ์์ ๋จ์ผ ํ์ผ๋ก ํตํฉํ๊ธฐ ์ํด ๋ชจ๋ ๋ชจ๋ธ ๊ตฌ์ฑ ์์๋ฅผ ํ๋์ ํ์ผ์ ํจํค์งํ๋ diffusion ๋ชจ๋ธ์ฉ ๋จ์ผ ํ์ผ ํ์์ ๋๋ค. ์ธ์ด์ ์ข ์์ ์ด์ง ์์ผ๋ฉฐ, ์ ์ฒด ํ์ผ์ ๋ค์ด๋ก๋ํ์ง ์๊ณ ์๊ฒฉ ์์น์์ ํ์ฑํ ์ ์๋๋ก ์ค๊ณ๋์์ต๋๋ค.
์ด ์์ ์ GGUF ํ์์์ ์๊ฐ์ ๋ฐ์์ต๋๋ค.
DDUF์์ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ํ์ฐ ๋ชจ๋ธ ์ค ์ผ๋ถ๋ฅผ ์ฌ์ฉํ๊ธฐ ์์ํ๋ ค๋ฉด DDUF ์กฐ์ง์ ํ์ธํด ๋ณด์ธ์.
๊ธฐ์ฌ๋ฅผ ์ง์ฌ์ผ๋ก ํ์ํฉ๋๋ค!
๊ด๋ฒ์ํ๊ฒ ์ฑํ๋๋ ํ์ผ ํฌ๋งท์ ๋ง๋ค๊ธฐ ์ํด์๋ ์ปค๋ฎค๋ํฐ์ ์ด๊ธฐ ํผ๋๋ฐฑ์ด ํ์ํฉ๋๋ค. ์์ง ํ์ ๋ ์ฌํญ์ ์์ผ๋ฉฐ, ๋ชจ๋ ๋ถ์ ์๊ฒฌ์ ์์คํ ์๊ฐํฉ๋๋ค. ์ฌ์ฉ ์ฌ๋ก๊ฐ ํฌํจ๋์ง ์์ ๊ฒฝ์ฐ, DDUF ์กฐ์ง์ discussions์์ ์๋ ค ์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
์ฃผ์ ๊ธฐ๋ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๋จ์ผ ํ์ผ ํจํค์ง.
- ๊ธฐ์กด ๋๊ตฌ ํ์ฉ์ ์ํด ZIP ํ์ผ ํ์ ๊ธฐ๋ฐ.
- ์์ถ์ ์ฌ์ฉํ์ง ์์
mmapํธํ์ฑ์ ๋ณด์ฅํ๊ณ , ์ด๋ฅผ ํตํด ๋น ๋ฅธ ๋ก๋ฉ๊ณผ ์ ์ฅ์ ์ง์ํฉ๋๋ค. - ์ธ์ด ๋น์ข ์์ : Python, JavaScript, Rust, C++ ๋ฑ์ผ๋ก ํด๋ง์ ๊ตฌํํ ์ ์์ต๋๋ค.
- HTTP ์นํ์ : ๋ฉํ๋ฐ์ดํฐ์ ํ์ผ ๊ตฌ์กฐ๋ฅผ HTTP Range ์์ฒญ์ ์ฌ์ฉํ์ฌ ์๊ฒฉ์ผ๋ก ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
- ์ ์ฐ์ฑ: ๊ฐ ๋ชจ๋ธ ๊ตฌ์ฑ ์์๋ ํ์ฌ Diffusers ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅด๋ฉฐ ์์ฒด ๋๋ ํฐ๋ฆฌ์ ์ ์ฅ๋ฉ๋๋ค.
- Safe: Safetensors๋ฅผ ๊ฐ์ค์น ์ ์ฅ ํ์์ผ๋ก ์ฌ์ฉํ๋ฉฐ, ZIP ํญํ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ค์ฒฉ ๋๋ ํฐ๋ฆฌ๋ฅผ ๊ธ์งํฉ๋๋ค.
๊ธฐ์ ์ฌ์
๊ธฐ์ ์ ์ผ๋ก .dduf ํ์ผ์ ์ค์ ๋ก .zip ์์นด์ด๋ธ์
๋๋ค. ๋ฒ์ฉ์ ์ผ๋ก ์ง์๋๋ ํ์ผ ํ์์ ๊ธฐ๋ฐ์ผ๋ก ํจ์ผ๋ก์จ ์ด๋ฏธ ๊ฒฌ๊ณ ํ ํด๋ง์ด ์กด์ฌํ๋ค๋ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค. ๊ทธ๋ฌ๋ ํ์ฐ ๋ชจ๋ธ์ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๊ธฐ ์ํด ๋ช ๊ฐ์ง ์ ์ฝ ์ฌํญ์ด ์ ์ฉ๋ฉ๋๋ค:
- ๋ฐ์ดํฐ๋ ์์ถ๋์ง ์์ ์ํ๋ก ์ ์ฅ๋์ด์ผ ํ๋ฉฐ(ํ๋๊ทธ
0), ์ด๋ฅผ ํตํด ๋ฉ๋ชจ๋ฆฌ ๋งคํ์ ์ด์ฉํ ์ง์ฐ ๋ก๋ฉ์ด ๊ฐ๋ฅํฉ๋๋ค. - ZIP64 ํ๋กํ ์ฝ์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํด์ผ ํ๋ฉฐ, ์ด๋ฅผ ํตํด 4GB ์ด์์ ํ์ผ์ ์ ์ฅํ ์ ์์ต๋๋ค.
- ์์นด์ด๋ธ์๋
.json,.safetensors,.model๋ฐ.txtํ์ผ๋ง ํฌํจํ ์ ์์ต๋๋ค. - ์์นด์ด๋ธ์ ๋ฃจํธ์
model_index.jsonํ์ผ์ด ์กด์ฌํด์ผ ํฉ๋๋ค. ์ด ํ์ผ์๋ ๋ชจ๋ธ ๋ฐ ๊ทธ ๊ตฌ์ฑ ์์์ ๋ํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ ํค-๊ฐ ๋งคํ์ด ์์ด์ผ ํฉ๋๋ค. - ๊ฐ ๊ตฌ์ฑ ์์๋ ์์ฒด ๋๋ ํฐ๋ฆฌ(์:
vae/,text_encoder/)์ ์ ์ฅ๋์ด์ผ ํฉ๋๋ค. ์ค์ฒฉ๋ ํ์ผ์ UNIX ์คํ์ผ ๊ฒฝ๋ก ๊ตฌ๋ถ์(/)๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. - ๊ฐ ๋๋ ํ ๋ฆฌ๋
model_index.json์ธ๋ฑ์ค์ ๊ตฌ์ฑ ์์์ ๋์ํด์ผ ํฉ๋๋ค. - ๊ฐ ๋๋ ํฐ๋ฆฌ์๋ json ์ค์ ํ์ผ(
config.json,tokenizer_config.json,preprocessor_config.json,scheduler_config.json์ค ํ๋)์ด ํฌํจ๋์ด์ผ ํฉ๋๋ค. - ํ์ ๋๋ ํฐ๋ฆฌ๋ ํ์ฉ๋์ง ์์ต๋๋ค.
ํ์ผ์ด ์ ํจํ์ง ํ์ธํ๊ณ ์ถ์ผ์ ๊ฐ์? ์ด Space๋ฅผ ์ฌ์ฉํด ํ์ธํด ๋ณด์ธ์: https://huggingface.co/spaces/DDUF/dduf-check.
์ฌ์ฉ
huggingface_hub์ Python์์ DDUF ํ์ผ์ ์ฒ๋ฆฌํ๋ ๋๊ตฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. ํ์ผ ๋ฌด๊ฒฐ์ฑ์ ๊ฒ์ฆํ๋ ๋ด์ฅ ๊ท์น๊ณผ DDUF ํ์ผ์ ์ฝ๊ณ ๋ด๋ณด๋ด๋ ํฌํผ๋ฅผ ํฌํจํฉ๋๋ค. ์ด ๋๊ตฌ๊ฐ diffusers ํตํฉ๊ณผ ๊ฐ์ Python ์ํ๊ณ์์ ์ฑํ๋๊ธฐ๋ฅผ ๋ชฉํ๋ก ํฉ๋๋ค. ์ ์ฌํ ๋๊ตฌ๋ ๋ค๋ฅธ ์ธ์ด(JavaScript, Rust, C++ ๋ฑ)๋ฅผ ์ํด ๊ฐ๋ฐ๋ ์ ์์ต๋๋ค.
DDUF ํ์ผ์ ์ฝ๋ ๋ฐฉ๋ฒ
read_dduf_file์ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ์ฌ DDUF ํ์ผ์ ์ฝ์ต๋๋ค. ๋ฉํ๋ฐ์ดํฐ๋ง ์ฝ๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ณผ๋ํ๊ฒ ์ฐจ์งํ์ง ์๋ ๊ฐ๋ฒผ์ด ํธ์ถ์
๋๋ค. ์๋ ์์์์๋ ์ด๋ฏธ FLUX.1-dev.dduf ํ์ผ์ ๋ก์ปฌ๋ก ๋ค์ด๋ก๋ํ๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
>>> from huggingface_hub import read_dduf_file
# Read DDUF metadata
>>> dduf_entries = read_dduf_file("FLUX.1-dev.dduf")read_dduf_file๋ DDUF ์์นด์ด๋ธ์ ๊ฐ ํ์ผ์ ํด๋นํ๋ ํญ๋ชฉ์ ํฌํจํ๋ ๋งคํ์ ๋ฐํํฉ๋๋ค. ํ์ผ์ ์๋ณธ DDUF ํ์ผ ๋ด ํญ๋ชฉ์ ํ์ผ๋ช
, ์คํ์
, ๊ธธ์ด๋ฅผ ํฌํจํ๋ DDUFEntry dataclass๋ก ํํ๋ฉ๋๋ค. ์ด ์ ๋ณด๋ ์ ์ฒด ํ์ผ์ ๋ก๋ํ์ง ์๊ณ ๋ ํด๋น ๋ด์ฉ์ ์ฝ๋ ๋ฐ ์ ์ฉํฉ๋๋ค. ์ค์ ๋ก๋ ์ ์์ค ์ฝ๊ธฐ๋ฅผ ์ง์ ์ฒ๋ฆฌํ ํ์ ์์ด ํฌํผ์ ์์กดํ๋ฉด ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด, model_index.json์ ๋ด์ฉ์ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
>>> import json
>>> json.loads(dduf_entries["model_index.json"].read_text())
{'_class_name': 'FluxPipeline', '_diffusers_version': '0.32.0.dev0', '_name_or_path': 'black-forest-labs/FLUX.1-dev', ...๋ฐ์ด๋๋ฆฌ ํ์ผ์ ๊ฒฝ์ฐ as_mmap์ ์ฌ์ฉํ์ฌ ์์ ๋ฐ์ดํธ์ ์ก์ธ์คํด์ผ ํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์๋ณธ ํ์ผ์ ๋ํ ๋ฉ๋ชจ๋ฆฌ ๋งคํ์ผ๋ก ๋ฐ์ดํธ๋ฅผ ๋ฐํํฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ ๋งคํ์ ์ฌ์ฉํ๋ฉด ๋ฉ๋ชจ๋ฆฌ์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ์ง ์๊ณ ํ์ํ ๋ฐ์ดํธ๋ง ์ฝ์ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, safetensors ๊ฐ์ค์น๋ฅผ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
>>> import safetensors.torch
>>> with dduf_entries["vae/diffusion_pytorch_model.safetensors"].as_mmap() as mm:
... state_dict = safetensors.torch.load(mm) # `mm` is a bytes object
as_mmap์ ๋ฉ๋ชจ๋ฆฌ ๋งคํ์ ์ด์ ์ ํ์ฉํ๋ ค๋ฉด ์ปจํ ์คํธ ๋งค๋์ ๋ด์์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
DDUF ํ์ผ์ ์์ฑํ๋ ๋ฐฉ๋ฒ
export_folder_as_dduf์ ํด๋ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ์ฌ DDUF ํ์ผ์ ๋ด๋ณด๋
๋๋ค.
# Export a folder as a DDUF file
>>> from huggingface_hub import export_folder_as_dduf
>>> export_folder_as_dduf("FLUX.1-dev.dduf", folder_path="path/to/FLUX.1-dev")์ด ๋๊ตฌ๋ ํด๋๋ฅผ ์ค์บํ๊ณ ๊ด๋ จ ํญ๋ชฉ์ ์ถ๊ฐํ๋ฉฐ ๋ด๋ณด๋ธ ํ์ผ์ด ์ ํจํ์ง ํ์ธํฉ๋๋ค. ์ด ๊ณผ์ ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด DDUFExportError๊ฐ ๋ฐ์๋ฉ๋๋ค.
๋ ๋ง์ ์ ์ฐ์ฑ์ ์ํด, ์ต์ข
DDUF ํ์ผ์ ํฌํจํ ํ์ผ ๋ชฉ๋ก์ ๋ช
์์ ์ผ๋ก ์ง์ ํ๋ ค๋ฉด export_entries_as_dduf๋ฅผ ์ฌ์ฉํ์ธ์:
# Export specific files from the local disk.
>>> from huggingface_hub import export_entries_as_dduf
>>> export_entries_as_dduf(
... dduf_path="stable-diffusion-v1-4-FP16.dduf",
... entries=[ # List entries to add to the DDUF file (here, only FP16 weights)
... ("model_index.json", "path/to/model_index.json"),
... ("vae/config.json", "path/to/vae/config.json"),
... ("vae/diffusion_pytorch_model.fp16.safetensors", "path/to/vae/diffusion_pytorch_model.fp16.safetensors"),
... ("text_encoder/config.json", "path/to/text_encoder/config.json"),
... ("text_encoder/model.fp16.safetensors", "path/to/text_encoder/model.fp16.safetensors"),
... # ... add more entries here
... ]
... )export_entries_as_dduf์ ์ด๋ฏธ ๋์คํฌ์ ๋ชจ๋ธ์ ์ ์ฅํ ๊ฒฝ์ฐ ์ ์๋ํฉ๋๋ค. ํ์ง๋ง ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋๋ ๋ชจ๋ธ์ DDUF ํ์ผ๋ก ์ง์ ์ง๋ ฌํํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? export_entries_as_dduf์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ง๋ ฌํํ๋ ๋ฐฉ๋ฒ์ ์๋ ค์ฃผ๋ Python generator๋ฅผ ์ ๊ณตํจ์ผ๋ก์จ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค:
(...)
# Export state_dicts one by one from a loaded pipeline
>>> def as_entries(pipe: DiffusionPipeline) -> Generator[Tuple[str, bytes], None, None]:
... # Build a generator that yields the entries to add to the DDUF file.
... # The first element of the tuple is the filename in the DDUF archive. The second element is the content of the file.
... # Entries will be evaluated lazily when the DDUF file is created (only 1 entry is loaded in memory at a time)
... yield "vae/config.json", pipe.vae.to_json_string().encode()
... yield "vae/diffusion_pytorch_model.safetensors", safetensors.torch.save(pipe.vae.state_dict())
... yield "text_encoder/config.json", pipe.text_encoder.config.to_json_string().encode()
... yield "text_encoder/model.safetensors", safetensors.torch.save(pipe.text_encoder.state_dict())
... # ... add more entries here
>>> export_entries_as_dduf(dduf_path="my-cool-diffusion-model.dduf", entries=as_entries(pipe))Diffusers๋ก DDUF ํ์ผ ๋ก๋
Diffusers์๋ DDUF ํ์ผ์ ๋ํ ๋ด์ฅ ํตํฉ ๊ธฐ๋ฅ์ด ์์ต๋๋ค. Hub์ ์ ์ฅ๋ ์ฒดํฌํฌ์ธํธ์์ ํ์ดํ๋ผ์ธ์ ๋ก๋ํ๋ ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
from diffusers import DiffusionPipeline
import torch
pipe = DiffusionPipeline.from_pretrained(
"DDUF/FLUX.1-dev-DDUF", dduf_file="FLUX.1-dev.dduf", torch_dtype=torch.bfloat16
).to("cuda")
image = pipe(
"photo a cat holding a sign that says Diffusers", num_inference_steps=50, guidance_scale=3.5
).images[0]
image.save("cat.png")F.A.Q.
ZIP๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ถํ๋ ์ด์ ๋ ๋ฌด์์ธ๊ฐ์?
ZIP์ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ์ ์ ๊ณตํฉ๋๋ค:
- ๋ฒ์ฉ ์ง์ ํ์ผ ํ์
- ์ฝ๊ธฐ์๋ ์ถ๊ฐ์ ์ธ ์ข ์์ฑ์ด ํ์ํ์ง ์์ต๋๋ค
- ๋ด์ฅ ํ์ผ ์ธ๋ฑ์ฑ
- ๊ด๋ฒ์ํ ์ธ์ด ์ง์
์์นด์ด๋ธ์ ์์ ๋ถ๋ถ์ ๋ชฉ์ฐจ๊ฐ ํฌํจ๋ TAR์ ์ฌ์ฉํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ธ๊ฐ์?
์ด ๋๊ธ์ ์ค๋ช ์ ์ฐธ์กฐํ์ธ์.
์ ์์ถ์ด ์๋์?
- ๋์ฉ๋ ํ์ผ์ ์ง์ ๋ฉ๋ชจ๋ฆฌ ๋งคํ์ ํ์ฑํํฉ๋๋ค
- ์ผ๊ด๋๊ณ ์์ธก ๊ฐ๋ฅํ ์๊ฒฉ ํ์ผ ์ก์ธ์ค๋ฅผ ๋ณด์ฅํฉ๋๋ค
- Prevents CPU overhead during file reading
- safetensors์์ ํธํ์ฑ์ ์ ์งํฉ๋๋ค
DDUF ํ์ผ์ ์์ ํ ์ ์๋์?
์๋์. ํ์ฌ DDUF ํ์ผ์ ๋ถ๋ณ(immutable)์ผ๋ก ์ค๊ณ๋์ด ์์ต๋๋ค. ๋ชจ๋ธ์ ์ ๋ฐ์ดํธํ๋ ค๋ฉด ์๋ก์ด DDUF ํ์ผ์ ์์ฑํ์ธ์.
DDUF์ ์ง์ํ๋ ํ๋ ์์ํฌ/์ฑ์ ๋ฌด์์ธ๊ฐ์?
์ฐ๋ฆฌ๋ ์ง์์ ์ผ๋ก ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋ ์์ํฌ์ ์ ๊ทผํ๊ณ ์์ต๋๋ค. ํ๋ก์ ํธ์ ์ง์์ ์ถ๊ฐํ๋ ๋ฐ ๊ด์ฌ์ด ์์ผ์๋ค๋ฉด DDUF org์์ Discussion์ ์ด์ด ์ฃผ์ธ์.
Update on GitHub