Hub Python Library documentation

理解缓存

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v2.4.0).
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 下载到这些文件夹中。缓存机制可确保如果文件已存在且未更新,则不会重复下载;但如果文件已更新,且您请求的是最新版本,则会下载最新文件(同时保留旧版本文件,以便您再次需要时使用)。

为了实现这一点,所有文件夹都包含相同的结构:

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

每个文件夹旨在包含以下内容:

参考文献

refs 文件夹包含指示给定引用最新修订的文件。例如,如果我们之前从某个仓库的 main 分支获取了文件,那么 refs 文件夹中将包含一个名为 main 的文件,该文件本身包含当前头部的提交标识符。

如果 main 的最新提交标识符为 aaaaaa,那么它将包含 aaaaaa。

如果该分支被更新为一个新提交,其标识符为 bbbbbb,那么从该引用重新下载文件会将 refs/main 文件更新为包含 bbbbbb。

Blobs

blobs 文件夹包含我们下载的实际文件。每个文件的名称都是其哈希值。

快照

snapshots 文件夹包含指向上述 blob 的符号链接。它本身由多个文件夹组成:每个已知的修订版本对应一个文件夹!

在上面的说明中,我们最初从 aaaaaa 版本获取了一个文件,然后才从 bbbbbb 版本获取文件。在这种情况下,snapshots 文件夹中现在会有两个文件夹:aaaaaa 和 bbbbbb。

在这些文件夹中的每一个中,都存在符号链接,其名称为我们已下载的文件名。例如,如果我们下载了修订版本 aaaaaa 的 README.md 文件,则会有以下路径:

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

该 README.md 文件实际上是一个符号链接,指向包含该文件哈希值的 blob。

通过这种方式创建骨架,我们开启了文件共享机制:如果同一个文件是在修订版本 bbbbbb 中获取的,那么它会有相同的哈希值,因此无需重新下载该文件。

树

trees 文件夹会缓存某个仓库在特定提交(commit)下包含的文件列表。由于提交是不可变的,其文件列表永远不会改变。这意味着该列表可以永久缓存,无需再与 Hub 进行核对。

每个缓存列表都以提交哈希值命名,并存储为 JSON 文件,例如 trees/aaaaaa.json。对于该提交下的仓库中的每个文件,它都会记录下载该文件所需的信息:其路径、大小和哈希值。这些信息与 Hub 通常返回的内容相同,但正常情况下,获取每个文件的信息都需要一次网络调用。

此缓存由 snapshot_download() 写入。首次下载某个 commit 时,文件列表会被获取一次并保存在此处。下次下载相同的 commit 时,列表将从磁盘读取,而无需再次获取。因此,当所有内容均已缓存时,重新运行下载操作仅需一次网络调用:即用于将分支或标签名称解析为 commit 哈希值的那次调用。

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 文件夹相同,每个已知的修订版本对应一个子文件夹:

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

与 snapshots 文件夹不同,此处的文件是简单的空文件(没有符号链接)。在本示例中,文件 "config_that_does_not_exist.json" 在 Hub 的 "aaaaaa" 版本中并不存在。由于该文件夹仅存储空文件,因此其磁盘占用可以忽略不计。

那么现在你可能会问,这些信息为什么重要? 在某些情况下,框架会尝试为模型加载可选文件。记录可选文件不存在这一事实可以加快模型加载速度,因为每个可能的可选文件都能节省一次 HTTP 调用。 例如,在 transformers 中,每个 tokenizer 都可以支持额外的文件。 第一次在你的机器上加载 tokenizer 时,它会缓存哪些可选文件存在(以及哪些不存在),从而加快后续初始化的加载时间。

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。文件将直接复制到 snapshots/ 中,而不是通过符号链接指向 blobs/。

当不支持符号链接时,会向用户显示一条警告消息,以提醒他们正在使用功能受限的缓存系统版本。通过将环境变量 HF_HUB_DISABLE_SYMLINKS_WARNING 设置为 true,可以禁用此警告。

跨仓库共享的 Blob

默认情况下,Xet 文件还会在仓库之间进行去重。通过 hf_xet 下载的 Xet 文件仅在 <CACHE_DIR>/blobs/<prefix>/<xet_hash> 处存储一次,而该仓库的 blobs/<etag> 条目是指向它的相对符号链接。当另一个仓库需要相同的文件时,它会获得一个符号链接而非下载:不传输任何字节,也不占用额外空间。快照布局保持不变。一个标记文件用于标识存储,因此由 huggingface_hub 之外的方式创建的 blobs 目录永远不会被修改。

