Hub Python Library documentation

キャッシュの仕組みを理解する

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

キャッシュの仕組みを理解する

huggingface_hub は、Hub からダウンロードした個別のファイルを保存し、リポジトリが更新された際に変更されていないファイルを再度ダウンロードすることを避けるため、ローカルのファイルベースのキャッシュを使用します。さらに、hf_xet は、アップロードを最適化するためにシャードキャッシュとステージングデータを保存します(Xet キャッシングを参照)。

このガイドでは、huggingface_hub が提供する Python 固有のキャッシュ管理ツールについて説明します。Hugging Face Hub のキャッシュシステムの仕組みに関する言語非依存の概要については、ローカルキャッシュに関する Hub ドキュメントを参照してください。

ファイルベースのキャッシュ

Hugging Face Hubのキャッシュシステムは、Hubに依存するライブラリ間で共有される中央キャッシュとして設計されています。v0.8.0で更新され、リビジョン間で同じファイルを再ダウンロードすることを防止するようになりました。

キャッシュシステムは次のように設計されています:

<CACHE_DIR>
├─ <MODELS>
├─ <DATASETS>
├─ <SPACES>
├─ <KERNELS>

デフォルトの<CACHE_DIR>は~/.cache/huggingface/hubです。ただし、すべてのメソッドのcache_dir引数でカスタマイズしたり、HF_HOMEまたはHF_HUB_CACHEの環境変数を指定したりすることで変更できます。

モデル、データセット、スペース、カーネルは共通のルートを持ちます。これらのリポジトリにはそれぞれ、リポジトリの種類、存在する場合は名前空間(組織名またはユーザー名)、リポジトリ名が含まれます:

<CACHE_DIR>
├─ models--julien-c--EsperBERTo-small
├─ models--lysandrejik--arxiv-nlp
├─ models--bert-base-cased
├─ datasets--glue
├─ datasets--huggingface--DataMeasurementsFiles
├─ spaces--dalle-mini--dalle-mini

これらフォルダ内が、Hub からすべてのファイルをダウンロードする先となります。キャッシュにより、ファイルが既に存在していて更新されていない場合は、2 回ダウンロードされることはありません。ただし、ファイルが更新されており、最新ファイルの取得を要求している場合は、最新ファイルがダウンロードされます(必要になった場合に備えて、以前のファイルはそのまま保持されます)。

これを達成するために、すべてのフォルダーには同じ骨格が含まれています:

<CACHE_DIR>
├─ datasets--glue
│  ├─ refs
│  ├─ blobs
│  ├─ snapshots
│  ├─ trees
...

各フォルダには、以下の内容が含まれるように設計されています。

参考文献

refs フォルダには、指定された参照の最新リビジョンを示すファイルが含まれます。例えば、リポジトリの main ブランチからファイルを以前に取得した場合は、refs フォルダに main という名前のファイルが含まれ、そのファイルには現在のヘッドのコミット識別子が格納されます。

mainの最新のコミットがaaaaaaを識別子として持つ場合、aaaaaaが含まれます。

同じブランチが新しいコミットで更新され、その識別子がbbbbbbである場合、そのリファレンスからファイルを再ダウンロードすると、refs/mainファイルの内容がbbbbbbに更新されます。

Blobs

blobsフォルダには、ダウンロードした実際のファイルが含まれています。各ファイルの名前は、そのハッシュ値です。

スナップショット

snapshotsフォルダには、上記のブロブへのシンボリックリンクが含まれています。このフォルダ自体は、既知のリビジョンごとに1つずつの複数のフォルダで構成されています!

上記の説明では、bbbbbb リビジョンのファイルをフェッチする前に、aaaaaa リビジョンのファイルをフェッチしていました。この状況では、snapshots フォルダ内に aaaaaa と bbbbbb という2つのフォルダが存在することになります。

これらのフォルダーのそれぞれには、ダウンロードしたファイル名と同じ名前を持つライブシンボリックリンクが配置されています。例えば、リビジョンaaaaaaのREADME.mdファイルをダウンロードした場合、以下のパスが作成されます。

<CACHE_DIR>/<REPO_NAME>/snapshots/aaaaaa/README.md

README.mdファイルは実際にはシンボリックリンクであり、そのファイルのハッシュを持つブロブにリンクしています。

この方法でスケルトンを作成することで、ファイル共有の仕組みが有効になります。同じファイルがリビジョンbbbbbbで取得された場合、ハッシュ値が同じになるため、ファイルを再ダウンロードする必要はありません。

ツリー

trees フォルダーは、リポジトリが特定のコミット時点で含むファイルのリストをキャッシュします。コミットは不変であるため、そのファイルリストは変更されません。つまり、このリストは、Hub に対して再確認する必要が一切なく、永久にキャッシュできます。

各キャッシュされたリストはコミットハッシュを名前に持ち、trees/aaaaaa.json のような JSON ファイルとして保存されます。そのコミット時点のリポジトリ内の各ファイルについて、ファイルをダウンロードするために必要な情報が記録されています。具体的には、パス、サイズ、ハッシュです。これは通常 Hub が返すのと同じ情報ですが、これを取得するには通常、ファイルごとに 1 回のネットワーク呼び出しが必要です。

