NLP-beginner Claude Opus 4.8 commited on
Commit
d7687c2
·
1 Parent(s): f28d994

Add curated submission zip build script

Browse files

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Files changed (1) hide show
  1. scripts/build_submission_zip.py +152 -0
scripts/build_submission_zip.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Build the curated, TA-runnable submission ZIP for CS3319 Project 2.
4
+
5
+ The repo is 3.2 GB; this script selects the minimal set needed to:
6
+ (a) read the paper (PDF + LaTeX source + figures),
7
+ (b) run the load-weights smoke test (code/run_inference.ipynb),
8
+ (c) inspect the final result + final submission CSV,
9
+ and leaves the multi-GB intermediate artifacts in the Hugging Face backup.
10
+
11
+ Usage:
12
+ python scripts/build_submission_zip.py # -> cs3319_final_deliverable.zip
13
+ python scripts/build_submission_zip.py --out X.zip
14
+ """
15
+ from __future__ import annotations
16
+ import argparse, zipfile, os, sys
17
+ from pathlib import Path
18
+
19
+ ROOT = Path(__file__).resolve().parents[1]
20
+ TOP = "cs3319_final_deliverable" # top-level folder inside the zip
21
+
22
+ # ---- directories included in full ----
23
+ FULL_DIRS = [
24
+ "code",
25
+ "checkpoints/final_ens6",
26
+ "checkpoints/extra_models",
27
+ "data_and_docs",
28
+ "figures_v2",
29
+ "figures_paper",
30
+ "reports",
31
+ "docs/diagrams",
32
+ "docs_first_principles",
33
+ "env",
34
+ "notes",
35
+ ]
36
+
37
+ # ---- individual files (cherry-picked from larger trees) ----
38
+ EXTRA_FILES = [
39
+ "README.md",
40
+ "SUBMISSION_README.md",
41
+ "AI_USAGE.md",
42
+ "scripts/render_diagrams.sh",
43
+ "scripts/build_submission_zip.py",
44
+ "validation_runs/dynamic_summary.csv",
45
+ "validation_runs/stack_ratio_analysis.csv",
46
+ "validation_runs/stack_threshold_summary.csv",
47
+ "validation_runs/dynamic_seed202/val_labels_seed202.npy",
48
+ "validation_runs/dynamic_seed202/val_pairs_seed202.npy",
49
+ "cached_scores/test_known_mask.npy",
50
+ "cached_scores/test_lgb_scores.npy",
51
+ "cached_scores/test_lgb_v2_scores.npy",
52
+ "cached_scores/test_bpr_cos.npy",
53
+ "cached_scores/test_bpr_dot.npy",
54
+ "cached_scores/lgb_model.pkl",
55
+ "cached_scores/lgb_v2_model.pkl",
56
+ "ACM_Conference_Proceedings_Primary_Article_Template/cs3319_final_paper_cn.tex",
57
+ "ACM_Conference_Proceedings_Primary_Article_Template/cs3319_final_paper_cn.pdf",
58
+ "ACM_Conference_Proceedings_Primary_Article_Template/cs3319_final_paper_cn.bbl",
59
+ "ACM_Conference_Proceedings_Primary_Article_Template/cs3319_references.bib",
60
+ "ACM_Conference_Proceedings_Primary_Article_Template/acmart.cls",
61
+ "ACM_Conference_Proceedings_Primary_Article_Template/ACM-Reference-Format.bst",
62
+ ]
63
+
64
+ # whole subdirectory under validation_runs/dynamic_seed202 to include (the result)
65
+ RESULT_DIRS = [
66
+ "validation_runs/dynamic_seed202/high_order_graph_stack",
67
+ ]
68
+
69
+ SKIP_NAMES = {"__pycache__", ".ipynb_checkpoints", ".git", ".cache"}
70
+ SKIP_SUFFIXES = (".pyc", ".pyo")
71
+
72
+
73
+ def should_skip(p: Path) -> bool:
74
+ if any(part in SKIP_NAMES for part in p.parts):
75
+ return True
76
+ if p.suffix in SKIP_SUFFIXES:
77
+ return True
78
+ return False
79
+
80
+
81
+ def collect() -> list[Path]:
82
+ files: list[Path] = []
83
+ seen: set[Path] = set()
84
+
85
+ def add(p: Path):
86
+ if p in seen:
87
+ return
88
+ if not p.exists():
89
+ print(f" ! missing (skipped): {p}", file=sys.stderr)
90
+ return
91
+ seen.add(p)
92
+ files.append(p)
93
+
94
+ for d in FULL_DIRS + RESULT_DIRS:
95
+ base = ROOT / d
96
+ if not base.exists():
97
+ print(f" ! missing dir (skipped): {d}", file=sys.stderr)
98
+ continue
99
+ for p in base.rglob("*"):
100
+ if p.is_file() and not should_skip(p):
101
+ add(p)
102
+ for f in EXTRA_FILES:
103
+ p = ROOT / f
104
+ if p.is_file() and not should_skip(p):
105
+ add(p)
106
+ else:
107
+ print(f" ! missing file (skipped): {f}", file=sys.stderr)
108
+ return sorted(files)
109
+
110
+
111
+ def main():
112
+ ap = argparse.ArgumentParser()
113
+ ap.add_argument("--out", default=str(ROOT / "cs3319_final_deliverable.zip"))
114
+ ap.add_argument("--top", default=TOP)
115
+ args = ap.parse_args()
116
+
117
+ files = collect()
118
+ total = sum(p.stat().st_size for p in files)
119
+ print(f"selected {len(files)} files, {total/1e6:.1f} MB uncompressed")
120
+
121
+ out = Path(args.out)
122
+ # write zip (LARGE_DEFLATE via ZIP_DEFLATED; binary files added as-is effectively)
123
+ with zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED, compresslevel=6, allowZip64=True) as z:
124
+ # MANIFEST first, at top level
125
+ manifest_lines = [
126
+ f"CS3319 Project 2 — curated submission package",
127
+ f"Built from repo: {ROOT}",
128
+ f"Files: {len(files)} Uncompressed: {total/1e6:.1f} MB",
129
+ f"Public LB F1 = 0.96626 | validation F1 = 0.966874",
130
+ "",
131
+ "TA verification: see SUBMISSION_README.md (3 steps, CPU, seconds).",
132
+ "Run: jupyter nbconvert --to notebook --execute code/run_inference.ipynb",
133
+ "",
134
+ "=== File list (relative paths) ===",
135
+ "",
136
+ ]
137
+ rels = sorted(p.relative_to(ROOT).as_posix() for p in files)
138
+ manifest_lines += rels
139
+ z.writestr(f"{args.top}/MANIFEST.txt", "\n".join(manifest_lines) + "\n")
140
+
141
+ for p in files:
142
+ arc = f"{args.top}/{p.relative_to(ROOT).as_posix()}"
143
+ z.write(p, arc)
144
+
145
+ zsize = out.stat().st_size
146
+ print(f"\nwrote {out}")
147
+ print(f"zip size: {zsize/1e6:.1f} MB ({zsize/1073741824:.2f} GB)")
148
+ print(f"ratio: {zsize/max(total,1)*100:.1f}% of uncompressed")
149
+
150
+
151
+ if __name__ == "__main__":
152
+ main()