Hugging Face Hub
NORA может работать как кеширующий прокси (pull-through) для публичных моделей Hugging Face Hub. Сведения о модели, ревизии и списки файлов NORA запрашивает у Hub при каждом запросе; файлы моделей кешируются по дайджесту, которым их называет Hub, и сверяются с ним при скачивании. Это реестр только для проксирования, и он включается явно: по умолчанию выключен и не входит в all. Доступен с NORA 1.4.0.
Включение
Заголовок раздела «Включение»NORA_HF_ENABLED=true nora serveЕсли реестры выбираются через NORA_REGISTRIES_ENABLE (или [registries] enable), назовите его там: all оставляет прокси Hugging Face выключенным, all,hf включает его вместе со всеми остальными.
config.toml:
[hf]enabled = trueproxy = "https://huggingface.co"proxy_timeout = 30 # секундыcdn_hosts = ["hf.co", "huggingface.co"] # куда может вести редирект файлаПеременные окружения:
| Переменная | Описание | По умолчанию |
|---|---|---|
NORA_HF_ENABLED | Включить прокси Hugging Face | false |
NORA_HF_PROXY | URL upstream Hub; пустое значение отключает upstream | https://huggingface.co |
NORA_HF_PROXY_TIMEOUT | Таймаут upstream в секундах | 30 |
NORA_HF_CDN_HOSTS | Хосты, куда может вести редирект файла, через запятую: каждая запись и имена под ней | hf.co,huggingface.co |
Настройка клиента
Заголовок раздела «Настройка клиента»Укажите NORA для huggingface_hub через HF_ENDPOINT:
export HF_ENDPOINT=http://nora.example.com:4000/hf
hf download openai-community/gpt2 # весь снапшотhf download openai-community/gpt2 config.json # один файлhf download openai-community/gpt2 config.json --revision refs/pr/198Python API читает ту же переменную:
from huggingface_hub import hf_hub_download, snapshot_download
hf_hub_download("openai-community/gpt2", "config.json")snapshot_download("openai-community/gpt2")Проверено с huggingface_hub 0.36.0, 1.0.0, 1.33.0, 2.0.0, 2.1.1 и 2.2.0, а с 2.1.1 — и против huggingface.co: обычный файл, LFS-файл репозитория на Xet, устаревший id репозитория (gpt2), ревизии refs/pr/N и коммит — все запросы через NORA. С установленным hf_xet клиент всё равно скачивает по обычному HTTP: NORA никогда не объявляет Xet.
Как это работает
Заголовок раздела «Как это работает»- Редиректы остаются внутри NORA. На запрос файла Hub отвечает редиректом — относительным 307 на свой кеш resolve или 302 на CDN для LFS-файла. NORA проходит их сама, поэтому до клиента не доходит ни один
Location, и каждый байт идёт через NORA. Редирект проходится только на origin самого upstream или по https на хост изcdn_hosts— CDN Hub,us.aws.cdn.hf.co, лежит подhf.co. IP-адрес совпадает как адрес, а не как суффикс; по http на CDN NORA идёт, только если весь обход от http-upstream шёл по http, и никогда — после https. Запись открывает все порты своего хоста, поэтомуlocalhostи внутренние имена в боевой список не пишут. Редирект на любой другой хост —502, и к этому хосту NORA не обращается. Зеркалу, которое отдаёт файлы с другого хоста, этот хост нужно добавить вcdn_hosts. - Всегда свежо. Ответ Hub на resolve запрашивается при каждом скачивании: в нём названы коммит и дайджест файла. Поэтому
mainникогда не устаревает, а байты берутся из кеша, если этот дайджест у NORA уже есть. - Кеш по дайджесту. Файлы хранятся по репозиторию под дайджестом, которым их называет Hub (sha256 для LFS-файла, git blob sha1 для обычного):
hf/models/{repo}/blobs/{digest}. Файл весов, который не меняется между коммитами, скачивается один раз. - Сверка при скачивании. Файл сверяется с этим дайджестом, а его последний кусок придерживается до совпадения: испорченный файл обрывается на кусок раньше и не сохраняется. Файл, прочитанный из кеша, так же сверяется со своим пином; не прошедшая сверку копия удаляется, и следующее скачивание берёт файл заново. Чтение части файла (range) из кеша не сверяется — часть нельзя перехешировать, как и в любом формате.
- Проходят насквозь, не сохраняясь: range-запрос к ещё не закешированному файлу,
HEADи файл, etag которого не называет дайджест. Клиент, ушедший раньше времени, ничего после себя не оставляет. - Без Xet.
xetHashубирается из метаданных на любой глубине, заголовки и ссылки Xet до клиента не доходят, а эндпоинты токенов Xet отвечают404.
Возможности
Заголовок раздела «Возможности»| Эндпоинт | Метод | Статус | Примечание |
|---|---|---|---|
/hf/api/models/{repo} | GET | Полная | Сведения о модели, без xetHash |
/hf/api/models/{repo}/revision/{rev} | GET | Полная | Ревизия в том виде, как её закодировал клиент (refs%2Fpr%2F1 остаётся одним сегментом) |
/hf/api/models/{repo}/tree/{rev}[/{path}] | GET | Полная | Список по страницам; Link rel="next" указывает под /hf |
/hf/{repo}/resolve/{rev}/{file} | HEAD | Полная | Ответ из ответа Hub на resolve (коммит, etag, размер) |
/hf/{repo}/resolve/{rev}/{file} | GET | Полная | Кеш по дайджесту; Range поддерживается |
/hf/api/models/{repo}/xet-read-token/…, xet-write-token/… | GET | Отказ (404) | NORA никогда не отдаёт Xet |
/hf/api/datasets/…, /hf/datasets/… | * | — (501) | Только модели |
Загрузка (POST, PUT, DELETE, PATCH) | * | — (405) | Только прокси |
Размер кеша и retention
Заголовок раздела «Размер кеша и retention»Закешированные файлы учитываются в [gc] proxy_cache_max_bytes (NORA_GC_PROXY_CACHE_MAX_BYTES) вместе с проксированными пакетами RPM и Debian; сверх лимита GC вытесняет сначала самые старые файлы. Правила retention, где назван hf, их подрезают (older_than_days, а keep_last считается в файлах); правило * к этому формату, включаемому явно, не применяется.
Курация
Заголовок раздела «Курация»Скачивание называется по id репозитория, а его версия — коммит. Правило на репозиторий отказывает до запроса к Hub; правило на коммит действует для main, когда main указывает на этот коммит, — и для уже закешированного файла. Псевдоним — устаревший id вроде gpt2, другой регистр, переименованный репозиторий — проверяется и под каноническим id (openai-community/gpt2), который NORA узнаёт у Hub; если узнать его не удалось, курация в режиме enforce отказывает (502), а в режиме audit записывает скачивание под запрошенным id и пропускает. Allowlist коммитов без коммита не пропускает ничего. curation.min_release_age при включённом прокси Hugging Face отвергается при старте: у коммита Hub нет даты публикации, которую NORA может прочитать. Подробнее — Курация.
Известные ограничения
Заголовок раздела «Известные ограничения»- Только модели: датасеты и Spaces не отдаются (
501). - Только публичные репозитории: токен клиента никогда не уходит в upstream, поэтому закрытый (gated или private) репозиторий отвечает собственным отказом Hub (его статус,
X-Error-Codeи сообщение). - Общий лимит запросов: NORA обращается к Hub без токена, поэтому анонимные лимиты Hub делят все клиенты за NORA, а закешированный файл всё равно стоит одного запроса resolve.
429передаётся клиенту сRetry-After,RateLimitиRateLimit-Policy, по которым huggingface_hub ждёт сброса окна. - Hub должен быть доступен для скачивания: ответ resolve запрашивается каждый раз, отдачи устаревшей копии пока нет.
HfFileSystemне проверялся; его вызовpaths-info— этоPOST, он отвечает405.- Псевдоним и канонический id кешируются отдельно (
gpt2иopenai-community/gpt2). - Веб-интерфейс: формат виден на панели, но закешированные файлы пока не перечисляются.
nora backupвключает кеш — каждый сохранённый файл весов. Исключитьhf/пока нельзя, поэтому перед резервной копией большого кеша держите его в пределахproxy_cache_max_bytesили правила retention.- S3: задайте для бакета правило жизненного цикла
AbortIncompleteMultipartUpload. Заполнение кеша, прерванное во время загрузки (перезапуск), оставляет части multipart-загрузки, которые объектное хранилище держит, пока их не отменят. - Загрузка через NORA не поддерживается (
405).