このキャッシュはsnapshot_download()によって書き込まれます。コミットを初めてダウンロードする際、ファイル一覧が一度取得され、ここに保存されます。同じコミットを次にダウンロードする際、一覧は再度取得されるのではなく、ディスクから読み込まれます。その結果、すべてがすでにキャッシュされている状態でダウンロードを再実行しても、ネットワーク呼び出しは1回のみで済みます。それは、ブランチ名またはタグ名をコミットハッシュに解決するために必要な呼び出しです。

snapshot_download() と hf_hub_download() は、ネットワーク呼び出しを回避するためにこのキャッシュを読み取ります。コミットハッシュをリビジョンとしてファイルをダウンロードする場合(snapshot_download() が内部で各ファイルに対して行っている処理がまさにこれです)、ダウンロードのメタデータはキャッシュされたファイルリストから読み取られ、ファイルごとのネットワーク呼び出しはスキップされます。つまり、単一のファイルに対する hf_hub_download() も、同じコミットに対して以前に snapshot_download() が保存したファイルリストの恩恵を受けることができます。

キャッシュされたファイルリストは、コミットに何が含まれるべきかを正確に記述しているため、snapshot_download() はローカルスナップショットが完全かどうかを判断することもできます。Hub にアクセスできない場合(オフライン、接続失敗、または local_files_only=True を指定した場合)に、ローカルスナップショットから期待される一部のファイルが欠落している場合、snapshot_download() は部分的なフォルダを返す代わりに IncompleteSnapshotError を発生させます。これ以前は、不完全なスナップショットが静かに返され、ファイルが欠落していることに気づかずに作業を続けてしまう可能性がありました。allow_patterns または ignore_patterns によって除外されたファイルは、欠落としてカウントされません。この例外は、その snapshot_path 属性を通じて不完全なスナップショットへのパスを公開するため、必要に応じて部分的にキャッシュされたファイルを特定できます。

.no_exist(高度な設定)

blobs、refs、snapshotsフォルダに加えて、キャッシュ内に.no_existフォルダが見つかる場合があります。このフォルダは、一度ダウンロードを試みたもののHub上に存在しないファイルを管理します。その構造はsnapshotsフォルダと同じで、既知のリビジョンごとに1つのサブフォルダが作成されます:

<CACHE_DIR>/<REPO_NAME>/.no_exist/aaaaaa/config_that_does_not_exist.json

snapshots フォルダーとは異なり、ファイルは単なる空ファイル(シンボリックリンクなし)です。この例では、ファイル "config_that_does_not_exist.json" は、リビジョン "aaaaaa" において Hub に存在しません。空ファイルのみを保存するため、このフォルダーはディスク使用量の観点から無視できるほど小さいです。

では、なぜこの情報が重要なのか疑問に思われるかもしれません。 一部のケースでは、フレームワークがモデルのオプションファイルを読み込もうとします。オプションファイルが存在しないことを保存しておくことで、存在しうる各オプションファイルごとに1回のHTTP呼び出しを節約できるため、モデルの読み込みが高速になります。 例えば、transformersでは、各トークナイザーが追加のファイルをサポートできます。 マシンでトークナイザーを初めて読み込むと、次の初期化時の読み込み時間を短縮するために、どのオプションファイルが存在し(存在しないのはどれか)、がキャッシュされます。

To test if a file is cached locally (without making any HTTP request), you can use the try_to_load_from_cache() helper. It will either return the filepath (if exists and cached), the object _CACHED_NO_EXIST (if non-existence is cached) or None (if we don’t know).

from huggingface_hub import try_to_load_from_cache, _CACHED_NO_EXIST

filepath = try_to_load_from_cache()
if isinstance(filepath, str):
    # file exists and is cached
    ...
elif filepath is _CACHED_NO_EXIST:
    # non-existence of file is cached
    ...
else:
    # file is not cached
    ...

実際

実際には、キャッシュは以下のツリー構造になっているはずです。

    [  96]  .
    └── [ 160]  models--julien-c--EsperBERTo-small
        ├── [ 160]  blobs
        │   ├── [321M]  403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
        │   ├── [ 398]  7cb18dc9bafbfcf74629a4b760af1b160957a83e
        │   └── [1.4K]  d7edf6bd2a681fb0175f7735299831ee1b22b812
        ├── [  96]  refs
        │   └── [  40]  main
        ├── [ 128]  snapshots
        │   ├── [ 128]  2439f60ef33a0d46d85da5001d52aeda5b00ce9f
        │   │   ├── [  52]  README.md -> ../../blobs/d7edf6bd2a681fb0175f7735299831ee1b22b812
        │   │   └── [  76]  pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
        │   └── [ 128]  bbc77c8132af1cc5cf678da3f1ddf2de43606d48
        │       ├── [  52]  README.md -> ../../blobs/7cb18dc9bafbfcf74629a4b760af1b160957a83e
        │       └── [  76]  pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
        └── [  96]  trees
            ├── [ 521]  2439f60ef33a0d46d85da5001d52aeda5b00ce9f.json
            └── [ 521]  bbc77c8132af1cc5cf678da3f1ddf2de43606d48.json

