Source code for eval_framework.tasks.dataset_revisions

"""Pinned Hugging Face dataset revisions.

A lock file maps dataset paths to pinned commit SHAs. Tasks declare the lock file that
governs them via their ``REVISION_LOCKFILE`` attribute and resolve their pin from it at
construction time.
"""

import json
import logging
from functools import lru_cache
from pathlib import Path

from huggingface_hub import HfApi

logger = logging.getLogger(__name__)

# The revision of the datasets used by the benchmarks is declared in a file, so we can automatically
# update them in CI without having to parse python code.
HF_REVISIONS_LOCKFILE = Path(__file__).resolve().parent / "hf-dataset-revisions.json"

# Hand-maintained pins for datasets that must not move, e.g. because newer revisions are
# incompatible with the task implementation. Never updated by the refresh job.
FROZEN_HF_REVISIONS_LOCKFILE = Path(__file__).resolve().parent / "frozen-hf-dataset-revisions.json"


[docs] class HfDatasetRevisions: """Pinned revisions of Hugging Face datasets, mapping dataset path → commit SHA.""" def __init__(self, revisions: dict[str, str]) -> None: self._revisions = dict(revisions)
[docs] @classmethod def from_file(cls, path: Path) -> "HfDatasetRevisions": return cls(json.loads(path.read_text(encoding="utf-8")))
[docs] def to_dict(self) -> dict[str, str]: return dict(self._revisions)
[docs] def to_file(self, path: Path) -> None: path.write_text( json.dumps(dict(sorted(self._revisions.items())), indent=4, ensure_ascii=False) + "\n", encoding="utf-8", )
[docs] def revision_for(self, dataset_path: str) -> str: """The pinned commit SHA for a dataset. Raises ``KeyError`` if it is not pinned.""" return self._revisions[dataset_path]
[docs] def num_revisions(self) -> int: return len(self._revisions)
[docs] def update_to_latest(self, api: HfApi) -> None: """Update every pin to its dataset's latest commit SHA. Intended to run on CI to ensure the pinned revisions are up-to-date. If the lookup for a dataset fails, its existing pin is kept. """ for path, sha in self._revisions.items(): try: latest = api.dataset_info(path, timeout=100.0).sha except Exception as exc: logger.warning("Could not refresh %s (%s); keeping pinned revision %s", path, exc, sha) continue if latest and latest != sha: logger.info("%s: %s -> %s", path, sha, latest) self._revisions[path] = latest or sha
@lru_cache def _revisions_from_file(lockfile: Path) -> HfDatasetRevisions: return HfDatasetRevisions.from_file(lockfile)
[docs] def pinned_revision(lockfile: Path, dataset_path: str) -> str: """The commit SHA pinned for ``dataset_path`` in ``lockfile``. Resolves the exact dataset revision an eval runs against, so results stay reproducible across dataset updates. Every dataset used by a task is expected to be pinned; a missing entry is a bug in the lock file and raises ``KeyError``. """ try: return _revisions_from_file(lockfile).revision_for(dataset_path) except KeyError: raise KeyError(f"Dataset '{dataset_path}' is not pinned in {lockfile}") from None