GuardRateLeaderboard / docs /data-loading-cache_ru.md
Anton Malykhin
fix: stabilize benchmark leaders, model benchmark sorting, and HF bucket reads
644ba85
|
Raw
History Blame Contribute Delete
22.3 kB

Загрузка данных и кеширование

Этот документ описывает текущую реализацию загрузки данных и кеширования во frontend HiveTrace Guardrail Leaderboard.

У реализации три основные цели:

  • хранить приватный Hugging Face token только на сервере SvelteKit;
  • не скачивать и не адаптировать повторно неизменившиеся payload-файлы bucket;
  • ускорить повторные переходы между страницами и сохранить предсказуемое окно актуальности данных.

Архитектура

Browser
  -> SvelteKit page или __data.json request
  -> Node process в Hugging Face Space
  -> private Hugging Face bucket
       -> latest/manifest.json
       -> payload-файлы, указанные в manifest

Браузер не обращается к приватному bucket напрямую. Все запросы в bucket выполняет сервер SvelteKit с помощью server-only переменной HF_TOKEN.

Источник данных

Bucket настраивается runtime-переменными:

HF_TOKEN=<private read token>
HF_BUCKET_ID=hivetrace/leaderboard_frontend_v2
HF_BUCKET_PREFIX=latest
HF_BUCKET_REQUEST_TIMEOUT_MS=60000
HF_BUCKET_REQUEST_RETRIES=2
HF_BUCKET_ENDPOINT=https://huggingface.co

HF_BUCKET_ENDPOINT, HF_BUCKET_REQUEST_TIMEOUT_MS и HF_BUCKET_REQUEST_RETRIES опциональны. Выше указаны их значения по умолчанию.

HF_BUCKET_CACHE_TTL_MS по-прежнему управляет обычным in-memory кешем manifest и прямым helper Tools snapshot. Основной поток page data для Ranking, Details и Visualizations после промаха браузерного кеша явно обновляет manifest, поэтому эта переменная не добавляет еще одну задержку актуальности при обычных переходах по страницам.

Manifest как указатель версии

latest/manifest.json является единственным указателем версии для frontend. Основные поля:

  • snapshot_id: идентификатор опубликованного набора данных;
  • files: пути ко всем payload-файлам;
  • hashes: SHA-256 хеши payload-файлов;
  • schema_version: версия контракта bucket;
  • количества моделей, групп и датасетов для валидации.

Frontend определяет изменение payload по snapshot_id. Каждая новая публикация обязана иметь новый уникальный snapshot_id.

Изменение payload-файлов или хешей без изменения snapshot_id не поддерживается. В таком случае frontend считает snapshot прежним и может использовать старый in-memory payload до перезапуска процесса Space.

Маршруты и payload-файлы

Маршрут Server loader Данные bucket
/ getHfBucketRankingState() catalog, leaderboard и details matrix
/details getHfBucketDetailsState() catalog, leaderboard и details matrix
/tools getHfBucketToolsState() catalog, leaderboard, drilldown index, radar, scatter, heatmap, grouped bars, Pareto, performance и robustness
/methodology нет bucket page loader payload из bucket не используется

Ranking также использует details matrix, потому что статус модели partial вычисляется по условию metrics_evaluated_samples < sample_count.

Корневой +layout.server.ts отдельно читает manifest и возвращает публичный статус bucket: дату snapshot, количество моделей и другие общие поля. Этот статус использует обычный кеш manifest. Он является метаданными layout и не управляет актуальностью page data.

Клиентская навигация

SvelteKit перехватывает внутренние ссылки главного меню и запрашивает данные маршрутов через endpoint вида:

/__data.json
/details/__data.json
/tools/__data.json

Локализованные варианты также распознаются, например /ru/details/__data.json.

Оптимизация response в src/hooks.server.ts применяется только к этим трем page-data маршрутам. Она не применяется к Methodology, статическим файлам, ошибкам и произвольным API response.

Браузерный кеш

Успешный page-data response получает заголовок:

Cache-Control: private, max-age=300

Это означает:

  • браузер может повторно использовать response маршрута в течение пяти минут;
  • response не попадает в общий CDN или shared proxy cache;
  • окно stale-while-revalidate отсутствует;
  • после пяти минут следующий переход обязан обратиться к серверу SvelteKit до отрисовки маршрута.

Кеш привязан к URL response, включая внутренние query-параметры SvelteKit. Поэтому Ranking, Details и Visualizations имеют отдельные записи браузерного кеша.

Уже открытая страница сама не обновляется. Новые данные применяются при следующем переходе или полной перезагрузке страницы.

Gzip-сжатие

