musabc commited on
Commit
5fc6ce3
·
verified ·
1 Parent(s): 84c6753

upload hf_push_v5.py

Browse files
Files changed (1) hide show
  1. hf_push_v5.py +280 -0
hf_push_v5.py ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Lightning AI'dan HuggingFace'e V5 verisi + checkpoint yukle.
3
+
4
+ 3 ayri repo kullanir (clean separation):
5
+ - musabc/nanogpt-tr-v5-data (dataset, ~30GB binaries + tokenizer)
6
+ - musabc/nanogpt-tr-v5-ckpts (model, latest_ckpt.pt + best_ckpt.pt)
7
+ - musabc/nanogpt-tr-v5-code (model, scripts — Thunder'da clone edilir)
8
+
9
+ Kullanim:
10
+ huggingface-cli login # bir kere
11
+ python hf_push_v5.py --all # her seyi yukle
12
+ python hf_push_v5.py --data # sadece binaries + tokenizer
13
+ python hf_push_v5.py --ckpt # sadece checkpoints
14
+ python hf_push_v5.py --code # sadece scriptler
15
+ python hf_push_v5.py --user musabc # user/org override
16
+
17
+ NOT: ilk yuklemede 30+ GB upload, internet hizina gore 30-60 dk.
18
+ huggingface_hub multipart upload otomatik kullanir.
19
+ """
20
+
21
+ import argparse
22
+ import os
23
+ import sys
24
+ from pathlib import Path
25
+
26
+ try:
27
+ from huggingface_hub import HfApi, create_repo, upload_file, upload_folder
28
+ except ImportError:
29
+ print("! huggingface_hub yok. Yukle: pip install -U huggingface_hub")
30
+ sys.exit(1)
31
+
32
+ REPO_BASE = "nanogpt-tr-v5"
33
+ DEFAULT_USER = "musabc"
34
+
35
+ ROOT = Path(__file__).parent
36
+ DATA_DIR = ROOT / "data"
37
+ RUN_DIR = ROOT / "runs" / "tr-200m-v5"
38
+
39
+ # Veri repo'suna gidecekler (dataset)
40
+ DATA_FILES = [
41
+ DATA_DIR / "v5_stage1.bin",
42
+ DATA_DIR / "v5_stage2.bin",
43
+ DATA_DIR / "v5_stage3.bin",
44
+ DATA_DIR / "v5_val.bin",
45
+ DATA_DIR / "v5_val_stage1.bin", # opsiyonel — yoksa atlanir
46
+ DATA_DIR / "v5_val_stage2.bin",
47
+ DATA_DIR / "v5_val_stage3.bin",
48
+ DATA_DIR / "tokenizer-tr-v5.json",
49
+ ]
50
+
51
+ # Checkpoint repo'suna gidecekler (model)
52
+ CKPT_FILES = [
53
+ RUN_DIR / "latest_ckpt.pt",
54
+ RUN_DIR / "best_ckpt.pt",
55
+ RUN_DIR / "train.log",
56
+ ]
57
+
58
+ # Kod repo'suna gidecekler (model — kod da model repo'sunda ok)
59
+ CODE_FILES = [
60
+ "model_v5.py",
61
+ "muon.py",
62
+ "05_train_v5.py",
63
+ "06_sample.py",
64
+ "04_tokenize.py",
65
+ "04b_make_val.py",
66
+ "hf_push_v5.py",
67
+ "hf_pull_v5.py", # asagida olusturulacak
68
+ ]
69
+
70
+
71
+ def fmt_size(b):
72
+ for u in ["B", "KB", "MB", "GB"]:
73
+ if b < 1024:
74
+ return f"{b:.1f} {u}"
75
+ b /= 1024
76
+ return f"{b:.1f} TB"
77
+
78
+
79
+ def ensure_repo(api: HfApi, repo_id: str, repo_type: str, private: bool):
80
+ try:
81
+ api.repo_info(repo_id, repo_type=repo_type)
82
+ print(f" ✓ repo var: {repo_id} ({repo_type})")
83
+ except Exception:
84
+ print(f" + repo olusturuluyor: {repo_id} ({repo_type}, private={private})")
85
+ create_repo(repo_id, repo_type=repo_type, private=private, exist_ok=True)
86
+
87
+
88
+ def push_files(api: HfApi, repo_id: str, repo_type: str,
89
+ files: list, target_subdir: str = ""):
90
+ total_size = 0
91
+ pushed = 0
92
+ skipped = 0
93
+ for f in files:
94
+ f = Path(f)
95
+ if not f.exists():
96
+ print(f" - atlandı (yok): {f.name}")
97
+ skipped += 1
98
+ continue
99
+ size = f.stat().st_size
100
+ total_size += size
101
+ target = f"{target_subdir}/{f.name}" if target_subdir else f.name
102
+ print(f" → {f.name} ({fmt_size(size)}) upload...", flush=True)
103
+ api.upload_file(
104
+ path_or_fileobj=str(f),
105
+ path_in_repo=target,
106
+ repo_id=repo_id,
107
+ repo_type=repo_type,
108
+ commit_message=f"upload {f.name}",
109
+ )
110
+ pushed += 1
111
+ print(f"\n ✓ {pushed} dosya yuklendi ({fmt_size(total_size)}), "
112
+ f"{skipped} atlandi")
113
+
114
+
115
+ def write_data_readme():
116
+ """Dataset repo icin README olustur."""
117
+ content = """---
118
+ language: tr
119
+ license: cc-by-4.0
120
+ size_categories:
121
+ - 10B<n<100B
122
+ tags:
123
+ - turkish
124
+ - pretraining
125
+ - language-modeling
126
+ ---
127
+
128
+ # nanogpt-tr-v5 Data
129
+
130
+ V5 (200M Türkçe LM) eğitimi için tokenize edilmiş veri.
131
+
132
+ ## Dosyalar
133
+
134
+ - `v5_stage1.bin` — Web tier (OSCAR, mC4, forum, FineWeb-HQ) ~2.94B token
135
+ - `v5_stage2.bin` — Medium tier (BellaTurca, Cosmos, CulturaX, Havadis, Cosmopedia) ~9.03B token
136
+ - `v5_stage3.bin` — Premium tier (Wiki, Wikisource, Tezler, Akademik, FinePDFs, Özenli) ~2.97B token
137
+ - `v5_val.bin` — Validation (3 stage'in son %1'i, ~150M token)
138
+ - `tokenizer-tr-v5.json` — BPE tokenizer, 32K vocab, Stage3 üzerinde eğitildi
139
+
140
+ ## Format
141
+
142
+ - uint16 token id'leri (vocab=32000 < 65535)
143
+ - Numpy memmap ile okunur:
144
+ ```python
145
+ import numpy as np
146
+ data = np.memmap("v5_stage1.bin", dtype=np.uint16, mode="r")
147
+ ```
148
+
149
+ ## Üretim
150
+
151
+ Bkz. [code repo](https://huggingface.co/{user}/nanogpt-tr-v5-code).
152
+ """
153
+ return content
154
+
155
+
156
+ def write_ckpt_readme():
157
+ """Checkpoint repo icin README."""
158
+ content = """---
159
+ language: tr
160
+ license: apache-2.0
161
+ tags:
162
+ - turkish
163
+ - pretrained
164
+ - gpt
165
+ ---
166
+
167
+ # nanogpt-tr-v5 Checkpoints
168
+
169
+ V5 200M Türkçe pretrained LM, multi-stage curriculum eğitimi.
170
+
171
+ ## Mimari
172
+
173
+ - 18 layer, 14 head, 896 embd
174
+ - 32K vocab, 2048 context
175
+ - RoPE (theta=100K) + RMSNorm + SwiGLU + QK-norm
176
+ - Logit soft-cap (30) + tied embeddings
177
+ - 210M parametre
178
+
179
+ ## Eğitim
180
+
181
+ - 21.6B token, multi-stage curriculum (web → medium → premium annealing)
182
+ - Muon (2D weights) + AdamW (1D + embed)
183
+ - bf16 mixed precision, torch.compile
184
+ - Lightning AI → Thunder Compute migration
185
+
186
+ ## Yükleme
187
+
188
+ ```python
189
+ import torch
190
+ from model_v5 import GPTV5, GPTConfigV5
191
+
192
+ ckpt = torch.load("best_ckpt.pt", weights_only=False)
193
+ cfg = GPTConfigV5(**ckpt["config"])
194
+ model = GPTV5(cfg)
195
+ state = {k.replace("_orig_mod.", ""): v for k, v in ckpt["model"].items()}
196
+ model.load_state_dict(state)
197
+ ```
198
+
199
+ ## Sample
200
+
201
+ `code` repo'sundaki `06_sample.py` kullanın.
202
+ """
203
+ return content
204
+
205
+
206
+ def main():
207
+ parser = argparse.ArgumentParser()
208
+ parser.add_argument("--all", action="store_true")
209
+ parser.add_argument("--data", action="store_true")
210
+ parser.add_argument("--ckpt", action="store_true")
211
+ parser.add_argument("--code", action="store_true")
212
+ parser.add_argument("--user", type=str, default=DEFAULT_USER,
213
+ help="HuggingFace user/org adı")
214
+ parser.add_argument("--private", action="store_true",
215
+ help="Repo'ları private yap (varsayılan: public)")
216
+ parser.add_argument("--token", type=str, default=None,
217
+ help="HF token (yoksa env HF_TOKEN veya cache)")
218
+ args = parser.parse_args()
219
+
220
+ if not (args.all or args.data or args.ckpt or args.code):
221
+ print("! Hiçbir hedef seçilmedi. --all / --data / --ckpt / --code")
222
+ sys.exit(1)
223
+
224
+ api = HfApi(token=args.token or os.environ.get("HF_TOKEN"))
225
+ # Token kontrol
226
+ try:
227
+ whoami = api.whoami()
228
+ print(f"HF user: {whoami['name']}")
229
+ except Exception as e:
230
+ print(f"! HF login problemi: {e}")
231
+ print(" huggingface-cli login ile bir kere giris yap.")
232
+ sys.exit(1)
233
+
234
+ data_repo = f"{args.user}/{REPO_BASE}-data"
235
+ ckpt_repo = f"{args.user}/{REPO_BASE}-ckpts"
236
+ code_repo = f"{args.user}/{REPO_BASE}-code"
237
+
238
+ # DATA
239
+ if args.all or args.data:
240
+ print(f"\n{'='*60}\nDATA upload → {data_repo}\n{'='*60}")
241
+ ensure_repo(api, data_repo, "dataset", args.private)
242
+ push_files(api, data_repo, "dataset", DATA_FILES)
243
+ # README
244
+ readme = write_data_readme().replace("{user}", args.user)
245
+ api.upload_file(
246
+ path_or_fileobj=readme.encode(),
247
+ path_in_repo="README.md",
248
+ repo_id=data_repo, repo_type="dataset",
249
+ commit_message="add README",
250
+ )
251
+ print(f" ✓ README yazildi")
252
+
253
+ # CKPT
254
+ if args.all or args.ckpt:
255
+ print(f"\n{'='*60}\nCKPT upload → {ckpt_repo}\n{'='*60}")
256
+ ensure_repo(api, ckpt_repo, "model", args.private)
257
+ push_files(api, ckpt_repo, "model", CKPT_FILES)
258
+ readme = write_ckpt_readme()
259
+ api.upload_file(
260
+ path_or_fileobj=readme.encode(),
261
+ path_in_repo="README.md",
262
+ repo_id=ckpt_repo, repo_type="model",
263
+ commit_message="add README",
264
+ )
265
+ print(f" ✓ README yazildi")
266
+
267
+ # CODE
268
+ if args.all or args.code:
269
+ print(f"\n{'='*60}\nCODE upload → {code_repo}\n{'='*60}")
270
+ ensure_repo(api, code_repo, "model", args.private)
271
+ code_paths = [ROOT / f for f in CODE_FILES]
272
+ push_files(api, code_repo, "model", code_paths)
273
+
274
+ print(f"\n{'='*60}\n✓ TAMAMLANDI\n{'='*60}")
275
+ print(f"\nThunder Compute'da indirmek için:")
276
+ print(f" python hf_pull_v5.py --user {args.user}")
277
+
278
+
279
+ if __name__ == "__main__":
280
+ main()