CACHEDIR.TAG

huggingface_hubは、キャッシュディレクトリ内にCACHEDIR.TAGファイルを自動的に作成します。このタグはCache Directory Tagging Standardに準拠しており、バックアップツール(Borg、restic、rsync など)に対して、そのディレクトリが再ダウンロード可能なキャッシュデータを含むため、バックアップから安全に除外できることを示します。

制限事項

効率的なキャッシュシステムを実現するために、huggingface-hub はシンボリックリンクを使用しています。ただし、すべてのマシンでシンボリックリンクがサポートされているわけではなく、特に Windows 環境では既知の制限事項です。この場合、huggingface_hub は blobs/ ディレクトリを使用せず、代わりにファイルを直接 snapshots/ ディレクトリに保存します。このワークアラウンドにより、ユーザーは Hub からファイルをダウンロードし、キャッシュする操作をまったく同じ方法で行うことができます。また、キャッシュを検査・削除するためのツール(下記参照)もサポートされています。ただし、同じリポジトリの複数のリビジョンをダウンロードした場合、単一のファイルが複数回ダウンロードされる可能性があるため、キャッシュシステムは効率が低下します。

Windowsマシンでシンボリックリンクベースのキャッシュシステムを利用するには、開発者モードを有効にするか、Pythonを管理者として実行する必要があります。

シンボリックリンクを適切に処理できない共有ファイルシステムなど、シンボリックリンクなしのキャッシュモードを能動的に使用したい場合は、HF_HUB_DISABLE_SYMLINKS 環境変数を 1 に設定できます。これにより、ファイルは blobs/ へのシンボリックリンクではなく、snapshots/ に直接コピーされます。

シンボリックリンクがサポートされていない場合、キャッシュシステムの劣化版を使用していることをユーザーに知らせる警告メッセージが表示されます。この警告は、HF_HUB_DISABLE_SYMLINKS_WARNING 環境変数を true に設定することで無効化できます。

リポジトリ間で共有されるブロブ

デフォルトでは、Xet ファイルはリポジトリ間で重複排除されます。hf_xet 経由でダウンロードされた Xet ファイルは、<CACHE_DIR>/blobs/<prefix>/<xet_hash> に一度だけ保存され、リポジトリの blobs/<etag> エントリはそれへの相対シンボリックリンクになります。別のリポジトリが同じファイルが必要な場合、ダウンロードの代わりにシンボリックリンクが作成されます。バイトの転送も追加のディスク容量も不要です。スナップショットのレイアウトは変更されません。マーカーファイルがストアを識別するため、huggingface_hub によって作成されなかった blobs ディレクトリには決してアクセスしません。

共有ファイルには、そのファイルを使用しているリポジトリのブロブを列挙した<xet_hash>.refsマニフェストがあります。hf cache rmはこれを読み取り、削除の影響を受ける共有ファイルのみを確認します。また、hf cache pruneは、キャッシュされたリポジトリがもう使用していない共有ファイルを削除します。マニフェストはあくまでヒントであり、すべてのエントリはファイルシステムと照合されます。メタデータが欠落しているか読み取れないファイルは保持されます。クリーンアップでは、有効なキャッシュエントリを壊すよりも、回収可能なデータを残すことを優先します。

リポジトリごとのサイズは論理的な値であり、共有ファイルはそれを使用するすべてのリポジトリでカウントされます。キャッシュ全体のsize_on_diskは物理的な値であり、各共有ファイルは一度のみカウントされます。これには、もはやどのリポジトリからも使用されていないファイルも含まれます。

旧バージョンのクライアント(huggingface_hub、huggingface.js、hf-hub、llama.cpp、およびシンボリックリンクに従うもの)は、同じリポジトリフォルダ内で、通常どおり読み取りとダウンロードを続行します。ただし、2つの制約があります。

  • huggingface_hub<=1.31 は、削除されたリポジトリの共有ファイルをストアに残したままにします。これらは hf cache ls によってフラグが付けられ、hf cache prune によって削除されます。他のクライアントのキャッシュ削除ツールは、他のリポジトリで使用されている共有ファイルを削除してしまう可能性があります。影響を受けたファイルは、次に使用される際に再ダウンロードされます。hf cache rm、hf cache prune、およびプログラムによる削除には、最新バージョンの huggingface_hub を使用してください。
  • それらのキャッシュスキャナーは、トップレベルのblobsディレクトリを不明なエントリとして報告する場合があります。

ストアはシンボリックリンクベースのキャッシュレイアウトを必要とし、HF_HUB_DISABLE_XET=1 によって無効化されます。ファイル共有に失敗した場合(サポートされていないファイルシステム、権限エラー、既存の未マークの blobs ディレクトリなど)、通常のリポジトリローカルストレージにサイレントにフォールバックします。HF_HUB_DISABLE_SHARED_BLOBS=1 を設定することで、完全にオプトアウトできます。

リビジョンを固定する(高度な設定)