Тот же hook сжимает page-data response, когда выполнены все условия:

  • response успешный и содержит body;
  • заявленный размер не меньше 1 024 bytes;
  • клиент поддерживает gzip.

Сжатый response содержит:

Content-Encoding: gzip
Vary: Accept-Encoding

Content-Length удаляется, потому что сжатый body передается потоком. Клиенты без поддержки gzip получают исходный body с тем же приватным кешем на пять минут.

Примерные измеренные размеры для текущего набора данных:

Данные маршрута Без сжатия Gzip
Ranking 171 KB 58 KB
Details 643 KB 158 KB
Visualizations 709 KB 122 KB

Размеры зависят от содержимого bucket и будут меняться при добавлении моделей и датасетов.

Поток server request

Если в браузере нет свежего page-data response, сервер выполняет следующие шаги:

  1. Page loader вызывает соответствующую state-функцию Ranking, Details или Tools.
  2. State-функция вызывает fetchBucketRankingSnapshot({ refreshManifest: true }).
  3. refreshManifest: true обходит обычный TTL manifest и читает актуальный небольшой manifest.json из Hugging Face.
  4. Если полученный snapshot_id совпадает с in-memory ranking snapshot, catalog и leaderboard используются повторно без скачивания payload.
  5. Если snapshot_id изменился, catalog и leaderboard скачиваются параллельно, проверяются их хеши и schema, после чего ranking snapshot заменяется.
  6. Данные конкретного маршрута переиспользуются или пересобираются для нового snapshot_id.
  7. SvelteKit сериализует адаптированные данные маршрута, а server hook добавляет приватный кеш и gzip-сжатие.

Разница между параметрами snapshot:

  • refreshManifest: true всегда проверяет manifest, но переиспользует payload при неизменном snapshot_id;
  • forceRefresh: true также отключает переиспользование payload и пересобирает ranking snapshot.

Обычные переходы по страницам используют refreshManifest, а не forceRefresh.

In-memory кеши сервера

Все серверные кеши хранятся в памяти работающего Node process. Они принадлежат одному replica Space и очищаются при перезапуске, засыпании контейнера или новом deploy.

Кеш manifest

src/lib/server/hf-bucket/cache.ts хранит:

  • распарсенный manifest;
  • время его получения;
  • время истечения кеша;
  • один общий in-flight request manifest.

Обычные callers используют HF_BUCKET_CACHE_TTL_MS, по умолчанию пять минут. Page-data refresh использует принудительное чтение manifest, описанное выше. Одновременные принудительные проверки подключаются к одному in-flight request, если пересекаются по времени.

Ranking snapshot

Ranking snapshot содержит manifest, catalog и leaderboard. Он кешируется по snapshot_id.

Одновременные загрузки одного snapshot используют общий promise. In-flight request также привязан к snapshot_id, поэтому запрос нового опубликованного snapshot не использует по ошибке загрузку предыдущего snapshot.

Details snapshot

Details snapshot добавляет details_matrix к ranking snapshot и кешируется по snapshot_id.

Этот кеш общий для Ranking и Details. Ranking использует matrix для определения partial, поэтому после открытия Ranking страница Details не скачивает и не валидирует details_matrix повторно. Одновременные запросы одного details snapshot также используют общий promise.

Адаптированные Ranking и Details

Готовые для UI объекты Ranking и Details кешируются по snapshot_id. Если manifest не изменился, сервер возвращает уже адаптированный объект. Новый snapshot парсится, валидируется и адаптируется один раз на Node process.

Visualizations snapshot и адаптированный Tools dataset

Для нового snapshot файлы визуализаций скачиваются параллельно. Raw visualization snapshot и адаптированный Tools dataset кешируются отдельно по snapshot_id.

Прямой helper getHfBucketToolsSnapshot() сохраняет свой быстрый путь на основе TTL. Страница /tools использует state-путь, который обновляет manifest после промаха браузерного кеша.

Валидация

Payload используется повторно только после проверки версии manifest. Новый payload проходит:

  • JSON parsing;
  • schema parsing;
  • проверку SHA-256 при наличии хеша;
  • сверку количеств из manifest;
  • проверку ссылок на модели, группы и датасеты;
  • проверку полноты matrix и дублирующихся пар;
  • проверку ссылок в данных визуализаций.

Ошибка валидации обрабатывается так же, как другая ошибка обновления.

Гарантия актуальности данных

Предположим, что корректный новый snapshot опубликован в момент T, а bucket доступен.

Response маршрута уже находится в браузерном кеше

Старый response может использоваться до истечения его индивидуального max-age в пять минут. Первый переход на этот маршрут после истечения кеша читает свежий manifest. Если snapshot_id изменился, тот же переход ожидает загрузку нового payload и получает новые данные.

