Hub documentation
DDUF
DDUF
概要
DDUF(Diffusion Diffusion Unified Format)は、拡散モデル用の単一ファイル形式です。モデルのすべてのコンポーネントを1つのファイルにパッケージングすることで、異なるモデル配布方法や重みの保存形式を統一することを目的としています。言語に依存せず、ファイル全体をダウンロードせずにリモートからパースできるように設計されています。
この作業は、GGUFフォーマットから着想を得ています。
DDUFで最も人気のある拡散モデルのいくつかを使い始めるには、DDUF組織をチェックしてください。
私たちは貢献を心から歓迎しています!
広く採用されるファイルフォーマットを作成するには、コミュニティからの早期のフィードバックが必要です。すべてが確定しているわけではなく、皆さんのご意見を大切にしています。あなたのユースケースがカバーされていない場合は、DDUF組織のディスカッションでお知らせください。
主な機能は以下の通りです。
- 単一ファイルのパッケージング。
- 既存のツールを活用するために、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 データクラスで表されます。この情報により、ファイル全体を読み込まずにその内容を読むことが可能になります。実際には、低レベルの読み取り処理を直接扱う必要はなく、ヘルパーに委ねる形になります。
例えば、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 が発生します。
より柔軟性を高めるには、export_entries_as_dduf を使用して、最終的な 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を使用しないのはなぜですか?
このコメントの説明を参照してください。
なぜ圧縮しないのですか?
- 大規模ファイルの直接メモリマッピングを有効にします
- リモートファイルへのアクセスの一貫性と予測可能性を確保します
- ファイル読み取り時のCPUオーバーヘッドを防止します
- safetensorsとの互換性を維持します
DDUFファイルを変更できますか?
いいえ。現時点では、DDUFファイルは不変(immutable)であるように設計されています。モデルを更新するには、新しいDDUFファイルを作成してください。
DDUFはどのフレームワーク/アプリでサポートされていますか?
私たちは常に他のライブラリやフレームワークにアプローチしています。プロジェクトへのサポート追加にご関心がある場合は、DDUF orgでDiscussionを作成してください。
Update on GitHub