每个共享文件都有一个 <xet_hash>.refs 清单,列出了使用该文件的仓库 blob。hf cache rm 会读取该清单,以仅检查受删除操作影响的共享文件;hf cache prune 则会移除不再被任何已缓存仓库使用的共享文件。该清单仅作为提示:每个条目都会与文件系统核对,若文件的元数据缺失或不可读,则保留该文件。清理操作倾向于保留可回收的数据,而不是破坏有效的缓存条目。

每个仓库的大小保持逻辑一致,因此共享文件会被计入每个使用它的仓库。整个缓存的 size_on_disk 是物理大小:每个共享文件只计算一次,包括那些不再被任何仓库使用的文件。

旧版客户端(huggingface_hub、huggingface.js、hf-hub、llama.cpp,以及任何遵循符号链接的客户端)仍可在相同的仓库文件夹中正常读取和下载。存在两个限制:

  • 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 可完全退出该功能。

固定修订版本(高级)

如果您正在将 Hub 集成到某个 ML 库中,snapshot_download() 单次调用仍然是推荐的方法:它会一次性解析 revision,并行下载所有内容,并缓存文件列表。以下内容仅适用于那些需要分别下载和加载多个组件(config、weights、tokenizer、processor、adapters 等)且无法使用单次调用的复杂库。

当库逐个下载多个文件时,每次调用都必须将 revision="main" 重新解析为提交哈希。这会导致每个文件产生一次 HTTP 调用,更糟糕的是,如果仓库在两次调用之间被更新,相隔几秒的两次调用可能会落在两个不同的提交上。

HfApi.resolve_revision() 会解析一次 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 不会启用该功能。下载的文件仍会缓存在 基于文件的缓存 中。

xet 目录默认位于 ~/.cache/huggingface/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 周。已过期的分片在上传时不会被加载,并在过期一周后被删除。

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 占用的空间,或者需要调试任何潜在的缓存相关问题,只需运行 rm -rf ~/<cache_dir>/xet 即可完全删除 xet 缓存,其中 <cache_dir> 是您的 Hugging Face 缓存位置,通常为 ~/.cache/huggingface

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 的文件外,下游库通常还需要缓存与 HF 相关但并非由 huggingface_hub 直接处理的其他文件(例如:从 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 仅打印标识符(每行一个),以便将其通过管道传递给其他工具。使用 --sort 按 accessed、modified、name 或 size 对条目进行排序(附加 :asc 或 :desc 以控制排序顺序),并使用 --limit 将结果限制为前 N 个条目。当需要检查存储在 HF_HOME 之外的缓存时,将这些选项与 --cache-dir 结合使用。

使用常用 shell 工具进行过滤

表格化输出意味着您可以继续使用熟悉的工具。例如,下面的代码片段可以找到与 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 中检查缓存

如需更高级的用法,请使用 scan_cache_dir(),这是 CLI 工具调用的 Python 实用函数。

您可以使用它来获取围绕 4 个 dataclass 组织的详细报告:

这是一个简单的使用示例。有关详细信息,请参阅参考文档。

>>> 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 文件也会被删除。
  • 如果某个修订版本关联了一个或多个refs,则引用将被删除。
  • 如果某个仓库的所有修订版本都被删除,则整个缓存的仓库将被删除。

使用 delete_files() 删除单个文件遵循相同的逻辑:快照条目会被移除,并且仅当没有其他缓存文件引用其 blob 时,才会删除该 blob。Refs 和快照文件夹会被保留。

修订哈希在所有仓库中都是唯一的。因此,hf cache rm 接受仓库标识符(例如 model/bert-base-uncased)或单独的修订哈希;当传入哈希时,无需单独指定仓库。

如果在缓存中未找到某个修订版本,它将被静默忽略。此外,如果在尝试删除文件或文件夹时无法找到该文件或文件夹,系统会记录一条警告,但不会抛出错误。删除操作将继续处理 DeleteCacheStrategy 对象中包含的其他路径。

从终端清理缓存

使用 hf cache rm 从缓存中永久删除仓库或修订版本。传入一个或多个仓库标识符(例如 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 时,该 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 文件,以及不再被任何缓存仓库引用的共享 blob:

➜ 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