MLライブラリにHubを統合する場合でも、snapshot_download()を1回呼び出すことが推奨されるアプローチです。この呼び出しは、リビジョンを1回だけ解決し、すべてのファイルを並列でダウンロードし、ファイル一覧をキャッシュします。以下は、設定、重み、トークナイザー、プロセッサー、アダプターなど多くのコンポーネントを個別にダウンロードして読み込み、単一の呼び出しを使用できない複雑なライブラリにのみ有用です。

ライブラリが複数のファイルを1つずつダウンロードする場合、各呼び出しでrevision="main"をコミットハッシュに解決し直す必要があります。これによりファイルごとに1回のHTTP呼び出しが発生し、さらに悪いことに、数秒間隔で実行された2回の呼び出しが、その間にリポジトリが更新された場合、異なる2つのコミットに到達する可能性があります。

HfApi.resolve_revision() はリビジョンを一度だけ解決し、ResolvedRevision を返します:

>>> from huggingface_hub import resolve_revision
>>> revision = resolve_revision("openai-community/gpt2")
>>> revision
ResolvedRevision(initial=None, resolved='607a30d783dfa663caf39e06633721c8d4cfcd7e')

ResolvedRevision は str のサブクラスであるため、revision 引数を受け取る huggingface_hub の任意のメソッドに渡すことができます。その文字列値は、ユーザーが最初に要求した値(ここでは "main" であり、そのため読みやすいエラーメッセージが表示されます)であり、.resolved にはコミットハッシュが保持されます。

>>> revision == "main"
True
>>> revision.resolved
'607a30d783dfa663caf39e06633721c8d4cfcd7e'

ダウンロードヘルパー(hf_hub_download()、snapshot_download()、get_cached_repo_tree())はResolvedRevisionを検出し、コミットハッシュを直接使用します。すべてのファイルが同じコミット由来であることが保証され、ファイルがキャッシュされた後はHTTP呼び出しが一切不要になります。

>>> from huggingface_hub import hf_hub_download
>>> config = hf_hub_download("openai-community/gpt2", "config.json", revision=revision)
>>> weights = hf_hub_download("openai-community/gpt2", "model.safetensors", revision=revision)

revision -> commit hash のマッピングは、キャッシュの refs/ フォルダにも書き込まれます(Refs を参照)。これにより、後で Hub にアクセスできない場合(オフラインモード、接続エラー、タイムアウト、Hub の停止)でも、HfApi.resolve_revision() はキャッシュされた値に透明にフォールバックします。キャッシュにも何も存在しない場合は、RevisionResolutionError が発生します。

コミットハッシュは、解決されたリポジトリに対してのみ意味を持ち、ダウンロードヘルパーはそれをそのまま使用します。したがって、ResolvedRevisionは、解決されたリポジトリにのみ渡す必要があります。ライブラリが別のリポジトリ(ベースモデル、アダプター、独立したリポジトリに存在するコンポーネントなど)からもダウンロードする場合は、そのリポジトリ用に解決されたリビジョンが必要です。単にResolvedRevisionをHfApi.resolve_revision()に渡すだけです。これはどのリポジトリに属しているかを記憶しており、最初に要求されたリビジョン(ここでは"main")を新しいリポジトリに対して再度解決します。

>>> other_revision = resolve_revision("openai-community/gpt2-medium", revision=revision)  # resolves "main" again
>>> other_revision.resolved
'6dcaa7a952f72f9298047fd5137cd6e4f05f41da'
>>> config = hf_hub_download("openai-community/gpt2-medium", "config.json", revision=other_revision)

Xetのキャッシュ

より効率的なアップロードを提供するために、hf_xet は既存の huggingface_hub キャッシュに xet ディレクトリを追加します。このディレクトリには、アップロードの重複排除と再開に使用されるシャード(ファイルをチャンクにマッピングするデータ構造)とステージングデータが保存されます。Xet Storage システムの詳細については、このセクションを参照してください。

hf_xet は、ダウンロードにローカルチャンクキャッシュを使用しなくなりました。HF_XET_CHUNK_CACHE_SIZE_BYTES を設定しても、ローカルチャンクキャッシュは有効になりません。ダウンロードされたファイルは引き続き、ファイルベースのキャッシュに保存されます。

デフォルトでは~/.cache/huggingface/xetに配置されるxetディレクトリは、HF_XET_CACHEで設定できます。構造は以下の通りです:

<CACHE_DIR>
├─ xet
│  ├─ environment_identifier
│  │  ├─ shard-cache
│  │  ├─ staging

environment_identifier ディレクトリはエンコードされた文字列です(マシン上では https___cas_serv-tGqkUaZf_CBPHQ6h のように表示される場合があります)。これは開発時に使用され、ローカル版と本番版のキャッシュが同時に存在できるようにします。また、異なる ストレージリージョン にあるリポジトリからダウンロードする際にも使用されます。xet ディレクトリ内に複数のこのようなエントリが表示される場合がありますが、それぞれが異なる環境に対応しており、内部構造は同じです。

