ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

huggingface_hub 缓存系统完全指南:结构原理、扫描分析与空间清理实战

huggingface_hub 缓存系统完全指南:结构原理、扫描分析与空间清理实战 开发工具CLI机器学习【免费下载链接】huggingface_hubThe official CLI and Python client for the Hugging Face Hub.项目地址https://gitcode.com/gh_mirrors/hu/huggingface_hub点击查看免费下载导读huggingface_hub作为 Hugging Face Hub 的官方 CLI 与 Python 客户端其本地缓存系统是所有依赖 Hub 的库如 transformers、datasets共享的中央仓库。本文基于 docs/source/de/guides/manage-cache.md 展开完整讲解缓存目录的结构设计refs / blobs / snapshots / trees / .no_exist、跨 revision 去重下载的底层原理、Windows 无符号链接环境的限制与对策以及如何使用hf cache ls / rm / prune命令和scan_cache_dir、delete_revisions等 Python 接口扫描、验证并清理缓存、释放磁盘空间。读完本文你将能够解释缓存目录树中每一个目录的用途并通过命令行或 Python 精确管理自己的本地缓存。理解缓存系统Caching verstehenHugging Face Hub 的缓存系统被设计为所有依赖 Hub 的库之间共享的中央缓存并在 v0.8.0 中进行了升级其核心目标是在不同 revision 之间避免重复下载相同文件。缓存系统整体结构如下CACHE_DIR ├─ MODELS ├─ DATASETS ├─ SPACES默认的CACHE_DIR位于用户主目录下。它可以通过以下两种方式自定义在所有方法中传入cache_dir参数设置环境变量HF_HOME或HF_HUB_CACHE。从源码看constants.py 中默认路径定义为default_cache_path os.path.join(HF_HOME, hub)而HF_HUB_CACHE优先读取环境变量未设置时回退到该默认路径。模型、数据集和 Space 共享同一根目录。每个仓库文件夹的命名编码了仓库类型、命名空间组织或用户名如存在与仓库名称中间以--分隔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 ...下面逐一解析这些目录的职责。refs引用 → commit 的映射refs目录中的文件记录某个引用reference指向的最新 revision。例如如果你曾从某仓库的main分支拉取过文件refs目录下就会有一个名为main的文件其内容是该分支当前 HEAD 的 commit 标识符。若main最新 commit 的标识符为aaaaaa则refs/main内容为aaaaaa若同一分支被更新到新 commitbbbbbb再次从该引用下载文件时refs/main会被更新为bbbbbb。这个设计使分支名/标签名能够在本地快速解析为具体的 commit hash。相关逻辑可以在 file_download.py 的try_to_load_from_cache中看到解析 revision 时先读取refs/revision文件内容。blobs真正存储文件内容blobs目录存放实际下载的文件每个文件的文件名就是其内容的哈希值。由于文件名即哈希不同 revision 中内容相同的文件会拥有相同的 blob天然实现内容寻址content-addressing这正是跨 revision 去重的物理基础。snapshotsrevision 视角的符号链接视图snapshots目录包含指向上述 blobs 的符号链接symlink其内部按已知 revision分目录。仍以上述例子先下载了 revisionaaaaaa的文件再下载 revisionbbbbbb的文件则snapshots下会存在aaaaaa与bbbbbb两个目录。每个 revision 目录中的符号链接以文件名为名。例如在 revisionaaaaaa下载了README.md路径即为CACHE_DIR/REPO_NAME/snapshots/aaaaaa/README.md这个README.md实际上是链接到哈希命名 blob 的符号链接。通过这样的骨架设计实现了文件共享机制如果 revisionbbbbbb中获取到的是同一文件其哈希相同就无需重新下载。treescommit 文件列表缓存源码补充除德国语文档描述的refs/blobs/snapshots外当前仓库的英文版文档 docs/source/en/guides/manage-cache.md 还说明了trees目录它按 commit hash 缓存某个提交包含的文件清单每个文件的路径、大小与哈希以 JSON 形式存放在trees/commit_hash.json。commit 不可变因此文件列表可以永久缓存而无需再次向 Hub 校验。该缓存由snapshot_download写入snapshot_download与hf_hub_download都会读取它来省去按文件的网络请求。.no_exist进阶缓存文件不存在除了blobs、refs、snapshots缓存中可能还有一个.no_exist目录它记录你曾尝试下载但在 Hub 上不存在的文件。其结构与snapshots相同每个已知 revision 一个子目录CACHE_DIR/REPO_NAME/.no_exist/aaaaaa/config_that_does_not_exist.json与snapshots不同这里的文件是简单的空文件非符号链接。上例表示config_that_does_not_exist.json在 revisionaaaaaa中不存在于 Hub。由于只存空文件其磁盘占用可以忽略不计。为什么需要记录不存在某些框架会尝试为模型加载可选文件。把可选文件的不存在性缓存下来每次加载模型就能省去每个可选文件对应的 1 次 HTTP 请求。transformers就是典型案例每个 tokenizer 可能支持额外文件首次加载时会缓存哪些可选文件存在哪些不存在从而加速后续初始化。用 try_to_load_from_cache 无网络探测缓存要在不发起任何 HTTP 请求的情况下测试文件是否已在本地缓存可以使用try_to_load_from_cache辅助函数。它的返回有三种情况文件路径存在且已缓存、_CACHED_NO_EXIST对象不存在这一事实已被缓存或None无法确定。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 ...从源码 file_download.py 可以看到其判定顺序先检查refs目录解析 revision再检查.no_exist/revision/filename是否存在存在则返回_CACHED_NO_EXIST随后检查snapshots目录中是否存在对应 revision 与文件。实际缓存目录示例实践中一个缓存仓库大致呈现如下节选自文档的tree输出[ 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注意pytorch_model.bin在两个 revision 中都指向blobs/403450e2...同一哈希因此该文件在磁盘上只存一份——这正是跨 revision 去重的直观体现。CACHEDIR.TAG 标签源码补充huggingface_hub会在缓存目录内自动创建CACHEDIR.TAG文件遵循Cache Directory Tagging Standard告知备份工具如 Borg、restic、rsync该目录包含可重新下载的缓存数据可安全地从备份中排除。相关写入逻辑位于仓库的缓存工具模块中属于缓存目录的自动化治理细节。限制Windows 与符号链接为保证缓存高效huggingface_hub依赖符号链接但并非所有机器都支持符号链接——这在 Windows 上是已知限制。不支持时huggingface_hub不再使用blobs/目录而是把文件直接存放在snapshots/目录。这一折衷方案让用户仍能以完全相同的方式下载和缓存 Hub 文件且下述缓存检查与删除工具同样可用但缓存效率降低——下载同一仓库的多个 revision 时单个文件可能被下载多次。若希望在 Windows 机器上享受基于符号链接的缓存需要启用开发者模式或将 Python 以管理员身份运行。当符号链接不受支持时用户会看到一条警告提示正在使用降级版缓存。可通过设置环境变量HF_HUB_DISABLE_SYMLINKS_WARNING为true来关闭该警告。此外若想主动使用无符号链接模式例如在不善处理符号链接的共享文件系统上可从当前仓库的 constants.py 看到HF_HUB_DISABLE_SYMLINKS环境变量设置为1后文件会被直接复制进snapshots/而非链接到blobs/。缓存资产Assets zwischenspeichern除了缓存来自 Hub 的文件下游库经常还需要缓存其他与 HF 相关但不由huggingface_hub直接处理的文件例如从 GitHub 下载的文件、预处理数据、日志等。这些文件被称为assets可通过cached_assets_path缓存。这个小型辅助函数基于请求库的名称以及可选的命名空间与子文件夹名以统一方式在 HF 缓存中生成路径。设计目标是每个下游库在自己的 assets 文件夹内按各自方式管理资产结构不限并可以利用huggingface_hub提供的工具管理缓存尤其是通过 CLI 命令扫描和删除部分 assets。from huggingface_hub import cached_assets_path assets_path cached_assets_path(library_namedatasets, namespaceSQuAD, subfolderdownload) something_path assets_path / something.json # Machen Sie, was Sie möchten, in Ihrem Assets-Ordner![!TIP]cached_assets_path是存储资产的推荐方式但并非强制。如果你的库已有自己的缓存完全可以继续使用从源码 src/huggingface_hub/utils/_cache_assets.py 看其实现要点包括未指定assets_dir时默认使用HF_ASSETS_CACHE即HF_HOME / assets见 constants.py也可用HF_ASSETS_CACHE环境变量或assets_dir参数覆盖路径为三层深度assets_dir / library_name / namespace / subfoldernamespace与subfolder缺省为defaultlibrary_name必填名称中的空格、/、\会被替换为--避免产生路径问题返回前会执行mkdir(exist_okTrue, parentsTrue)保证返回路径一定存在且为目录。Assets 实际目录结构实践中 assets 缓存与 Hub 缓存并列形如下述目录树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/ └── (...)扫描缓存Cache scannen目前缓存的旧文件永远不会自动从本地目录删除下载分支的新 revision 时旧文件会保留以备再次使用。因此扫描缓存目录、找出占用磁盘最多的仓库与 revision 就非常有用。huggingface_hub提供了可通过hfCLI 或 Python 脚本调用的辅助工具。在终端中检查缓存最便捷的方式是执行hf cache ls。默认情况下它按仓库聚合信息列出所有已缓存仓库的大小、最后访问时间、最后修改时间与引用的 revisionrefs➜ 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可切换到 snapshotrevision级别的视图。过滤器支持人类可读的取值例如size1GB或accessed30d开箱即用➜ hf cache ls --revisions --filter size1GB --filter accessed30d 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只输出标识符。所有变体都可与--cache-dir组合用于检查不在HF_HOME下的缓存。用 Shell 工具过滤表格输出可继续交给熟悉的命令行工具处理。下面的例子展示t5-small的全部 revision➜ 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 工具函数定义见 src/huggingface_hub/utils/_cache_manager.py。调用后返回围绕4 个数据类组织的详细报告[HFCacheInfo]scan_cache_dir返回的完整报告[CachedRepoInfo]某个已缓存仓库的信息[CachedRevisionInfo]仓库内某个已缓存 revision即 snapshot的信息[CachedFileInfo]snapshot 中某个已缓存文件的信息这些数据类均为 frozen dataclass见 _cache_manager.py并提供size_on_disk_str、last_accessed_str等人类可读属性以及CachedRepoInfo.cache_id如model/t5-small与refs映射等便捷属性。简单使用示例如下完整参数见参考文档 from huggingface_hub import scan_cache_dir hf_cache_info scan_cache_dir() HFCacheInfo( size_on_disk3398085269, reposfrozenset({ CachedRepoInfo( repo_idt5-small, repo_typemodel, repo_pathPosixPath(...), size_on_disk970726914, nb_files11, last_accessed1662971707.3567169, last_modified1662971107.3567169, revisionsfrozenset({ CachedRevisionInfo( commit_hashd78aea13fa7ecd06c29e3e46195d6341255065d5, size_on_disk970726339, snapshot_pathPosixPath(...), # No last_accessed as blobs are shared among revisions last_modified1662971107.3567169, filesfrozenset({ CachedFileInfo( file_nameconfig.json, size_on_disk1197 file_pathPosixPath(...), blob_pathPosixPath(...), blob_last_accessed1662971707.3567169, blob_last_modified1662971107.3567169, ), CachedFileInfo(...), ... }), ), CachedRevisionInfo(...), ... }), ), CachedRepoInfo(...), ... }), warnings[ CorruptedCacheException(Snapshots dir doesnt exist in cached repo: ...), CorruptedCacheException(...), ... ], )值得注意的实现细节均可从源码确认单个CachedRevisionInfo没有last_accessed字段因为 blob 在多个 revision 间共享无法可靠地归属到单一 revision见 _cache_manager.py扫描过程中损坏的仓库会被跳过但抛出的CorruptedCacheException会被捕获并收集在HFCacheInfo.warnings列表中使扫描得以继续见 scan_cache_dir 的 docstring。清空缓存Cache leeren扫描缓存很有用但真正要做的事情通常是删除部分内容以释放磁盘空间。这可以通过hf cache rm和hf cache prune两个 CLI 命令完成也可以在 Python 中调用扫描结果 [HFCacheInfo] 对象上的delete_revisions辅助方法实现。删除策略Löschstrategie要删除缓存你需要传入一组待删除的 revision。工具会据此制定释放空间的策略并返回一个 [DeleteCacheStrategy] 对象定义见 _cache_manager.py描述将删除哪些文件与文件夹并给出预计释放的空间。确认后必须调用execute()才能真正执行删除。为防止偏差策略对象不可手动修改。删除 revision 的策略如下删除包含该 revision 符号链接的snapshot目录仅被待删除 revision 引用的 blob 文件也会被删除若某 revision 关联了 1 个或多个refs这些引用会被删除若仓库的所有 revision 均被删除则删除整个缓存仓库。从源码看HFCacheInfo.delete_revisions先按 commit hash 匹配待删除 revisionhash 在全部仓库间唯一再区分整仓删除与部分 revision 删除两种情形逐一收集要删除的 repos / snapshots / refs / blobs最后返回一个未执行的DeleteCacheStrategy。策略对象还提供expected_freed_size_str属性供预览。execute()的删除顺序是先删 snapshot 条目与仓库目录再删 snapshot 目录、refs 文件最后删 blob 文件避免出现引用指向已删除目标的中间状态见 _cache_manager.py。[!TIP] revision 的哈希在所有仓库间唯一。因此hf cache rm既可以接收仓库标识如model/bert-base-uncased也可以只接收单个 revision 哈希——传哈希时无需额外指定仓库。[!WARNING] 若某个 revision 在缓存中未找到会被静默忽略。另外删除时若某个文件或文件夹不存在会记录警告但不会抛出错误对 [DeleteCacheStrategy] 中其他路径的删除会继续进行。从终端清空缓存使用hf cache rm删除缓存的仓库或单个 revision传入一个或多个仓库标识如model/bert-base-uncased或 revision 哈希➜ 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.仓库与具体 revision 可以在同一次调用中混用。使用--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.如果你的缓存不在默认位置可组合使用--cache-dir PFAD。清理孤儿 snapshot 使用hf cache prune。该命令自动删除所有不再被任何分支或标签引用的 revision➜ hf cache prune About to delete 3 unreferenced revision(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); freed 2.4G.两个命令均支持--dry-run、--yes与--cache-dir可用来生成预览、构建自动化流程并指定替代缓存目录。从 Python 清空缓存如需更多灵活性可编程调用 [~HFCacheInfo.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() Cache deletion done. Saved 8.6G.实践建议小结日常查看优先用hf cache ls配合--revisions、--filter size1GB、--sort size:desc与--format json/csv需要脚本联动时用--quiet输出标识符并管道给xargs等工具。批量清理对不再引用的孤儿 revision 用hf cache prune对指定仓库或 revision 用hf cache rm务必先--dry-run预览。离线环境用try_to_load_from_cache无网络探测本地缓存其 不存在也缓存 的特性来自.no_exist目录可显著减少可选文件的探测请求。下游库集成非 Hub 来源的资产请用cached_assets_path(library_name..., namespace..., subfolder...)存入HF_ASSETS_CACHE便于统一纳入缓存扫描与删除流程。自定义位置通过cache_dir参数或HF_HOME、HF_HUB_CACHE环境变量控制缓存根目录所有 CLI 命令均可配合--cache-dir指向非默认位置。如需深入各数据结构与 CLI 选项的完整说明可继续查阅 文件下载与缓存工具模块、缓存管理实现 与 assets 路径工具 的源码及相应测试如 tests/test_hf_api.py 与缓存相关测试用例。赞分享开发工具CLI机器学习【免费下载链接】huggingface_hubThe official CLI and Python client for the Hugging Face Hub.项目地址https://gitcode.com/gh_mirrors/hu/huggingface_hub点击查看免费下载相关推荐Turborepo构建缓存清理管理存储空间的完整指南Turborepo构建缓存清理管理存储空间的完整指南 在大型JavaScript和TypeScript项目中Turborepo的构建缓存系统能够显著提升开发构建工具开发工具CLInpkill 完全指南扫描并清理 node_modules释放磁盘空间npkill 完全指南扫描并清理 node_modules释放磁盘空间 导读 npkill 是一个用 TypeScript 编写的交互式 CLI 工具能拯救C盘空间Scoop缓存深度清理指南从原理到实战拯救C盘空间Scoop缓存深度清理指南从原理到实战 你是否遇到过Windows系统盘空间莫名告急作为开发者频繁安装开发工具后C盘可用空间持续萎缩却找不开发工具CLI上一篇Lenis滚动控制终极指南让网页跳转如丝般顺滑下一篇Synology NAS网络升级终极方案Realtek USB以太网驱动完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表