Ожидаемая гарантия:

Не позднее первого перехода после истечения пятиминутного браузерного кеша маршрута пользователь получает новый snapshot.

Дополнительного окна выдачи stale response нет.

Response маршрута отсутствует в браузерном кеше

Переход сразу обращается к серверу и проверяет manifest. Если новый payload уже находится в памяти сервера, он используется повторно. Иначе переход ожидает скачивание и адаптацию нового snapshot.

Полная перезагрузка страницы

Пятиминутная политика применяется к SvelteKit navigation response __data.json. Обычный полный HTML request не покрывается этим page-data кешем и снова запускает server page loader.

Исключения

Пятиминутное ожидание неприменимо, если:

  • Hugging Face или сеть недоступны;
  • новый payload не проходит parsing, проверку хеша или валидацию;
  • publisher повторно использовал старый snapshot_id;
  • manifest опубликован раньше, чем стали доступны все указанные в нем файлы.

Поведение при ошибках

Кеш также обеспечивает устойчивость:

  • если refresh завершился ошибкой и готовые данные маршрута существуют, сервер возвращает кеш;
  • если новый manifest доступен, но новый payload невалиден или недоступен, route state становится stale, и UI может показать предупреждение;
  • если пригодного кеша нет, маршрут возвращает состояние unavailable с пустым fallback dataset;
  • одновременные запросы используют общую in-flight работу и не дублируют загрузку bucket.

Важная деталь текущей реализации: если принудительное чтение manifest завершилось ошибкой, но в памяти есть предыдущий manifest, слой manifest может вернуть его как stale. После этого сервер продолжит выдавать предыдущие route data. Текущий route state не во всех случаях пробрасывает именно этот fallback manifest как видимое предупреждение stale.

Публикация нового snapshot

Producer должен выполнять публикацию атомарно с точки зрения frontend:

  1. Сгенерировать все payload-файлы.
  2. По возможности использовать immutable или snapshot-specific пути.
  3. Рассчитать и записать SHA-256 хеши.
  4. Загрузить каждый payload-файл и проверить, что он доступен для чтения.
  5. Создать manifest с новым уникальным snapshot_id, корректными путями, хешами, количествами и версией schema.
  6. Последним загрузить latest/manifest.json.

Публикация manifest последним не позволяет frontend увидеть новую версию, которая ссылается на еще недоступные файлы.

Cold start и replicas

После перезапуска или cold start Space in-memory snapshot отсутствует. Первый request должен прочитать manifest и все payload-файлы, необходимые выбранному маршруту. Следующие запросы используют подготовленные данные повторно.

Если Space работает с несколькими replicas, каждая имеет собственный кеш в памяти и прогревается независимо. Браузерный кеш остается локальным для каждого пользователя.

Операционная проверка

Для проверки заголовков page-data response нужен авторизованный запрос к Space:

curl -sS \
  -H "Authorization: Bearer $HF_TOKEN" \
  -H "Accept-Encoding: gzip" \
  -D - \
  -o /dev/null \
  "https://<space-domain>/details/__data.json"

Ожидаемые заголовки:

Cache-Control: private, max-age=300
Content-Encoding: gzip
Vary: Accept-Encoding

curl не воспроизводит navigation cache браузера без отдельной настройки собственного кеша. Поэтому повторные curl-запросы доходят до сервера и могут повторно запускать проверку manifest.

При проверке новой публикации нужно убедиться, что:

  • manifest содержит новый snapshot_id;
  • каждый указанный файл существует;
  • хеши соответствуют опубликованному содержимому;
  • в логах Space нет ошибок валидации bucket;
  • первый переход после истечения браузерного кеша показывает новый snapshot.

Карта реализации

Ответственность Файл
HTTP client bucket и server-only token src/lib/server/hf-bucket/client.ts
Обычный кеш manifest и in-flight request src/lib/server/hf-bucket/cache.ts
Загрузка и валидация Ranking snapshot src/lib/server/hf-bucket/ranking-snapshot.ts
Общий Details snapshot src/lib/server/hf-bucket/details-snapshot.ts
Загрузка Visualization snapshot src/lib/server/hf-bucket/tools-snapshot.ts
Кеш адаптированного Ranking src/lib/server/hf-bucket/ranking-cache.ts
Кеш адаптированного Details src/lib/server/hf-bucket/details-cache.ts
Raw и адаптированный кеш Tools src/lib/server/hf-bucket/tools-cache.ts
Заголовки браузерного кеша и gzip src/hooks.server.ts
Публичный статус bucket в root layout src/routes/+layout.server.ts
Оркестрация маршрутов src/routes/+page.server.ts, src/routes/details/+page.server.ts, src/routes/tools/+page.server.ts