内部ディレクトリは、以下の目的で使用されます。

  • shard-cacheには、アップロードパスで利用されるキャッシュされたシャードが含まれています。
  • stagingは、再開可能なアップロードをサポートするために設計されたワークスペースです。

これらは以下に説明されています。

シャードキャッシュとステージングデータは、アップロードの最適化レイヤーとしてhf_xetによって管理されます。ダウンロードされたファイルの管理には、huggingface_hubのファイルベースのキャッシュAPIを使用してください。

shard-cache

このキャッシュは、Hub にコンテンツをアップロードする際に使用されます。ディレクトリはフラットな構造で、シャードファイルのみで構成され、各ファイルはシャード名として ID を使用します。

<CACHE_DIR>
├─ xet
│  ├─ environment_identifier
│  │  ├─ shard-cache
│  │  │  ├─ 1fe4ffd5cf0c3375f1ef9aec5016cf773ccc5ca294293d3f92d92771dacfc15d.mdb
│  │  │  ├─ 906ee184dc1cd0615164a89ed64e8147b3fdccd1163d80d794c66814b3b09992.mdb
│  │  │  ├─ ceeeb7ea4cf6c0a8d395a2cf9c08871211fbbd17b9b5dc1005811845307e6b8f.mdb
│  │  │  ├─ e8535155b1b11ebd894c908e91a1e14e3461dddd1392695ddc90ae54a548d8b2.mdb

shard-cacheには、以下の条件を満たすシャードが含まれます:

  • ローカルで生成され、CASに正常にアップロードされました
  • グローバル重複排除アルゴリズムの一部としてCASからダウンロードされました

Shards はファイルとチャンク間のマッピングを提供します。アップロード中、各ファイルはチャンクに分割され、そのチャンクのハッシュが保存されます。その後、キャッシュ内のすべての Shard が参照されます。Shard に、アップロード中のローカルファイルに存在するチャンクハッシュが含まれている場合、そのチャンクは CAS に既に保存されているため破棄できます。

すべてのシャードには、ダウンロードから3〜4週間という有効期限が設定されています。期限切れのシャードはアップロード時に読み込まれず、期限切れから1週間後に削除されます。

staging

アップロードがリポジトリへの新しいコンテンツのコミット前に終了した場合、ファイル転送を再開する必要があります。ただし、中断前に一部のチャンクが正常にアップロードされている可能性があります。

最初からやり直す必要がないように、staging ディレクトリはアップロード中のワークスペースとして機能し、正常にアップロードされたチャンクのメタデータを保存します。staging ディレクトリの構造は以下の通りです:

<CACHE_DIR>
├─ xet
│  ├─ environment_identifier
│  │  ├─ staging
│  │  │  ├─ shard-session
│  │  │  │  ├─ 906ee184dc1cd0615164a89ed64e8147b3fdccd1163d80d794c66814b3b09992.mdb
│  │  │  │  ├─ xorb-metadata
│  │  │  │  │  ├─ 1fe4ffd5cf0c3375f1ef9aec5016cf773ccc5ca294293d3f92d92771dacfc15d.mdb

ファイルが処理され、チャンクが正常にアップロードされると、そのメタデータがxorb-metadata内にシャードとして保存されます。アップロードセッションを再開すると、各ファイルが再度処理され、このディレクトリ内のシャードが参照されます。正常にアップロード済みのコンテンツはスキップされ、新しいコンテンツはアップロードされ(そのメタデータも保存されます)。

一方、shard-session は処理済みファイルのファイル情報とチャンク情報を保存します。アップロードが正常に完了すると、これらのシャードの内容は、より永続的な shard-cache に移動されます。

制限と限界

shard-cacheには16GBのソフトリミットがあり、HF_XET_SHARD_CACHE_SIZE_LIMIT環境変数で設定できます。このキャッシュを管理するための高レベルAPIはありません。

シャードキャッシュとステージングデータは、アップロードの最適化に使用されます。アセット自体を操作するには、huggingface_hub のキャッシュシステム APIの使用を推奨します。

Xet が使用しているスペースを解放する必要がある場合、またはキャッシュ関連の問題をデバッグする必要がある場合は、<cache_dir> が Hugging Face キャッシュの場所(通常は ~/.cache/huggingface)である rm -rf ~/<cache_dir>/xet を実行して、xet キャッシュを完全に削除するだけです。

xet キャッシュディレクトリツリーの例:

<CACHE_DIR>
├─ xet
│  ├─ environment_identifier
│  │  ├─ shard-cache
│  │  │  ├─ 1fe4ffd5cf0c3375f1ef9aec5016cf773ccc5ca294293d3f92d92771dacfc15d.mdb
│  │  │  ├─ 906ee184dc1cd0615164a89ed64e8147b3fdccd1163d80d794c66814b3b09992.mdb
│  │  │  ├─ ceeeb7ea4cf6c0a8d395a2cf9c08871211fbbd17b9b5dc1005811845307e6b8f.mdb
│  │  │  ├─ e8535155b1b11ebd894c908e91a1e14e3461dddd1392695ddc90ae54a548d8b2.mdb
│  │  ├─ staging
│  │  │  ├─ shard-session
│  │  │  │  ├─ 906ee184dc1cd0615164a89ed64e8147b3fdccd1163d80d794c66814b3b09992.mdb
│  │  │  │  ├─ xorb-metadata
│  │  │  │  │  ├─ 1fe4ffd5cf0c3375f1ef9aec5016cf773ccc5ca294293d3f92d92771dacfc15d.mdb

