File size: 4,152 Bytes
e317359
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env python3
import os
import sys
import argparse
from pathlib import Path
from dotenv import load_dotenv
from huggingface_hub import HfApi

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--yes", action="store_true", help="Auto confirm deletion")
    args = parser.parse_args()

    REPO_ROOT = Path(__file__).resolve().parents[1]
    load_dotenv(REPO_ROOT / ".env")

    token = os.getenv("HF_TOKEN")
    repo_id = os.getenv("HF_SPACE_REPO", "ThinkcatLab/LiveHouse-TS")

    if not token:
        print("HF_TOKEN not found in .env", file=sys.stderr)
        return 1

    print(f"Connecting to Hugging Face Space: {repo_id}")
    api = HfApi(token=token)

    # List all files in the repository
    try:
        files = api.list_repo_files(repo_id=repo_id, repo_type="space")
    except Exception as e:
        print(f"Failed to list files: {e}", file=sys.stderr)
        return 1

    allowed_dirs = {
        "aggregates",
        "arima",
        "chronos_bolt",
        "chronos_2",
        "ets",
        "moirai_2_0",
        "moving_average",
        "seasonal_naive",
        "sundial",
        "tabpfn_ts",
        "timesfm_2_5",
        "tirex",
        "toto_1_0",
    }

    allowed_files = {
        "online_status.json",
        "dataset_properties.csv",
        "dataset_eval_intervals.json",
        "eval_history.jsonl",
        "eval_state.json",
        "baseline_rank_history.csv",
        "baseline_rank_history_daily.csv",
        "baseline_rank_history_weekly.csv",
        "model_allowlist.json",
    }

    files_to_delete = []

    for f in files:
        if not f.startswith("results/"):
            continue

        parts = f.split("/")
        if len(parts) < 2:
            continue

        # check if it is a file directly under results/
        if len(parts) == 2:
            filename = parts[1]
            if filename in {"evaluation_metrics.jsonl", "evaluation_metrics_canonical.jsonl"}:
                files_to_delete.append(f)
            elif filename not in allowed_files:
                files_to_delete.append(f)
        else:
            # it is inside a subdirectory under results/
            sub_dir = parts[1]
            if sub_dir == "aggregates" and (
                parts[-1].endswith(".zip")
                or parts[-1] == "evaluation_metrics_canonical.jsonl"
                or "canonical_all_history" in parts
            ):
                files_to_delete.append(f)
            elif sub_dir == "saved_evals" or "forecasts" in parts:
                files_to_delete.append(f)
            elif sub_dir not in allowed_dirs:
                files_to_delete.append(f)

    if not files_to_delete:
        print("No extra files to delete on remote Space.")
        return 0

    print(f"Found {len(files_to_delete)} files to delete from Hugging Face Space:")
    for f in files_to_delete[:20]:
        print(f" - {f}")
    if len(files_to_delete) > 20:
        print(f" ... and {len(files_to_delete) - 20} more.")

    if not args.yes:
        confirm = input("Proceed with deletion? (y/n): ").strip().lower()
        if confirm != "y":
            print("Cancelled.")
            return 0

    # Delete the files using api.delete_file or commit operations
    from huggingface_hub import CommitOperationDelete

    operations = [CommitOperationDelete(path_in_repo=f) for f in files_to_delete]

    # We batch commit in chunks of 500 files to avoid payload limits
    chunk_size = 500
    for i in range(0, len(operations), chunk_size):
        chunk = operations[i:i+chunk_size]
        print(f"Deleting chunk {i // chunk_size + 1} ({len(chunk)} files)...")
        try:
            api.create_commit(
                repo_id=repo_id,
                repo_type="space",
                operations=chunk,
                commit_message=f"Clean remote results: delete extra model files (part {i // chunk_size + 1})",
            )
        except Exception as e:
            print(f"Failed to delete chunk: {e}", file=sys.stderr)
            return 1

    print("Deletion completed successfully.")
    return 0

if __name__ == "__main__":
    sys.exit(main())