chore: import upstream snapshot with attribution
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,401 @@
|
||||
"""HF dataset store for nightly precision-regression baselines.
|
||||
|
||||
Layout: ``<model>/<YYYY>/<MM>/<DD>/run-<sglang_sha7>/{meta.json,
|
||||
comparator_report.jsonl, tensors/*.pt}``. Root ``manifest.jsonl`` has one
|
||||
row per run; rows carry a ``push_index`` so fetch picks the latest push
|
||||
regardless of file order (prune may rewrite the file).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Optional, TypeVar
|
||||
|
||||
from huggingface_hub import HfApi, hf_hub_download, snapshot_download
|
||||
from huggingface_hub.errors import (
|
||||
EntryNotFoundError,
|
||||
HfHubHTTPError,
|
||||
RepositoryNotFoundError,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class HfStoreConfig:
|
||||
repo: str
|
||||
revision: str = "main"
|
||||
|
||||
@classmethod
|
||||
def from_env(cls) -> HfStoreConfig:
|
||||
repo = os.environ.get("SGLANG_PRECISION_HF_REPO")
|
||||
if not repo:
|
||||
raise RuntimeError(
|
||||
"SGLANG_PRECISION_HF_REPO is not set. The precision baseline "
|
||||
"store is required (there is no local-only mode); set the repo "
|
||||
"and HF_TOKEN_PRECISION_STORE."
|
||||
)
|
||||
revision = os.environ.get("SGLANG_PRECISION_HF_REVISION", "main")
|
||||
return cls(repo=repo, revision=revision)
|
||||
|
||||
|
||||
def _sanitize_model_name(model: str) -> str:
|
||||
return model.replace("/", "__").replace(" ", "_")
|
||||
|
||||
|
||||
def _today_path() -> tuple[str, str]:
|
||||
now = datetime.now(timezone.utc)
|
||||
return now.strftime("%Y-%m-%d"), now.strftime("%Y/%m/%d")
|
||||
|
||||
|
||||
def _push_index() -> int:
|
||||
return time.time_ns()
|
||||
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
def _with_retries(
|
||||
op: Callable[[], _T],
|
||||
*,
|
||||
what: str,
|
||||
attempts: int = 3,
|
||||
base_delay: float = 2.0,
|
||||
) -> _T:
|
||||
"""Exponential backoff on 429/5xx; auth/404 raise immediately."""
|
||||
last_exc: Optional[BaseException] = None
|
||||
for attempt in range(1, attempts + 1):
|
||||
try:
|
||||
return op()
|
||||
except HfHubHTTPError as e:
|
||||
status = getattr(getattr(e, "response", None), "status_code", None)
|
||||
transient = status is None or status == 429 or 500 <= status < 600
|
||||
if not transient or attempt == attempts:
|
||||
raise
|
||||
last_exc = e
|
||||
time.sleep(base_delay * (2 ** (attempt - 1)))
|
||||
raise RuntimeError(f"unreachable retry exit for {what}: {last_exc}")
|
||||
|
||||
|
||||
def _row_recency_key(row: dict[str, Any], fallback_index: int) -> tuple[int, int]:
|
||||
# Fall back to file position for legacy rows that predate push_index.
|
||||
explicit = row.get("push_index")
|
||||
try:
|
||||
explicit_i = int(explicit) if explicit is not None else -1
|
||||
except (TypeError, ValueError):
|
||||
explicit_i = -1
|
||||
return (explicit_i, fallback_index)
|
||||
|
||||
|
||||
def _select_latest_run(
|
||||
rows: list[dict[str, Any]],
|
||||
*,
|
||||
model: str,
|
||||
capture_signature: Optional[str] = None,
|
||||
) -> Optional[str]:
|
||||
# A baseline is only comparable to a target with the same capture shape, so
|
||||
# when a signature is given, mismatched (incl. legacy unsigned) rows are
|
||||
# skipped — fetch then returns None and the caller establishes a fresh one
|
||||
# instead of erroring on incompatible tensors.
|
||||
# A failed run must not become the next comparison baseline, or a persistent
|
||||
# regression is masked: today's regressed tensors (uploaded as "failed")
|
||||
# would be selected as the reference next run. Prefer non-failed rows and
|
||||
# fall back to a failed one only when no usable baseline exists.
|
||||
candidates: list[tuple[tuple[int, int], dict[str, Any]]] = []
|
||||
for idx, row in enumerate(rows):
|
||||
if row.get("model") != model:
|
||||
continue
|
||||
if (
|
||||
capture_signature is not None
|
||||
and row.get("capture_signature") != capture_signature
|
||||
):
|
||||
continue
|
||||
if "run_path" not in row:
|
||||
continue
|
||||
candidates.append((_row_recency_key(row, idx), row))
|
||||
if not candidates:
|
||||
return None
|
||||
candidates.sort(key=lambda kv: kv[0])
|
||||
usable = [c for c in candidates if c[1].get("pass_label") != "failed"]
|
||||
chosen = usable or candidates
|
||||
return chosen[-1][1]["run_path"]
|
||||
|
||||
|
||||
def fetch_latest_baseline(
|
||||
*,
|
||||
config: HfStoreConfig,
|
||||
model: str,
|
||||
target_tensors_dir: Path,
|
||||
capture_signature: Optional[str] = None,
|
||||
) -> Optional[str]:
|
||||
# Tensors land flat in target_tensors_dir (no enclosing tensors/) so the
|
||||
# caller can treat it like a fresh dump dir.
|
||||
rows, _ = _read_manifest(config)
|
||||
run_path = _select_latest_run(
|
||||
rows, model=model, capture_signature=capture_signature
|
||||
)
|
||||
if run_path is None:
|
||||
return None
|
||||
|
||||
snapshot_root = _with_retries(
|
||||
lambda: snapshot_download(
|
||||
repo_id=config.repo,
|
||||
repo_type="dataset",
|
||||
revision=config.revision,
|
||||
allow_patterns=[f"{run_path}/tensors/*"],
|
||||
),
|
||||
what="snapshot download",
|
||||
)
|
||||
src = Path(snapshot_root) / run_path / "tensors"
|
||||
if not src.exists():
|
||||
return None
|
||||
|
||||
target_tensors_dir.mkdir(parents=True, exist_ok=True)
|
||||
for fp in src.iterdir():
|
||||
if fp.is_file():
|
||||
shutil.copy2(fp, target_tensors_dir / fp.name)
|
||||
return run_path
|
||||
|
||||
|
||||
def _read_manifest(config: HfStoreConfig) -> tuple[list[dict[str, Any]], str]:
|
||||
# Skip corrupt rows rather than bricking the store on a partial write.
|
||||
try:
|
||||
manifest_local = _with_retries(
|
||||
lambda: hf_hub_download(
|
||||
repo_id=config.repo,
|
||||
repo_type="dataset",
|
||||
filename="manifest.jsonl",
|
||||
revision=config.revision,
|
||||
),
|
||||
what="manifest fetch",
|
||||
)
|
||||
except (EntryNotFoundError, RepositoryNotFoundError):
|
||||
return [], ""
|
||||
|
||||
text = Path(manifest_local).read_text(encoding="utf-8")
|
||||
rows: list[dict[str, Any]] = []
|
||||
for line in text.splitlines():
|
||||
if not line.strip():
|
||||
continue
|
||||
try:
|
||||
rows.append(json.loads(line))
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
return rows, text
|
||||
|
||||
|
||||
_MANIFEST_PROMOTE_KEYS = (
|
||||
"hardware",
|
||||
"tp_size",
|
||||
"pass_label",
|
||||
"capture_signature",
|
||||
"num_layers_compared",
|
||||
"num_layers_passed",
|
||||
"num_layers_failed",
|
||||
"max_rel_diff",
|
||||
"ci_run_id",
|
||||
)
|
||||
|
||||
|
||||
def push_run(
|
||||
*,
|
||||
config: HfStoreConfig,
|
||||
model: str,
|
||||
sglang_commit: str,
|
||||
today_tensors_dir: Path,
|
||||
meta: dict[str, Any],
|
||||
comparator_report: Optional[Path] = None,
|
||||
force: bool = False,
|
||||
) -> str:
|
||||
# Dedup: same model+date+sha → skip tensor upload but still refresh meta
|
||||
# + comparator_report + append a new manifest row, so pass-1 baseline and
|
||||
# pass-2 stats both land. force=True re-uploads tensors too.
|
||||
api = HfApi()
|
||||
date_str, date_path = _today_path()
|
||||
model_sanitized = _sanitize_model_name(model)
|
||||
sha7 = (
|
||||
sglang_commit[:7] if sglang_commit and sglang_commit != "unknown" else "no_sha"
|
||||
)
|
||||
run_path = f"{model_sanitized}/{date_path}/run-{sha7}"
|
||||
|
||||
existing_rows, existing_text = _read_manifest(config)
|
||||
tensors_already_present = any(r.get("run_path") == run_path for r in existing_rows)
|
||||
skip_tensors = tensors_already_present and not force
|
||||
|
||||
with tempfile.TemporaryDirectory() as stage_dir:
|
||||
stage = Path(stage_dir)
|
||||
run_dir = stage / "run"
|
||||
run_dir.mkdir(parents=True)
|
||||
if not skip_tensors:
|
||||
tensors_out = run_dir / "tensors"
|
||||
tensors_out.mkdir()
|
||||
for fp in today_tensors_dir.iterdir():
|
||||
if fp.is_file() and fp.suffix == ".pt":
|
||||
shutil.copy2(fp, tensors_out / fp.name)
|
||||
(run_dir / "meta.json").write_text(json.dumps(meta, indent=2), encoding="utf-8")
|
||||
if comparator_report is not None and comparator_report.exists():
|
||||
shutil.copy2(comparator_report, run_dir / "comparator_report.jsonl")
|
||||
|
||||
commit_msg = (
|
||||
f"refresh meta {sha7} for {model} on {date_str}"
|
||||
if skip_tensors
|
||||
else f"add run {sha7} for {model} on {date_str}"
|
||||
)
|
||||
_with_retries(
|
||||
lambda: api.upload_folder(
|
||||
repo_id=config.repo,
|
||||
repo_type="dataset",
|
||||
revision=config.revision,
|
||||
folder_path=str(run_dir),
|
||||
path_in_repo=run_path,
|
||||
commit_message=commit_msg,
|
||||
),
|
||||
what="upload_folder",
|
||||
)
|
||||
|
||||
manifest_row = {
|
||||
"date": date_str,
|
||||
"model": model,
|
||||
"run_path": run_path,
|
||||
"sglang_commit": sglang_commit,
|
||||
"push_index": _push_index(),
|
||||
**{k: meta.get(k) for k in _MANIFEST_PROMOTE_KEYS if k in meta},
|
||||
}
|
||||
|
||||
new_manifest_path: Optional[str] = None
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(
|
||||
"w", suffix=".jsonl", delete=False, encoding="utf-8"
|
||||
) as tmp_out:
|
||||
tmp_out.write(existing_text)
|
||||
if existing_text and not existing_text.endswith("\n"):
|
||||
tmp_out.write("\n")
|
||||
tmp_out.write(json.dumps(manifest_row) + "\n")
|
||||
new_manifest_path = tmp_out.name
|
||||
|
||||
_with_retries(
|
||||
lambda: api.upload_file(
|
||||
path_or_fileobj=new_manifest_path,
|
||||
path_in_repo="manifest.jsonl",
|
||||
repo_id=config.repo,
|
||||
repo_type="dataset",
|
||||
revision=config.revision,
|
||||
commit_message=f"manifest += {sha7} {date_str}",
|
||||
),
|
||||
what="manifest upload",
|
||||
)
|
||||
finally:
|
||||
if new_manifest_path and os.path.exists(new_manifest_path):
|
||||
os.unlink(new_manifest_path)
|
||||
return run_path
|
||||
|
||||
|
||||
def prune_old_runs(
|
||||
*,
|
||||
config: HfStoreConfig,
|
||||
model: Optional[str] = None,
|
||||
keep_days: int = 30,
|
||||
weekly_archive: bool = True,
|
||||
dry_run: bool = True,
|
||||
) -> dict[str, list[str]]:
|
||||
# dry_run defaults True because model=None+keep_days=0 would wipe the
|
||||
# store. Live mode rewrites the manifest before deleting folders so a
|
||||
# mid-run failure leaves manifest pointing at the kept rows only.
|
||||
api = HfApi()
|
||||
rows, _ = _read_manifest(config)
|
||||
if not rows:
|
||||
return {"kept": [], "pruned": []}
|
||||
|
||||
cutoff_date = datetime.now(timezone.utc).date()
|
||||
|
||||
def _row_date(row: dict[str, Any]) -> Optional[datetime]:
|
||||
try:
|
||||
return datetime.strptime(row["date"], "%Y-%m-%d").replace(
|
||||
tzinfo=timezone.utc
|
||||
)
|
||||
except (KeyError, ValueError):
|
||||
return None
|
||||
|
||||
kept_rows: list[dict[str, Any]] = []
|
||||
pruned_rows: list[dict[str, Any]] = []
|
||||
|
||||
by_model_week: dict[tuple[str, int, int], list[dict[str, Any]]] = {}
|
||||
for row in rows:
|
||||
if model is not None and row.get("model") != model:
|
||||
kept_rows.append(row)
|
||||
continue
|
||||
dt = _row_date(row)
|
||||
if dt is None:
|
||||
kept_rows.append(row)
|
||||
continue
|
||||
age_days = (cutoff_date - dt.date()).days
|
||||
if age_days <= keep_days:
|
||||
kept_rows.append(row)
|
||||
continue
|
||||
iso_year, iso_week, _ = dt.isocalendar()
|
||||
by_model_week.setdefault((row.get("model", ""), iso_year, iso_week), []).append(
|
||||
row
|
||||
)
|
||||
|
||||
for week_rows in by_model_week.values():
|
||||
week_rows.sort(key=lambda r: r.get("date", ""))
|
||||
if weekly_archive and week_rows:
|
||||
kept_rows.append(week_rows[-1])
|
||||
pruned_rows.extend(week_rows[:-1])
|
||||
else:
|
||||
pruned_rows.extend(week_rows)
|
||||
|
||||
kept_rows.sort(key=lambda r: (r.get("date", ""), r.get("model", "")))
|
||||
|
||||
report = {
|
||||
"kept": [r["run_path"] for r in kept_rows if "run_path" in r],
|
||||
"pruned": [r["run_path"] for r in pruned_rows if "run_path" in r],
|
||||
}
|
||||
if dry_run or not pruned_rows:
|
||||
return report
|
||||
|
||||
rewritten: Optional[str] = None
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(
|
||||
"w", suffix=".jsonl", delete=False, encoding="utf-8"
|
||||
) as tmp_out:
|
||||
for r in kept_rows:
|
||||
tmp_out.write(json.dumps(r) + "\n")
|
||||
rewritten = tmp_out.name
|
||||
_with_retries(
|
||||
lambda: api.upload_file(
|
||||
path_or_fileobj=rewritten,
|
||||
path_in_repo="manifest.jsonl",
|
||||
repo_id=config.repo,
|
||||
repo_type="dataset",
|
||||
revision=config.revision,
|
||||
commit_message=f"manifest -= {len(pruned_rows)} pruned",
|
||||
),
|
||||
what="manifest rewrite (prune)",
|
||||
)
|
||||
finally:
|
||||
if rewritten and os.path.exists(rewritten):
|
||||
os.unlink(rewritten)
|
||||
|
||||
for r in pruned_rows:
|
||||
rp = r.get("run_path")
|
||||
if not rp:
|
||||
continue
|
||||
try:
|
||||
api.delete_folder(
|
||||
repo_id=config.repo,
|
||||
repo_type="dataset",
|
||||
path_in_repo=rp,
|
||||
revision=config.revision,
|
||||
commit_message=f"prune {rp}",
|
||||
)
|
||||
except Exception:
|
||||
# Folder may already be missing; manifest no longer points at it.
|
||||
pass
|
||||
|
||||
return report
|
||||
Reference in New Issue
Block a user