Xet Storageの詳細については、このセクションを参照してください。

アセットのキャッシュ

Hubからのファイルのキャッシュに加えて、下流のライブラリは、huggingface_hubが直接処理しないHF関連の他のファイル(GitHubからダウンロードしたファイル、前処理済みデータ、ログなど)のキャッシュを必要とすることがよくあります。これらのassetsと呼ばれるファイルをキャッシュするには、cached_assets_path()を使用できます。この小さなヘルパーは、リクエストしたライブラリの名前に基づき、オプションで名前空間とサブフォルダ名に基づいて、HFキャッシュ内のパスを統一された方法で生成します。その目的は、適切なassetsフォルダ内に留まる限り、各下流ライブラリが独自の方式でassetsを管理できるようにすることです(例:構造に関するルールなし)。これにより、これらのライブラリはhuggingface_hubのツールを活用してキャッシュを管理でき、特にCLIコマンドからassetsの一部をスキャンして削除できます。

from huggingface_hub import cached_assets_path

assets_path = cached_assets_path(library_name="datasets", namespace="SQuAD", subfolder="download")
something_path = assets_path / "something.json" # Do anything you like in your assets folder !

cached_assets_path() はアセットを保存するための推奨方法ですが、必須ではありません。ライブラリが独自のキャッシュを使用している場合は、それをそのまま使用して問題ありません。

実践におけるアセット

実際には、アセットのキャッシュは以下のツリー構造になるはずです。

    assets/
    └── datasets/
    │   ├── SQuAD/
    │   │   ├── downloaded/
    │   │   ├── extracted/
    │   │   └── processed/
    │   ├── Helsinki-NLP--tatoeba_mt/
    │       ├── downloaded/
    │       ├── extracted/
    │       └── processed/
    └── transformers/
        ├── default/
        │   ├── something/
        ├── bert-base-cased/
        │   ├── default/
        │   └── training/
    hub/
    └── models--julien-c--EsperBERTo-small/
        ├── blobs/
        │   ├── (...)
        │   ├── (...)
        ├── refs/
        │   └── (...)
        └── [ 128]  snapshots/
            ├── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
            │   ├── (...)
            └── bbc77c8132af1cc5cf678da3f1ddf2de43606d48/
                └── (...)

ファイルベースのキャッシュを管理する

キャッシュを確認する

現在、キャッシュされたファイルはローカルディレクトリから削除されません。ブランチの新しいリビジョンをダウンロードしても、以前にダウンロードしたファイルは、再度必要になった場合に備えて保持されます。そのため、どのリポジトリやリビジョンが最もディスク容量を占有しているかを確認するために、キャッシュディレクトリを調査すると便利です。huggingface_hub は、hf CLI または Python から使用できるヘルパーを提供しています。

ターミナルからキャッシュを検査する

hf cache ls を実行して、ローカルに保存されている内容を確認します。デフォルトでは、このコマンドはリポジトリごとに情報を集約します:

➜ hf cache ls
ID                                   SIZE   LAST_ACCESSED LAST_MODIFIED REFS
------------------------------------ ------- ------------- ------------- -------------------
dataset/glue                         116.3K 4 days ago     4 days ago     2.4.0 main 1.17.0
dataset/google/fleurs                 64.9M 1 week ago     1 week ago     main refs/pr/1
model/Jean-Baptiste/camembert-ner    441.0M 2 weeks ago    16 hours ago   main
model/bert-base-cased                  1.9G 1 week ago     2 years ago
model/t5-base                          10.1K 3 months ago   3 months ago   main
model/t5-small                        970.7M 3 days ago     3 days ago     main refs/pr/1

Found 6 repo(s) for a total of 12 revision(s) and 3.4G on disk.

--revisions を追加すると、キャッシュされたスナップショットをすべて一覧表示できます。フィルターをチェーンすることで、重要な情報に絞り込むことができます。フィルターは人間が読みやすいサイズや期間を認識するため、size>1GB や accessed>30d のような式はそのまま動作します:

➜ hf cache ls --revisions --filter "size>1GB" --filter "accessed>30d"
ID                                   REVISION            SIZE   LAST_MODIFIED REFS
------------------------------------ ------------------ ------- ------------- -------------------
model/bert-base-cased                6d1d7a1a2a6cf4c2    1.9G  2 years ago
model/t5-small                       1c610f6b3f5e7d8a    1.1G  3 months ago  main

Found 2 repo(s) for a total of 2 revision(s) and 3.0G on disk.

