Hub documentation
Локальный кэш Hub
Локальный кэш Hub
Этот документ описывает структуру хранения данных локального кэша HF Hub на диске. Он предназначен в качестве справочного материала для повторной реализации системы кэширования на любом языке.
Ниже приведён частичный список библиотек и приложений, использующих эту структуру кэша. Пожалуйста, отправьте PR, чтобы добавить свой проект.
Библиотеки
| Библиотека | Язык | Примечания |
|---|---|---|
huggingface_hub | Python | И любая библиотека, которая от него зависит (например, transformers, diffusers, datasets, mlx, vllm …) |
hf-hub | Rust | |
swift-huggingface | Swift | |
@huggingface/hub | JavaScript | Только Node.js |
SMILE | Java | См. документацию HuggingFaceHub |
Приложения
| Применение | Язык | Примечания |
|---|---|---|
llama.cpp | C++ | С момента #20775 |
Llama-macOS | Swift | macOS-приложение, созданное на базе llama.cpp |
HuggingFaceModelDownloader | Перейти | |
oMLX | Python | Сервер инференса MLX для macOS, начиная с v0.4.0 |
Расположение кэша
Каталог кэша по умолчанию:
~/.cache/huggingface/hubЭто можно переопределить с помощью переменных окружения:
HF_HUB_CACHE— прямой путь к каталогу кэша (имеет приоритет)HF_HOME— путь к домашнему каталогу Hugging Face; если задан, кэш находится в$HF_HOME/hub
Обзор
<CACHE_DIR>/
├── .locks/ # Lock files for concurrent download safety
├── blobs/ # Shared blob store: Xet files deduplicated across repos
├── models--<org>--<repo>/ # Cached model repositories
├── datasets--<org>--<repo>/ # Cached dataset repositories
└── spaces--<org>--<repo>/ # Cached space repositoriesКаждое загруженное репозиторий получает одну плоскую папку. Внутри папки репозитория файлы хранятся один раз в каталоге blobs/ с адресацией по содержимому и доступны через символьные ссылки в snapshots/. Именованные ссылки (ветки, теги) отслеживаются в refs/. Начиная с huggingface_hub 1.32, файлы, загруженные с помощью hf_xet, хранятся один раз для всего кэша в общем хранилище блобов в корне кэша. Запись blobs/ репозитория в этом случае является символьной ссылкой на этот файл.
Схема
┌──────────────────────────────────────────┐
│ Repository folder │
│ models--julien-c--EsperBERTo-small │
└──────────────┬───────────────────────────┘
│
┌─────────────┬───────┴───────┬──────────────┐
│ │ │ │
v v v v
┌───────┐ ┌────────┐ ┌────────────┐ ┌──────────┐
│ refs/ │ │ blobs/ │ │ snapshots/ │ │.no_exist/│
└───┬───┘ └────┬───┘ └──────┬─────┘ └────┬─────┘
│ │ │ │
│ │ │ │
"main" contains Files stored One folder Empty marker
commit hash by content per commit files for
e.g. "aaaaaa" hash (SHA-1 hash, e.g. files known
or SHA-256) aaaaaa/ not to exist
Resolves a bbbbbb/
branch/tag to │
a snapshot ──────────────────────► Contains symlinks
to ../../blobs/{hash}Именование папок репозитория
Репозитории хранятся в виде плоских каталогов в корне кэша. Имя папки кодирует тип репозитория и его идентификатор:
{type}s--{repo_id_with_slashes_replaced_by_--}Правила:
- Тип репозитория принимает множественное число:
models,datasets,spaces - Символы прямой косой черты (
/) в идентификаторе репозитория заменяются на-- - Разделитель между всеми частями —
-- - Регистр символов сохраняется
Примеры:
| ID репозитория Hub | Тип репозитория | Имя папки кэша |
|---|---|---|
julien-c/EsperBERTo-small | модель | models--julien-c--EsperBERTo-small |
huggingface/DataMeasurementsFiles | dataset | datasets--huggingface--DataMeasurementsFiles |
dalle-mini/dalle-mini | space | spaces--dalle-mini--dalle-mini |
Buckets не обрабатываются этим кэшем, так как они не поддерживаются git. Вместо этого используйте специальную команду
hf buckets sync.
Внутри папки репозитория
Каждое кэшированное репозиторий имеет одинаковую внутреннюю структуру:
<repo_folder>/
├── blobs/
├── refs/
├── snapshots/
└── .no_exist/ # may not always be presentblobs/ : хранилище файлов с адресацией по содержимому
Каталог blobs/ хранит фактическое содержимое файлов. Имя каждого файла соответствует его etag на Hub:
- Файлы, отслеживаемые Git: идентифицируются по их хешу SHA-1 (40 шестнадцатеричных символов)
- Файлы Git LFS: именуемые по их хэшу SHA-256 (64 шестнадцатеричных символа)
Это плоский каталог — без подкаталогов. Идентичные файлы в разных ревизиях хранятся только один раз. Запись представляет собой либо обычный файл, либо относительную символьную ссылку в общее хранилище блобов; читателям следует переходить по ней.
blobs/
├── 403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd # SHA-256 (LFS)
├── 7cb18dc9bafbfcf74629a4b760af1b160957a83e # SHA-1 (git)
└── d7edf6bd2a681fb0175f7735299831ee1b22b812 # SHA-1 (git)refs/: ссылки на ветки и теги
Каталог refs/ сопоставляет человекочитаемые ссылки (имена веток, теги, номера PR) с хэшами коммитов.
Каждая ссылка представляет собой текстовый файл, содержащий одну строку: полный хеш коммита (40 шестнадцатеричных символов).
refs/
├── main # contains e.g. "bbc77c8132af1cc5cf678da3f1ddf2de43606d48"
├── 2.4.0 # a tag
└── refs/
└── pr/
└── 1 # pull request referenceКогда файл загружается с использованием имени ветки или тега, соответствующий файл ref создаётся или обновляется с последним хэшем коммита.
snapshots/ : представления ревизий
Каталог snapshots/ содержит один подкаталог для каждой кэшированной ревизии (хеш коммита). Каждый каталог ревизии повторяет структуру файлов репозитория на Hub, но файлы являются символическими ссылками, указывающими на ../../blobs/{hash}.
snapshots/
├── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
│ ├── README.md -> ../../blobs/d7edf6bd2a681fb0175f7735299831ee1b22b812
│ └── pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
└── bbc77c8132af1cc5cf678da3f1ddf2de43606d48/
├── README.md -> ../../blobs/7cb18dc9bafbfcf74629a4b760af1b160957a83e
└── pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bdКлючевые свойства:
- Символические ссылки используют относительные пути:
../../blobs/{hash} - Если файл не изменялся между двумя ревизиями, оба символических ссылки указывают на один и тот же blob без дублирования данных
- Файлы в подкаталогах на Hub представлены в снапшоте как подкаталоги (полный относительный путь сохраняется)
Переключение между снимками аналогично использованию git checkout в локальном git-репозитории.
.no_exist/ : кэш отсутствия
Каталог .no_exist/ отслеживает файлы, которые запрашивались, но отсутствуют в Hub. Это позволяет избежать повторных HTTP-запросов для необязательных файлов.
Структура повторяет структуру snapshots/: один подкаталог на каждый хеш коммита, содержащий пустые файлы (не символьные ссылки) с именами отсутствующих файлов.
.no_exist/
└── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
└── config_that_does_not_exist.json # empty fileЗанятое место на диске незначительно, так как это лишь пустые маркерные файлы.
Общая хранилище объектов
Файлы, загруженные через Xet, дедуплицируются между репозиториями. Такой файл хранится один раз в корне кэша, в blobs/, а каждый репозиторий, которому он нужен, получает относительную символьную ссылку вместо копии:
<CACHE_DIR>/
├── blobs/
│ ├── .huggingface-shared-blobs # marker file, contains the layout version ("1")
│ └── 73/ # first two hex characters of the Xet hash
│ ├── 73b079dc7bd546aed26d20a82289bd752fc52a2fda13e7f2b551f3af73845b59 # the file, named by its Xet hash (64 hex characters)
│ ├── 73b079dc7bd546aed26d20a82289bd752fc52a2fda13e7f2b551f3af73845b59.refs # manifest: one line per repo blob that references it (path relative to the cache root)
│ └── 73b079dc7bd546aed26d20a82289bd752fc52a2fda13e7f2b551f3af73845b59.lock # lock file
│
└── models--HuggingFaceTB--SmolLM2-135M-Instruct/
└── blobs/
└── 5af571cbf074e6d21a03528d2330792e532ca608f24ac70a143f6b369968ab8c -> ../../blobs/73/73b079dc7bd546aed26d20a82289bd752fc52a2fda13e7f2b551f3af73845b59Ключевые свойства:
- Запись репозитория сохраняет имя etag и становится относительной символьной ссылкой:
../../blobs/{xet_hash[:2]}/{xet_hash} - Структура
snapshots/не меняется, поэтому разрешение файлов не затрагивается - Файл-маркер идентифицирует хранилище: непустой каталог
blobs/в корне кэша без него никогда не используется и не изменяется - Хранилище требует символьные ссылки и
hf_xet. Если шаринг не удался, файл сохраняется в папке репозитория, как и раньше.HF_HUB_DISABLE_SHARED_BLOBS=1отключает хранилище - Только новые загрузки проходят через хранилище. Файлы, записанные более старыми версиями или другими клиентами, остаются обычными файлами в папке репозитория, поэтому кэш может содержать и то, и другое
Реализации, которые только читают кэш, не требуют изменений: переход по символическим ссылкам работает как и прежде.
Реализации, удаляющие данные из кэша, должны рассматривать blob репозитория, являющийся символьной ссылкой, как ссылку на хранилище:
- Удалите символьную ссылку в
blobs/репозитория, а не общий файл, на который она указывает - Заблокируйте
<xet_hash>.lockперед проверкой манифеста и удалением - Удалите общий файл и его
.refsтолько в том случае, если ни одна из символьных ссылок, перечисленных в манифесте, на него не указывает - Если манифест отсутствует или его невозможно прочитать, сохраните общий файл
См. руководство по кэшу huggingface_hub для информации о поведении при удалении и ограничениях в старых клиентах.
Файлы блокировки
Файлы блокировки предотвращают одновременную загрузку одного и того же объекта несколькими процессами. Они хранятся в каталоге .locks/ в корне кэша (не внутри папки репозитория):
<CACHE_DIR>/.locks/<repo_folder_name>/<blob_hash>.lockПример:
<CACHE_DIR>/.locks/models--julien-c--EsperBERTo-small/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd.lockПолный пример
~/.cache/huggingface/hub/
├── .locks/
│ └── models--julien-c--EsperBERTo-small/
│ └── 403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd.lock
│
└── models--julien-c--EsperBERTo-small/
├── blobs/
│ ├── [321M] 403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
│ ├── [ 398] 7cb18dc9bafbfcf74629a4b760af1b160957a83e
│ └── [1.4K] d7edf6bd2a681fb0175f7735299831ee1b22b812
│
├── refs/
│ └── main # contains "bbc77c8132af1cc5cf678da3f1ddf2de43606d48"
│
├── snapshots/
│ ├── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
│ │ ├── README.md -> ../../blobs/d7edf6bd2a681fb0175f7735299831ee1b22b812
│ │ └── pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
│ │
│ └── bbc77c8132af1cc5cf678da3f1ddf2de43606d48/
│ ├── README.md -> ../../blobs/7cb18dc9bafbfcf74629a4b760af1b160957a83e
│ └── pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd
│
└── .no_exist/
└── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/
└── optional_config.json # empty fileОбратите внимание, что pytorch_model.bin указывает на один и тот же blob в обеих ревизиях. Файл размером 321 МБ хранится на диске только один раз.
Логика разрешения файлов
Чтобы найти кэшированный файл на диске:
Разрешить ревизию в хеш коммита
- Если ревизия уже является 40-символьной шестнадцатеричной строкой, используйте её напрямую
- В противном случае прочитайте файл по пути
refs/{revision}, чтобы получить хеш коммита
Проверьте снимок
- Ищите
snapshots/{commit_hash}/{relative_path} - Если файл существует (в виде символической ссылки или обычного файла), он кэшируется. Следуйте по символической ссылке, чтобы получить содержимое
- Ищите
Проверка отсутствия
- Ищите
.no_exist/{commit_hash}/{relative_path} - Если файл существует, то известно, что он отсутствует на Hub для данной ревизии
- Ищите
Промах кэша
- Если ни один из путей не существует, файл ещё не был закэширован
Поведение в Windows
Кэш использует символические ссылки. На системах Windows, где символические ссылки недоступны, кэш работает в деградированном режиме: вместо ссылок в snapshots/ размещаются фактические копии файлов. В этом режиме каталог blobs/ и общий хранилище блобов не используются.
Это означает, что содержимое одного и того же файла может дублироваться между ревизиями, что увеличивает использование дискового пространства. Чтобы включить поддержку символьных ссылок в Windows, активируйте Developer Mode или запустите процесс от имени администратора.
Update on GitHub