機械可読の出力が必要ですか? --format json を使用すると構造化オブジェクトが、--format csv を使用するとスプレッドシート向けの出力が得られます。あるいは --quiet を使用すると識別子のみが 1 行ずつ出力されるため、他のツールにパイプで渡すことができます。 --sort を使用すると、accessed、modified、name、または size でエントリを並べ替えられます (順序を制御するには :asc または :desc を追加します)。また、 --limit を使用すると結果を上位 N 件のエントリに制限できます。 HF_HOME 外部に保存されているキャッシュを検査する必要がある場合は、これらのオプションを --cache-dir と組み合わせて使用してください。

一般的なシェルツールでフィルタリングする

Tabular output(表形式の出力)により、すでに慣れ親しんでいるツールをそのまま使い続けることができます。例えば、以下のスニペットはt5-smallに関連するすべてのキャッシュされたリビジョンを検索します。

➜ eval "hf cache ls --revisions" | grep "t5-small"
model/t5-small                       1c610f6b3f5e7d8a    1.1G  3 months ago  main
model/t5-small                       8f3ad1c90fed7a62    820.1M 2 weeks ago   refs/pr/1

Pythonからキャッシュをインスペクトする

より高度な使用方法として、CLIツールから呼び出されるPythonユーティリティであるscan_cache_dir()を使用します。

4つのデータクラスを軸に構成された詳細なレポートを取得するために使用できます。

…

>>> from huggingface_hub import scan_cache_dir

>>> hf_cache_info = scan_cache_dir()
HFCacheInfo(
    size_on_disk=3398085269,
    repos=frozenset({
        CachedRepoInfo(
            repo_id='t5-small',
            repo_type='model',
            repo_path=PosixPath(...),
            size_on_disk=970726914,
            nb_files=11,
            last_accessed=1662971707.3567169,
            last_modified=1662971107.3567169,
            revisions=frozenset({
                CachedRevisionInfo(
                    commit_hash='d78aea13fa7ecd06c29e3e46195d6341255065d5',
                    size_on_disk=970726339,
                    snapshot_path=PosixPath(...),
                    # No `last_accessed` as blobs are shared among revisions
                    last_modified=1662971107.3567169,
                    files=frozenset({
                        CachedFileInfo(
                            file_name='config.json',
                            size_on_disk=1197
                            file_path=PosixPath(...),
                            blob_path=PosixPath(...),
                            blob_last_accessed=1662971707.3567169,
                            blob_last_modified=1662971107.3567169,
                        ),
                        CachedFileInfo(...),
                        ...
                    }),
                ),
                CachedRevisionInfo(...),
                ...
            }),
        ),
        CachedRepoInfo(...),
        ...
    }),
    warnings=[
        CorruptedCacheException("Snapshots dir doesn't exist in cached repo: ..."),
        CorruptedCacheException(...),
        ...
    ],
)

キャッシュを確認する

huggingface_hubは、キャッシュされたファイルがHub上のチェックサムと一致していることを検証できます。特定のリポジトリの特定のリビジョンのファイル整合性を検証するには、hf cache verify CLIを使用します。

>>> hf cache verify meta-llama/Llama-3.2-1B-Instruct
✅ Verified 13 file(s) for 'meta-llama/Llama-3.2-1B-Instruct' (model) in ~/.cache/huggingface/hub/models--meta-llama--Llama-3.2-1B-Instruct/snapshots/9213176726f574b556790deb65791e0c5aa438b6
  All checksums match.

特定のキャッシュされたリビジョンを検証します:

>>> hf cache verify meta-llama/Llama-3.1-8B-Instruct --revision 0e9e39f249a16976918f6564b8830bc894c89659

使用法とオプションの完全なリストについては、hf cache verify CLI リファレンスを参照してください。

キャッシュをクリーンアップ

キャッシュのスキャンは興味深いですが、次に実行したいのは通常、ドライブの空き容量を確保するために一部のデータを削除することです。これはhf cache rmおよびhf cache pruneのCLIコマンドで可能です。また、キャッシュのスキャン時に返されるHFCacheInfoオブジェクトから、delete_revisions()およびdelete_files()のヘルパーをプログラム的に使用することもできます。

削除戦略

一部のキャッシュを削除するには、削除するリビジョンのリストを渡す必要があります。ツールはこのリストに基づいて、スペースを解放するための戦略を定義します。削除されるファイルとフォルダを説明するDeleteCacheStrategyオブジェクトを返します。 DeleteCacheStrategyは、解放されるスペースの量を確認できます。 削除に同意したら、削除を実行して有効にする必要があります。 不整合を避けるため、戦略オブジェクトを手動で編集することはできません。

リビジョンを削除する戦略は以下の通りです。

  • リビジョンのシンボリックリンクを含むsnapshotフォルダが削除されます。
  • 削除対象のリビジョンのみが参照しているblobsファイルも削除されます。
  • リビジョンが1つ以上のrefsにリンクされている場合、参照は削除されます。
  • リポジトリのすべてのリビジョンが削除された場合、キャッシュされたリポジトリ全体が削除されます。

delete_files() を使用して個別のファイルを削除する場合も、同じロジックが適用されます。スナップショットのエントリは削除され、他のキャッシュされたファイルがそれらを参照していない場合のみ、そのブロブが削除されます。リファレンスとスナップショットフォルダは保持されます。

リビジョンハッシュはすべてのリポジトリ間で一意です。そのため、hf cache rm は、リポジトリ識別子(例: model/bert-base-uncased)または単独のリビジョンハッシュのいずれかを引数として受け付けます。ハッシュを指定する場合は、リポジトリを別途指定する必要はありません。

リビジョンがキャッシュに見つからない場合、無視されます。また、ファイルまたはフォルダの削除を試みた際にそれらが存在しない場合、警告がログに記録されますが、エラーはスローされません。DeleteCacheStrategyオブジェクトに含まれる他のパスに対する削除は続行されます。

ターミナルからキャッシュをクリアする

hf cache rm を使用して、リポジトリまたはリビジョンをキャッシュから完全に削除します。1 つ以上のリポジトリ識別子(例: model/bert-base-uncased)またはリビジョンハッシュを指定します:

➜ hf cache rm model/bert-base-cased
About to delete 1 repo(s) totalling 1.9G.
  - model/bert-base-cased (entire repo)
Proceed with deletion? [y/N]: y
Deleted 1 repo(s) and 1 revision(s); freed 1.9G.

hf cache rmをhf cache ls --quietと組み合わせて、フィルタで特定されたエントリを一括削除することもできます。

>>> hf cache rm $(hf cache ls --filter "accessed>1y" -q) -y
About to delete 2 repo(s) totalling 5.31G.
  - model/meta-llama/Llama-3.2-1B-Instruct (entire repo)
  - model/hexgrad/Kokoro-82M (entire repo)
Deleted 2 repo(s) and 2 revision(s); freed 5.31G.

同じ呼び出し内でリポジトリとリビジョンを混在できます。--dry-run を追加して影響をプレビューするか、スクリプト実行時に確認プロンプトをスキップするには --yes を使用します:

➜ hf cache rm model/t5-small 8f3ad1c --dry-run
About to delete 1 repo(s) and 1 revision(s) totalling 1.1G.
  - model/t5-small:
      8f3ad1c [main] 1.1G
Dry run: no files were deleted.

リポジトリ全体ではなく単一のファイル(例えば、GGUF量子化ファイルなど)を削除するには、hf://ファイルURIを渡します。ファイルはリポジトリのすべてのキャッシュ済みリビジョンから削除され、他のキャッシュ済みファイルがまだ参照していない場合のみ、そのblobが削除されます。リビジョンは引き続き使用可能であり、削除されたファイルは次に必要になった際に再度ダウンロードされます。パスは完全一致でなければなりません。フォルダやglobパターンはサポートされていません。

➜ hf cache rm hf://models/unsloth/gemma-3-27b-it-GGUF/gemma-3-27b-it-Q4_K_M.gguf --dry-run
About to delete 1 file(s) totalling 16.5G.
  - model/unsloth/gemma-3-27b-it-GGUF@3f4b5c1d2e6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c/gemma-3-27b-it-Q4_K_M.gguf
Dry run: no files were deleted.

デフォルトのキャッシュディレクトリ以外で作業する場合は、コマンドに--cache-dir PATHを併せて使用してください。

キャッシュの不要なファイルをまとめて整理するには、hf cache pruneを実行します。これにより、ブランチやタグから参照されなくなったリビジョン、中断されたダウンロードで残った.incompleteファイル、およびキャッシュされたリポジトリから参照されなくなった共有ブロブが自動的に削除されます。

➜ hf cache prune
About to delete 3 unreferenced revision(s) and 2 incomplete download(s) (2.4G total).
  - model/t5-small:
      1c610f6b [refs/pr/1] 820.1M
      d4ec9b72 [(detached)] 640.5M
  - dataset/google/fleurs:
      2b91c8dd [(detached)] 937.6M
Proceed? [y/N]: y
Deleted 3 unreferenced revision(s) and 2 incomplete download(s); freed 2.4G.

.incomplete ファイルは、ダウンロードが中断された際に残る部分のブロブです。リビジョンベースのスキャンでは追跡されないため、hf cache ls はこれらをヒント(Found X incomplete download(s) ...)としてのみ表示し、実際に削除するのは hf cache prune コマンドです。hf cache rm は、リポジトリ全体を削除する場合を除き、これらには一切触れません。

両方のコマンドは--dry-run、--yes、--cache-dirをサポートしており、必要に応じてプレビュー、自動化、および代替のキャッシュディレクトリを指定できます。

Pythonからキャッシュをクリアする

より柔軟に操作するために、delete_revisions()メソッドをプログラム的に使用することもできます。簡単な例を以下に示します。詳細はリファレンスを参照してください。

>>> from huggingface_hub import scan_cache_dir

>>> delete_strategy = scan_cache_dir().delete_revisions(
...     "81fd1d6e7847c99f5862c9fb81387956d99ec7aa"
...     "e2983b237dccf3ab4937c97fa717319a9ca1a96d",
...     "6c0e6080953db56375760c0471a8c5f2929baf11",
... )
>>> print("Will free " + delete_strategy.expected_freed_size_str)
Will free 8.6G

>>> delete_strategy.execute()
Update on GitHub