cfahlgren1 HF Staff commited on
Commit
3f7cc27
·
verified ·
1 Parent(s): e60e429

remove the 3b-token experiment folder, now the same as v2

Browse files
README.md CHANGED
@@ -157,7 +157,7 @@ The browser computes in float32 on purpose: onnxruntime-web's int8 kernels were
157
  | `v2/eval.py`, `v2/eval_set.json` | The eval harness and the fixed text it scores |
158
  | `v2/export.py`, `v2/compress.py` | Re-export to ONNX, and the int8 download format |
159
  | `v2/metrics/*.json` | Eval results for v1, v2, the browser format, SmolLM2-135M and Pythia 14M–160M |
160
- | `v2/experiments/` | The no-FIM run, and the 3B-token run as trained (the same weights as `v2/`) |
161
  | `v2/report.json` | Training settings, loss history and export checks |
162
 
163
  </details>
 
157
  | `v2/eval.py`, `v2/eval_set.json` | The eval harness and the fixed text it scores |
158
  | `v2/export.py`, `v2/compress.py` | Re-export to ONNX, and the int8 download format |
159
  | `v2/metrics/*.json` | Eval results for v1, v2, the browser format, SmolLM2-135M and Pythia 14M–160M |
160
+ | `v2/experiments/` | The no-FIM run, for comparison |
161
  | `v2/report.json` | Training settings, loss history and export checks |
162
 
163
  </details>
v2/experiments/tinynext-v2-3b/config.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "vocab": 8192,
3
- "dim": 320,
4
- "layers": 8,
5
- "heads": 5,
6
- "ffn": 864,
7
- "parameters": 12539200,
8
- "seq": 512,
9
- "special_tokens": {
10
- "<|endoftext|>": 0,
11
- "<|pre|>": 1,
12
- "<|suf|>": 2,
13
- "<|mid|>": 3
14
- },
15
- "prompt": "No text after the cursor: the text before it. Otherwise: <|suf|> after <|pre|> before <|mid|>."
16
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
v2/experiments/tinynext-v2-3b/eval.py DELETED
@@ -1,499 +0,0 @@
1
- # /// script
2
- # requires-python = ">=3.11,<3.14"
3
- # dependencies = [
4
- # "torch>=2.6,<2.8",
5
- # "datasets>=3.0",
6
- # "numpy<3",
7
- # "onnxruntime>=1.20",
8
- # "transformers>=4.46",
9
- # "tokenizers>=0.20",
10
- # ]
11
- # ///
12
- """Scores autocomplete models the way people use them: type real text, pause, and see if the gray suggestion is right.
13
-
14
- Every model sees the same pauses in the same text and is decoded with the same rule as offline.page:
15
- follow the model's top pick while the running product of probabilities stays above a cutoff, and show
16
- the text up to the last finished word. A suggestion is right when the text really continues that way.
17
-
18
- Two scenarios:
19
- typing the cursor is at the end of what's written so far.
20
- editing the cursor is mid-sentence and real text follows a gap of 2-6 words. Only fill-in-the-middle
21
- models are given that text; the rest see only what's before the cursor.
22
-
23
- Usage:
24
- uv run eval.py --model tinynext-v1 --onnx model_quint8.onnx
25
- uv run eval.py --model smollm2-135m --hf HuggingFaceTB/SmolLM2-135M
26
- uv run eval.py --table # compare every metrics/*.json
27
- """
28
-
29
- import argparse
30
- import hashlib
31
- import json
32
- import random
33
- import re
34
- import statistics
35
- import time
36
- from collections.abc import Callable
37
- from dataclasses import dataclass, field
38
- from pathlib import Path
39
-
40
- import numpy as np
41
-
42
- HERE = Path(__file__).parent
43
- EVAL_SET = HERE / "eval_set.json"
44
- METRICS = HERE / "metrics"
45
-
46
- CUTOFFS = (0.3, 0.4, 0.5, 0.6, 0.7)
47
- MAIN_CUTOFF = 0.5 # what offline.page uses
48
- PAUSE_EVERY = 12 # characters between pauses
49
- MIN_SHOWN_CHARS = 4 # offline.page hides shorter suggestions
50
- MAX_WORDS = 6
51
- MAX_CHARS = 48
52
- DOMAINS = ("articles", "messages", "email")
53
- SCENARIOS = ("typing", "editing")
54
- PUNCTUATION = ".,!?;:"
55
-
56
- # ---- Eval text -------------------------------------------------------------------------------------------------
57
- # Kept apart from training: Wikipedia isn't in either model's data, OpenAssistant validation isn't in SmolTalk's
58
- # training split, and the emails come from the senders the original enron-autocomplete held out for its test set.
59
-
60
- CUT_REPLY = re.compile(
61
- r"(?im)^\s*(?:-+\s*original message|-+\s*forwarded by|-+\s*inline attachment|from:\s|to:\s|sent:\s"
62
- r"|subject:\s|cc:\s|.*\bwrote:\s*$|_{5,}|-{5,}|={5,}|\*{5,}|\d{1,2}/\d{1,2}/\d{2,4}\s+\d{1,2}:\d{2})"
63
- )
64
- SENSITIVE = re.compile(r"(?i)https?://|www\.|\S+@\S+|\(?\b\d{3}\)?[-. ]\d{3}[-. ]\d{4}\b|\b\d{3}-\d{2}-\d{4}\b")
65
- BULK_SENDER = re.compile(r"(?i)announce|newsletter|mailer|outlook\.team|^all[._]|general\.|chairman|enron\.(?:on|net)")
66
- SMART_CHARS = str.maketrans({"‘": "'", "’": "'", "“": '"', "”": '"', "–": "-", "—": "-", "\t": " "})
67
-
68
-
69
- def clean_email(body: str) -> list[str]:
70
- """The same cleaning enron-autocomplete was trained with."""
71
- text = body.replace("\r\n", "\n").replace("=20", " ").replace("=\n", "").translate(SMART_CHARS)
72
- text = "\n".join(line for line in text.split("\n") if not line.lstrip().startswith(">"))
73
- cut = CUT_REPLY.search(text)
74
- if cut:
75
- text = text[: cut.start()]
76
- text = re.sub(r"(?m)^-- *\n[\s\S]*", "", text)
77
- paragraphs = []
78
- for block in re.split(r"\n\s*\n", text):
79
- lines = [re.sub(r" +", " ", line).strip() for line in block.split("\n") if line.strip()]
80
- if not lines:
81
- continue
82
- joined = lines[0]
83
- for previous, line in zip(lines, lines[1:]):
84
- joined += (" " if len(previous) >= 50 else "\n") + line
85
- if SENSITIVE.search(joined) or sum(c.isalpha() for c in joined) < 0.6 * len(joined):
86
- continue
87
- paragraphs.append(joined)
88
- return paragraphs
89
-
90
-
91
- def is_held_out_sender(sender: str) -> bool:
92
- """enron-autocomplete put senders whose hash bucket is under 5 in its test split."""
93
- sender = sender.lower()
94
- if "@enron.com" not in sender or BULK_SENDER.search(sender):
95
- return False
96
- return int(hashlib.sha1(sender.encode()).hexdigest(), 16) % 100 < 5
97
-
98
-
99
- def ascii_paragraphs(text: str, min_chars: int = 40) -> list[str]:
100
- text = text.translate(SMART_CHARS).encode("ascii", "ignore").decode()
101
- return [p.strip() for p in re.split(r"\n\s*\n|\n", text) if len(p.strip()) >= min_chars]
102
-
103
-
104
- def build_eval_set(docs_per_domain: int = 80) -> dict[str, list[list[str]]]:
105
- from datasets import load_dataset
106
-
107
- sets: dict[str, list[list[str]]] = {domain: [] for domain in DOMAINS}
108
- wiki = load_dataset(
109
- "wikimedia/wikipedia", data_files="20231101.en/train-00040-of-00041.parquet", split="train", streaming=True
110
- )
111
- for row in wiki:
112
- paragraphs = [p for p in ascii_paragraphs(row["text"], 80) if not p.endswith(":")][:6]
113
- if len(paragraphs) >= 3:
114
- sets["articles"].append(paragraphs)
115
- if len(sets["articles"]) >= docs_per_domain:
116
- break
117
-
118
- for row in load_dataset("OpenAssistant/oasst1", split="validation"):
119
- if row["lang"] == "en" and "```" not in row["text"]:
120
- paragraphs = ascii_paragraphs(row["text"])[:6]
121
- if paragraphs:
122
- sets["messages"].append(paragraphs)
123
- if len(sets["messages"]) >= docs_per_domain:
124
- break
125
-
126
- for row in load_dataset("corbt/enron-emails", split="train", streaming=True):
127
- if is_held_out_sender(row["from"] or ""):
128
- paragraphs = [p for p in clean_email(row["body"] or "") if len(p) >= 40][:6]
129
- if paragraphs:
130
- sets["email"].append(paragraphs)
131
- if len(sets["email"]) >= docs_per_domain:
132
- break
133
- return sets
134
-
135
-
136
- def load_eval_set() -> dict[str, list[list[str]]]:
137
- if not EVAL_SET.exists():
138
- EVAL_SET.write_text(json.dumps(build_eval_set(), indent=1))
139
- return json.loads(EVAL_SET.read_text())
140
-
141
-
142
- @dataclass
143
- class Pause:
144
- domain: str
145
- scenario: str
146
- before: str # the document up to the cursor
147
- after: str # text after the cursor that a model may see (empty when typing)
148
- truth: str # what the person actually typed next
149
-
150
-
151
- def pauses(eval_set: dict[str, list[list[str]]], max_per_domain: int) -> list[Pause]:
152
- rng = random.Random(0)
153
- found: list[Pause] = []
154
- for domain in DOMAINS:
155
- in_domain: list[Pause] = []
156
- for paragraphs in eval_set[domain]:
157
- for index, paragraph in enumerate(paragraphs):
158
- earlier = "\n".join(paragraphs[:index])
159
- for at in range(PAUSE_EVERY, len(paragraph) - 8, PAUSE_EVERY):
160
- before = (earlier + "\n" if earlier else "") + paragraph[:at]
161
- truth = paragraph[at:]
162
- in_domain.append(Pause(domain, "typing", before, "", truth))
163
- # Editing: a gap of 2-6 words, then the rest of the paragraph as it was written.
164
- gap_words = rng.randint(2, 6)
165
- gap = re.match(r"(\S*\s+){%d}" % gap_words, truth)
166
- if gap and len(truth) > gap.end() + 10:
167
- in_domain.append(Pause(domain, "editing", before, truth[gap.end():], truth))
168
- rng.shuffle(in_domain)
169
- found += [p for p in in_domain if p.scenario == "typing"][:max_per_domain]
170
- found += [p for p in in_domain if p.scenario == "editing"][:max_per_domain]
171
- return found
172
-
173
-
174
- # ---- Decoding -------------------------------------------------------------------------------------------------
175
-
176
-
177
- @dataclass
178
- class Trajectory:
179
- """Suggestions that end at a word boundary, with the model's confidence in each. Greedy decoding gives the
180
- same path for every cutoff, so one decode answers all of them."""
181
-
182
- candidates: list[tuple[str, float]] = field(default_factory=list)
183
- milliseconds: float = 0.0
184
-
185
- def at(self, cutoff: float) -> str:
186
- best = ""
187
- for text, confidence in self.candidates:
188
- if confidence >= cutoff:
189
- best = text
190
- return best.rstrip()
191
-
192
-
193
- class Model:
194
- name: str
195
- sees_after: bool = False
196
-
197
- def suggest(self, before: str, after: str) -> Trajectory:
198
- raise NotImplementedError
199
-
200
-
201
- class CharGRU(Model):
202
- """enron-autocomplete / tinynext v1: one character per step, reading only the current paragraph."""
203
-
204
- HIDDEN, END, NEWLINE, FIRST, OFFSET = 512, 1, 2, 3, 29
205
-
206
- def __init__(self, name: str, onnx_path: str):
207
- import onnxruntime as ort
208
-
209
- self.name = name
210
- self.session = ort.InferenceSession(onnx_path, providers=["CPUExecutionProvider"])
211
- self.read_text: str | None = None
212
- self.reading = None
213
-
214
- def step(self, char_id: int, state):
215
- logits, state = self.session.run(None, {"input_id": np.array([char_id], np.int64), "state": state})
216
- return logits[0], state
217
-
218
- def encode(self, char: str) -> int | None:
219
- if char == "\n":
220
- return self.NEWLINE
221
- code = ord(char)
222
- return code - self.OFFSET if 32 <= code <= 126 else None
223
-
224
- def read(self, text: str):
225
- if self.read_text is None or not text.startswith(self.read_text):
226
- self.reading = self.step(self.END, np.zeros((1, self.HIDDEN), np.float32))
227
- self.read_text = ""
228
- for char in text[len(self.read_text):]:
229
- char_id = self.encode(char)
230
- if char_id is not None:
231
- self.reading = self.step(char_id, self.reading[1])
232
- self.read_text = text
233
- return self.reading
234
-
235
- def suggest(self, before: str, after: str) -> Trajectory:
236
- began = time.perf_counter()
237
- logits, state = self.read(before.split("\n")[-1])
238
- trajectory, run, confidence, words = Trajectory(), "", 1.0, 0
239
- while len(run) < MAX_CHARS and confidence >= min(CUTOFFS):
240
- probabilities = np.exp(logits - logits.max())
241
- probabilities /= probabilities.sum()
242
- char_id = int(probabilities.argmax())
243
- if char_id < self.FIRST:
244
- if run:
245
- trajectory.candidates.append((run, confidence))
246
- break
247
- char = chr(char_id + self.OFFSET)
248
- if char == " ":
249
- trajectory.candidates.append((run, confidence))
250
- words += 1
251
- if words >= MAX_WORDS:
252
- break
253
- confidence *= float(probabilities[char_id])
254
- run += char
255
- if char in PUNCTUATION:
256
- trajectory.candidates.append((run, confidence))
257
- logits, state = self.step(char_id, state)
258
- trajectory.milliseconds = (time.perf_counter() - began) * 1000
259
- return trajectory
260
-
261
-
262
- class TokenLM(Model):
263
- """A word-piece model. `next_logits(ids, cache)` runs one forward pass and returns (last logits, cache).
264
-
265
- The word being typed is "healed": the prompt stops before it, and the first generated pieces must spell it
266
- out, so a half-typed word like "resig" can still become "resignation" in one piece.
267
- """
268
-
269
- def __init__(self, name: str, next_logits: Callable, encode: Callable[[str], list[int]], token_texts: list[str],
270
- stop_ids: set[int], prompt: Callable[[list[int], list[int]], list[int]] | None = None,
271
- context_chars: int = 1500, suffix_chars: int = 300):
272
- self.name = name
273
- self.next_logits = next_logits
274
- self.encode = encode
275
- self.token_texts = token_texts
276
- self.stop_ids = stop_ids
277
- self.prompt = prompt
278
- self.sees_after = prompt is not None
279
- self.context_chars = context_chars
280
- self.suffix_chars = suffix_chars
281
- lengths = np.array([len(t) for t in token_texts])
282
- self.nonempty = lengths > 0
283
-
284
- def allowed(self, need: str) -> np.ndarray:
285
- """Pieces consistent with the rest of the half-typed word."""
286
- return np.array([bool(t) and (need.startswith(t) or t.startswith(need)) for t in self.token_texts])
287
-
288
- def suggest(self, before: str, after: str) -> Trajectory:
289
- began = time.perf_counter()
290
- before = before[-self.context_chars:]
291
- # The half-typed word keeps its leading space, since word pieces start with one. A line break stays in the prompt.
292
- space, newline = before.rfind(" "), before.rfind("\n")
293
- if space > newline:
294
- stem, need = before[:space], before[space:]
295
- else:
296
- stem, need = before[: newline + 1], before[newline + 1:]
297
- prefix_ids = self.encode(stem)
298
- if self.prompt:
299
- ids = self.prompt(prefix_ids, self.encode(after[: self.suffix_chars]) if after else [])
300
- else:
301
- ids = prefix_ids
302
- logits, cache = self.next_logits(ids, None)
303
-
304
- trajectory, generated, confidence = Trajectory(), "", 1.0
305
- for _ in range(16):
306
- logits = logits.astype(np.float64)
307
- if need:
308
- mask = self.allowed(need)
309
- if not mask.any():
310
- break
311
- logits = np.where(mask, logits, -np.inf)
312
- probabilities = np.exp(logits - logits.max())
313
- probabilities /= probabilities.sum()
314
- token = int(probabilities.argmax())
315
- text = self.token_texts[token]
316
- if token in self.stop_ids or "\n" in text:
317
- if generated:
318
- trajectory.candidates.append((generated, confidence))
319
- break
320
- if need:
321
- consumed = min(len(need), len(text))
322
- text, need = text[consumed:], need[consumed:]
323
- if text[:1].isspace() and generated:
324
- trajectory.candidates.append((generated, confidence))
325
- confidence *= float(probabilities[token])
326
- generated += text
327
- if generated.rstrip()[-1:] in PUNCTUATION and generated.strip():
328
- trajectory.candidates.append((generated, confidence))
329
- if confidence < min(CUTOFFS) or len(generated) > MAX_CHARS or len(generated.split()) > MAX_WORDS:
330
- break
331
- logits, cache = self.next_logits([token], cache)
332
- trajectory.milliseconds = (time.perf_counter() - began) * 1000
333
- return trajectory
334
-
335
-
336
- def hf_causal_lm(name: str, repo: str) -> TokenLM:
337
- import torch
338
- from transformers import AutoModelForCausalLM, AutoTokenizer
339
-
340
- device = "mps" if torch.backends.mps.is_available() else "cuda" if torch.cuda.is_available() else "cpu"
341
- tokenizer = AutoTokenizer.from_pretrained(repo)
342
- model = AutoModelForCausalLM.from_pretrained(repo, torch_dtype=torch.float32).to(device).eval()
343
-
344
- @torch.no_grad()
345
- def next_logits(ids, cache):
346
- out = model(torch.tensor([ids], device=device), past_key_values=cache, use_cache=True)
347
- return out.logits[0, -1].float().cpu().numpy(), out.past_key_values
348
-
349
- texts = [tokenizer.decode([i]) for i in range(len(tokenizer))]
350
- stops = {tokenizer.eos_token_id} if tokenizer.eos_token_id is not None else set()
351
- encode = lambda text: tokenizer.encode(text, add_special_tokens=False) or [tokenizer.eos_token_id]
352
- return TokenLM(name, next_logits, encode, texts, stops)
353
-
354
-
355
- def onnx_token_lm(name: str, folder: str, fim: bool) -> TokenLM:
356
- """A tinynext v2 export: graph.onnx + weights.f32 (compressed, expanded) or model.onnx, plus tokenizer.json."""
357
- import onnxruntime as ort
358
- from tokenizers import Tokenizer
359
-
360
- folder = Path(folder)
361
- graph = folder / "graph.onnx" if (folder / "graph.onnx").exists() else folder / "model.onnx"
362
- session = ort.InferenceSession(str(graph), providers=["CPUExecutionProvider"])
363
- config = json.loads((folder / "config.json").read_text())
364
- tokenizer = Tokenizer.from_file(str(folder / "tokenizer.json"))
365
- empty = np.zeros((config["layers"], 1, config["heads"], 0, config["dim"] // config["heads"]), np.float32)
366
-
367
- def next_logits(ids, cache):
368
- past_k, past_v = cache if cache else (empty, empty)
369
- logits, k, v = session.run(None, {"input_ids": np.array([ids], np.int64), "past_k": past_k, "past_v": past_v})
370
- return logits[0], (k, v)
371
-
372
- special = len(config["special_tokens"])
373
- texts = [tokenizer.decode([i], skip_special_tokens=False) if i >= special else "" for i in range(config["vocab"])]
374
- encode = lambda text: tokenizer.encode(text).ids or [0]
375
- prompt = (lambda prefix, suffix: prefix if not suffix else [2, *suffix, 1, *prefix, 3]) if fim else None
376
- return TokenLM(name, next_logits, encode, texts, set(range(special)), prompt=prompt)
377
-
378
-
379
- # ---- Scoring ---------------------------------------------------------------------------------------------------
380
-
381
-
382
- def word_by_word(suggestion: str, truth: str) -> int:
383
- """Characters you'd keep accepting a word at a time until a word is wrong."""
384
- kept = 0
385
- for match in re.finditer(r"\s*\S+", suggestion):
386
- if truth.startswith(suggestion[: match.end()]):
387
- kept = match.end()
388
- else:
389
- break
390
- return kept
391
-
392
-
393
- def score(model: Model, all_pauses: list[Pause]) -> dict:
394
- results: dict = {"model": model.name, "sees_after": model.sees_after, "cutoffs": {}, "examples": [], "latency_ms": {}}
395
- latencies: list[float] = []
396
- raw = []
397
- for index, pause in enumerate(all_pauses):
398
- trajectory = model.suggest(pause.before, pause.after if model.sees_after else "")
399
- latencies.append(trajectory.milliseconds)
400
- raw.append((pause, trajectory))
401
- if index % 500 == 0:
402
- print(f" {model.name}: {index}/{len(all_pauses)} pauses, median {statistics.median(latencies):.1f} ms", flush=True)
403
-
404
- for cutoff in CUTOFFS:
405
- table: dict = {}
406
- for domain in DOMAINS:
407
- for scenario in SCENARIOS:
408
- rows = [(p, t.at(cutoff)) for p, t in raw if p.domain == domain and p.scenario == scenario]
409
- if not rows:
410
- continue
411
- shown = [(p, s) for p, s in rows if len(s) >= MIN_SHOWN_CHARS]
412
- right = [(p, s) for p, s in shown if p.truth.startswith(s)]
413
- multi = [(p, s) for p, s in shown if len(s.split()) >= 2]
414
- multi_right = [(p, s) for p, s in multi if p.truth.startswith(s)]
415
- typed = len(rows) * PAUSE_EVERY
416
- table[f"{domain}/{scenario}"] = {
417
- "pauses": len(rows),
418
- "shown": round(len(shown) / len(rows), 4),
419
- "right": round(len(right) / max(1, len(shown)), 4),
420
- "avg_right_chars": round(sum(len(s) for _, s in right) / max(1, len(right)), 2),
421
- "multiword_shown": round(len(multi) / len(rows), 4),
422
- "multiword_right": round(len(multi_right) / max(1, len(multi)), 4),
423
- "saved_with_tab": round(sum(len(s) for _, s in right) / typed, 4),
424
- "saved_word_by_word": round(sum(word_by_word(s, p.truth) for p, s in shown) / typed, 4),
425
- }
426
- results["cutoffs"][str(cutoff)] = table
427
-
428
- for pause, trajectory in raw[:: max(1, len(raw) // 60)]:
429
- suggestion = trajectory.at(MAIN_CUTOFF)
430
- if len(suggestion) >= MIN_SHOWN_CHARS:
431
- results["examples"].append({
432
- "domain": pause.domain, "scenario": pause.scenario, "before": pause.before[-60:],
433
- "suggestion": suggestion, "truth": pause.truth[: len(suggestion) + 12], "right": pause.truth.startswith(suggestion),
434
- })
435
- results["latency_ms"] = {
436
- "p50": round(statistics.median(latencies), 2),
437
- "p95": round(float(np.percentile(latencies, 95)), 2),
438
- "note": "Measured in this eval process, not in a browser.",
439
- }
440
- return results
441
-
442
-
443
- # ---- Report ----------------------------------------------------------------------------------------------------
444
-
445
-
446
- def table(paths: list[Path]) -> str:
447
- runs = [json.loads(p.read_text()) for p in paths]
448
- lines = []
449
- for scenario in SCENARIOS:
450
- lines.append(f"\n### {scenario.capitalize()}, {int(MAIN_CUTOFF * 100)}% cutoff, suggestions of {MIN_SHOWN_CHARS}+ characters\n")
451
- lines.append("| Model | Domain | Shown | Right | Avg right | 2+ words shown | 2+ words right | Saved (Tab) | Saved (word by word) |")
452
- lines.append("|---|---|---|---|---|---|---|---|---|")
453
- for run in runs:
454
- for domain in DOMAINS:
455
- m = run["cutoffs"][str(MAIN_CUTOFF)].get(f"{domain}/{scenario}")
456
- if not m:
457
- continue
458
- lines.append(
459
- f"| {run['model']} | {domain} | {m['shown']:.0%} | {m['right']:.0%} | {m['avg_right_chars']:.1f} ch "
460
- f"| {m['multiword_shown']:.0%} | {m['multiword_right']:.0%} | {m['saved_with_tab']:.1%} | {m['saved_word_by_word']:.1%} |"
461
- )
462
- lines.append("\n| Model | Latency p50 | p95 |\n|---|---|---|")
463
- for run in runs:
464
- lines.append(f"| {run['model']} | {run['latency_ms']['p50']} ms | {run['latency_ms']['p95']} ms |")
465
- return "\n".join(lines)
466
-
467
-
468
- def main():
469
- parser = argparse.ArgumentParser()
470
- parser.add_argument("--model", help="Name for the metrics file")
471
- parser.add_argument("--onnx", help="A character-level GRU exported like enron-autocomplete")
472
- parser.add_argument("--hf", help="A Hugging Face causal LM to evaluate, e.g. HuggingFaceTB/SmolLM2-135M")
473
- parser.add_argument("--onnx-lm", help="Folder with a tinynext v2 ONNX export, config.json and tokenizer.json")
474
- parser.add_argument("--no-fim", action="store_true", help="With --onnx-lm: the model wasn't trained to fill in the middle")
475
- parser.add_argument("--max-pauses", type=int, default=1000, help="Per domain and scenario")
476
- parser.add_argument("--table", action="store_true", help="Print a comparison of every metrics/*.json")
477
- args = parser.parse_args()
478
-
479
- if args.table:
480
- print(table(sorted(METRICS.glob("*.json"))))
481
- return
482
- if args.onnx:
483
- model: Model = CharGRU(args.model, args.onnx)
484
- elif args.hf:
485
- model = hf_causal_lm(args.model, args.hf)
486
- elif args.onnx_lm:
487
- model = onnx_token_lm(args.model, args.onnx_lm, fim=not args.no_fim)
488
- else:
489
- parser.error("Pass --onnx, --hf or --table. train.py evaluates its own model through score().")
490
- all_pauses = pauses(load_eval_set(), args.max_pauses)
491
- print(f"{len(all_pauses)} pauses", flush=True)
492
- results = score(model, all_pauses)
493
- METRICS.mkdir(exist_ok=True)
494
- (METRICS / f"{args.model}.json").write_text(json.dumps(results, indent=1))
495
- print(table([METRICS / f"{args.model}.json"]))
496
-
497
-
498
- if __name__ == "__main__":
499
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
v2/experiments/tinynext-v2-3b/eval_set.json DELETED
The diff for this file is too large to render. See raw diff
 
v2/experiments/tinynext-v2-3b/metrics/tinynext-v2-3b.json DELETED
@@ -1,371 +0,0 @@
1
- {
2
- "model": "tinynext-v2-3b",
3
- "sees_after": true,
4
- "cutoffs": {
5
- "0.3": {
6
- "articles/typing": {
7
- "pauses": 1000,
8
- "shown": 0.204,
9
- "right": 0.5882,
10
- "avg_right_chars": 6.04,
11
- "multiword_shown": 0.086,
12
- "multiword_right": 0.5465,
13
- "saved_with_tab": 0.0604,
14
- "saved_word_by_word": 0.0679
15
- },
16
- "articles/editing": {
17
- "pauses": 1000,
18
- "shown": 0.152,
19
- "right": 0.6382,
20
- "avg_right_chars": 5.86,
21
- "multiword_shown": 0.062,
22
- "multiword_right": 0.629,
23
- "saved_with_tab": 0.0473,
24
- "saved_word_by_word": 0.0516
25
- },
26
- "messages/typing": {
27
- "pauses": 1000,
28
- "shown": 0.324,
29
- "right": 0.5463,
30
- "avg_right_chars": 7.8,
31
- "multiword_shown": 0.18,
32
- "multiword_right": 0.5333,
33
- "saved_with_tab": 0.115,
34
- "saved_word_by_word": 0.1404
35
- },
36
- "messages/editing": {
37
- "pauses": 1000,
38
- "shown": 0.317,
39
- "right": 0.5584,
40
- "avg_right_chars": 7.47,
41
- "multiword_shown": 0.173,
42
- "multiword_right": 0.5376,
43
- "saved_with_tab": 0.1102,
44
- "saved_word_by_word": 0.1328
45
- },
46
- "email/typing": {
47
- "pauses": 1000,
48
- "shown": 0.234,
49
- "right": 0.5598,
50
- "avg_right_chars": 6.03,
51
- "multiword_shown": 0.087,
52
- "multiword_right": 0.4023,
53
- "saved_with_tab": 0.0658,
54
- "saved_word_by_word": 0.0746
55
- },
56
- "email/editing": {
57
- "pauses": 1000,
58
- "shown": 0.213,
59
- "right": 0.5915,
60
- "avg_right_chars": 5.63,
61
- "multiword_shown": 0.078,
62
- "multiword_right": 0.4231,
63
- "saved_with_tab": 0.0591,
64
- "saved_word_by_word": 0.0653
65
- }
66
- },
67
- "0.4": {
68
- "articles/typing": {
69
- "pauses": 1000,
70
- "shown": 0.149,
71
- "right": 0.698,
72
- "avg_right_chars": 6.12,
73
- "multiword_shown": 0.057,
74
- "multiword_right": 0.614,
75
- "saved_with_tab": 0.0531,
76
- "saved_word_by_word": 0.0563
77
- },
78
- "articles/editing": {
79
- "pauses": 1000,
80
- "shown": 0.107,
81
- "right": 0.7103,
82
- "avg_right_chars": 5.72,
83
- "multiword_shown": 0.034,
84
- "multiword_right": 0.6765,
85
- "saved_with_tab": 0.0362,
86
- "saved_word_by_word": 0.0384
87
- },
88
- "messages/typing": {
89
- "pauses": 1000,
90
- "shown": 0.251,
91
- "right": 0.6255,
92
- "avg_right_chars": 7.7,
93
- "multiword_shown": 0.133,
94
- "multiword_right": 0.6015,
95
- "saved_with_tab": 0.1008,
96
- "saved_word_by_word": 0.1159
97
- },
98
- "messages/editing": {
99
- "pauses": 1000,
100
- "shown": 0.239,
101
- "right": 0.6569,
102
- "avg_right_chars": 7.29,
103
- "multiword_shown": 0.127,
104
- "multiword_right": 0.6378,
105
- "saved_with_tab": 0.0954,
106
- "saved_word_by_word": 0.1078
107
- },
108
- "email/typing": {
109
- "pauses": 1000,
110
- "shown": 0.162,
111
- "right": 0.679,
112
- "avg_right_chars": 5.84,
113
- "multiword_shown": 0.049,
114
- "multiword_right": 0.4898,
115
- "saved_with_tab": 0.0535,
116
- "saved_word_by_word": 0.0575
117
- },
118
- "email/editing": {
119
- "pauses": 1000,
120
- "shown": 0.165,
121
- "right": 0.6727,
122
- "avg_right_chars": 5.56,
123
- "multiword_shown": 0.055,
124
- "multiword_right": 0.5818,
125
- "saved_with_tab": 0.0514,
126
- "saved_word_by_word": 0.0545
127
- }
128
- },
129
- "0.5": {
130
- "articles/typing": {
131
- "pauses": 1000,
132
- "shown": 0.101,
133
- "right": 0.7822,
134
- "avg_right_chars": 5.86,
135
- "multiword_shown": 0.035,
136
- "multiword_right": 0.7143,
137
- "saved_with_tab": 0.0386,
138
- "saved_word_by_word": 0.04
139
- },
140
- "articles/editing": {
141
- "pauses": 1000,
142
- "shown": 0.08,
143
- "right": 0.825,
144
- "avg_right_chars": 5.61,
145
- "multiword_shown": 0.024,
146
- "multiword_right": 0.8333,
147
- "saved_with_tab": 0.0308,
148
- "saved_word_by_word": 0.0317
149
- },
150
- "messages/typing": {
151
- "pauses": 1000,
152
- "shown": 0.193,
153
- "right": 0.7461,
154
- "avg_right_chars": 7.31,
155
- "multiword_shown": 0.094,
156
- "multiword_right": 0.7021,
157
- "saved_with_tab": 0.0877,
158
- "saved_word_by_word": 0.0969
159
- },
160
- "messages/editing": {
161
- "pauses": 1000,
162
- "shown": 0.175,
163
- "right": 0.76,
164
- "avg_right_chars": 6.87,
165
- "multiword_shown": 0.091,
166
- "multiword_right": 0.7033,
167
- "saved_with_tab": 0.0762,
168
- "saved_word_by_word": 0.0843
169
- },
170
- "email/typing": {
171
- "pauses": 1000,
172
- "shown": 0.112,
173
- "right": 0.7768,
174
- "avg_right_chars": 5.54,
175
- "multiword_shown": 0.035,
176
- "multiword_right": 0.5143,
177
- "saved_with_tab": 0.0402,
178
- "saved_word_by_word": 0.0427
179
- },
180
- "email/editing": {
181
- "pauses": 1000,
182
- "shown": 0.118,
183
- "right": 0.7797,
184
- "avg_right_chars": 5.5,
185
- "multiword_shown": 0.031,
186
- "multiword_right": 0.7097,
187
- "saved_with_tab": 0.0422,
188
- "saved_word_by_word": 0.0435
189
- }
190
- },
191
- "0.6": {
192
- "articles/typing": {
193
- "pauses": 1000,
194
- "shown": 0.076,
195
- "right": 0.8026,
196
- "avg_right_chars": 5.77,
197
- "multiword_shown": 0.026,
198
- "multiword_right": 0.7692,
199
- "saved_with_tab": 0.0293,
200
- "saved_word_by_word": 0.0303
201
- },
202
- "articles/editing": {
203
- "pauses": 1000,
204
- "shown": 0.059,
205
- "right": 0.8983,
206
- "avg_right_chars": 5.45,
207
- "multiword_shown": 0.014,
208
- "multiword_right": 0.7857,
209
- "saved_with_tab": 0.0241,
210
- "saved_word_by_word": 0.0244
211
- },
212
- "messages/typing": {
213
- "pauses": 1000,
214
- "shown": 0.152,
215
- "right": 0.8421,
216
- "avg_right_chars": 7.22,
217
- "multiword_shown": 0.068,
218
- "multiword_right": 0.8382,
219
- "saved_with_tab": 0.077,
220
- "saved_word_by_word": 0.0795
221
- },
222
- "messages/editing": {
223
- "pauses": 1000,
224
- "shown": 0.141,
225
- "right": 0.8369,
226
- "avg_right_chars": 6.39,
227
- "multiword_shown": 0.065,
228
- "multiword_right": 0.7538,
229
- "saved_with_tab": 0.0628,
230
- "saved_word_by_word": 0.0669
231
- },
232
- "email/typing": {
233
- "pauses": 1000,
234
- "shown": 0.086,
235
- "right": 0.8256,
236
- "avg_right_chars": 5.23,
237
- "multiword_shown": 0.015,
238
- "multiword_right": 0.5333,
239
- "saved_with_tab": 0.0309,
240
- "saved_word_by_word": 0.0322
241
- },
242
- "email/editing": {
243
- "pauses": 1000,
244
- "shown": 0.084,
245
- "right": 0.8452,
246
- "avg_right_chars": 5.34,
247
- "multiword_shown": 0.016,
248
- "multiword_right": 0.75,
249
- "saved_with_tab": 0.0316,
250
- "saved_word_by_word": 0.0319
251
- }
252
- },
253
- "0.7": {
254
- "articles/typing": {
255
- "pauses": 1000,
256
- "shown": 0.052,
257
- "right": 0.8654,
258
- "avg_right_chars": 6.09,
259
- "multiword_shown": 0.017,
260
- "multiword_right": 0.8235,
261
- "saved_with_tab": 0.0228,
262
- "saved_word_by_word": 0.0232
263
- },
264
- "articles/editing": {
265
- "pauses": 1000,
266
- "shown": 0.043,
267
- "right": 0.9302,
268
- "avg_right_chars": 5.25,
269
- "multiword_shown": 0.01,
270
- "multiword_right": 0.9,
271
- "saved_with_tab": 0.0175,
272
- "saved_word_by_word": 0.0177
273
- },
274
- "messages/typing": {
275
- "pauses": 1000,
276
- "shown": 0.117,
277
- "right": 0.8718,
278
- "avg_right_chars": 6.64,
279
- "multiword_shown": 0.045,
280
- "multiword_right": 0.8889,
281
- "saved_with_tab": 0.0564,
282
- "saved_word_by_word": 0.0579
283
- },
284
- "messages/editing": {
285
- "pauses": 1000,
286
- "shown": 0.105,
287
- "right": 0.8857,
288
- "avg_right_chars": 5.98,
289
- "multiword_shown": 0.038,
290
- "multiword_right": 0.8684,
291
- "saved_with_tab": 0.0463,
292
- "saved_word_by_word": 0.0476
293
- },
294
- "email/typing": {
295
- "pauses": 1000,
296
- "shown": 0.058,
297
- "right": 0.8103,
298
- "avg_right_chars": 5.19,
299
- "multiword_shown": 0.007,
300
- "multiword_right": 0.4286,
301
- "saved_with_tab": 0.0203,
302
- "saved_word_by_word": 0.0206
303
- },
304
- "email/editing": {
305
- "pauses": 1000,
306
- "shown": 0.066,
307
- "right": 0.8788,
308
- "avg_right_chars": 4.98,
309
- "multiword_shown": 0.008,
310
- "multiword_right": 0.5,
311
- "saved_with_tab": 0.0241,
312
- "saved_word_by_word": 0.0244
313
- }
314
- }
315
- },
316
- "examples": [
317
- {
318
- "domain": "articles",
319
- "scenario": "editing",
320
- "before": " the Spaghetti Western film genre) and Hate Boat, were publi",
321
- "suggestion": "shed",
322
- "truth": "shed by Comico C",
323
- "right": true
324
- },
325
- {
326
- "domain": "articles",
327
- "scenario": "editing",
328
- "before": "rked on a tour of Canada with I Hate Sally, Hiretsukan, GFK,",
329
- "suggestion": " and",
330
- "truth": " and DeadPoets a",
331
- "right": true
332
- },
333
- {
334
- "domain": "messages",
335
- "scenario": "typing",
336
- "before": " be completely benevolent and will always act in our best in",
337
- "suggestion": "terests.",
338
- "truth": "terests, ensuring th",
339
- "right": false
340
- },
341
- {
342
- "domain": "messages",
343
- "scenario": "typing",
344
- "before": "onsidered new. Those decisions make the graphs as neat as po",
345
- "suggestion": "ssible.",
346
- "truth": "ssible, and it is t",
347
- "right": false
348
- },
349
- {
350
- "domain": "messages",
351
- "scenario": "editing",
352
- "before": "e optimal level of production and pricing for businesses. L'",
353
- "suggestion": "Hpital's Rule can",
354
- "truth": "Hpital's Rule can help analyz",
355
- "right": true
356
- },
357
- {
358
- "domain": "email",
359
- "scenario": "editing",
360
- "before": "ured products and marketing of electricity for the United St",
361
- "suggestion": "ates",
362
- "truth": "ates ? Actively ",
363
- "right": true
364
- }
365
- ],
366
- "latency_ms": {
367
- "p50": 15.38,
368
- "p95": 42.67,
369
- "note": "Measured in this eval process, not in a browser."
370
- }
371
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
v2/experiments/tinynext-v2-3b/model.onnx DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:d720a8d92844daca8da7820debd0be2c22d064b33de16ccbcfa69adf79307f13
3
- size 60813561
 
 
 
 
v2/experiments/tinynext-v2-3b/model.safetensors DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:0ffd7eaaee87262d76e9b401514eee2449e72b7aae899579b227c114d4a37366
3
- size 50161328
 
 
 
 
v2/experiments/tinynext-v2-3b/model_int8.onnx DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:34f405276119c07d523af9a5e43354ab50acbaa0e2be167166320401a3d35a2c
3
- size 15638872
 
 
 
 
v2/experiments/tinynext-v2-3b/report.json DELETED
@@ -1,2390 +0,0 @@
1
- {
2
- "args": {
3
- "vocab": 8192,
4
- "dim": 320,
5
- "layers": 8,
6
- "heads": 5,
7
- "ffn": 864,
8
- "seq": 512,
9
- "tokens": 3000000000.0,
10
- "val_tokens": 4000000.0,
11
- "epochs": 1.0,
12
- "batch": 512,
13
- "lr": 0.003,
14
- "fim_rate": 0.5,
15
- "mix": "fineweb=0.6,smoltalk=0.3,enron=0.1",
16
- "fineweb_files": 4,
17
- "smoltalk_files": 9,
18
- "tokenizer_docs": 200000,
19
- "eval_pauses": 1000,
20
- "log_every": 50,
21
- "repo": "cfahlgren1/tinynext",
22
- "folder": "v2/experiments/tinynext-v2-3b",
23
- "eval_folder": "v2",
24
- "name": "tinynext-v2-3b",
25
- "trackio_space": "cfahlgren1/tinynext-trackio",
26
- "stage": "train",
27
- "data_repo": "cfahlgren1/tinynext-data",
28
- "smoke": false,
29
- "no_push": false
30
- },
31
- "parameters": 12539200,
32
- "data": {
33
- "fineweb": {
34
- "docs": 2122073,
35
- "train_tokens": 1800000000
36
- },
37
- "smoltalk": {
38
- "docs": 1041801,
39
- "train_tokens": 900000000
40
- },
41
- "enron": {
42
- "docs": 268120,
43
- "train_tokens": 300000000
44
- }
45
- },
46
- "data_minutes": 0.2,
47
- "train_minutes": 55.8,
48
- "history": [
49
- {
50
- "step": 0,
51
- "train_loss": 9.0702,
52
- "lr": 1.3e-05,
53
- "tokens_per_second": 12800,
54
- "minutes": 0.34,
55
- "mfu_percent": 0.3,
56
- "gpu_util_percent": 98,
57
- "gpu_memory_gb": 76.5,
58
- "val_loss": 9.0663
59
- },
60
- {
61
- "step": 50,
62
- "train_loss": 7.215,
63
- "lr": 0.000671,
64
- "tokens_per_second": 930958,
65
- "minutes": 0.62,
66
- "mfu_percent": 22.4,
67
- "gpu_util_percent": 100,
68
- "gpu_memory_gb": 85.1
69
- },
70
- {
71
- "step": 100,
72
- "train_loss": 6.1306,
73
- "lr": 0.001329,
74
- "tokens_per_second": 925320,
75
- "minutes": 0.86,
76
- "mfu_percent": 22.3,
77
- "gpu_util_percent": 100,
78
- "gpu_memory_gb": 85.1
79
- },
80
- {
81
- "step": 150,
82
- "train_loss": 5.5618,
83
- "lr": 0.001986,
84
- "tokens_per_second": 924266,
85
- "minutes": 1.1,
86
- "mfu_percent": 22.3,
87
- "gpu_util_percent": 100,
88
- "gpu_memory_gb": 85.1
89
- },
90
- {
91
- "step": 200,
92
- "train_loss": 5.1433,
93
- "lr": 0.002643,
94
- "tokens_per_second": 923447,
95
- "minutes": 1.33,
96
- "mfu_percent": 22.3,
97
- "gpu_util_percent": 100,
98
- "gpu_memory_gb": 85.1
99
- },
100
- {
101
- "step": 250,
102
- "train_loss": 4.6259,
103
- "lr": 0.002997,
104
- "tokens_per_second": 923503,
105
- "minutes": 1.57,
106
- "mfu_percent": 22.3,
107
- "gpu_util_percent": 100,
108
- "gpu_memory_gb": 85.1
109
- },
110
- {
111
- "step": 300,
112
- "train_loss": 4.2702,
113
- "lr": 0.002995,
114
- "tokens_per_second": 923163,
115
- "minutes": 1.81,
116
- "mfu_percent": 22.3,
117
- "gpu_util_percent": 100,
118
- "gpu_memory_gb": 85.1
119
- },
120
- {
121
- "step": 350,
122
- "train_loss": 4.0271,
123
- "lr": 0.002994,
124
- "tokens_per_second": 922754,
125
- "minutes": 2.04,
126
- "mfu_percent": 22.3,
127
- "gpu_util_percent": 100,
128
- "gpu_memory_gb": 85.1
129
- },
130
- {
131
- "step": 400,
132
- "train_loss": 3.8697,
133
- "lr": 0.002992,
134
- "tokens_per_second": 922255,
135
- "minutes": 2.28,
136
- "mfu_percent": 22.2,
137
- "gpu_util_percent": 100,
138
- "gpu_memory_gb": 85.1
139
- },
140
- {
141
- "step": 450,
142
- "train_loss": 3.6918,
143
- "lr": 0.00299,
144
- "tokens_per_second": 921900,
145
- "minutes": 2.52,
146
- "mfu_percent": 22.2,
147
- "gpu_util_percent": 100,
148
- "gpu_memory_gb": 85.1
149
- },
150
- {
151
- "step": 500,
152
- "train_loss": 3.6502,
153
- "lr": 0.002987,
154
- "tokens_per_second": 921603,
155
- "minutes": 2.75,
156
- "mfu_percent": 22.2,
157
- "gpu_util_percent": 100,
158
- "gpu_memory_gb": 85.1,
159
- "val_loss": 3.6813
160
- },
161
- {
162
- "step": 550,
163
- "train_loss": 3.6069,
164
- "lr": 0.002985,
165
- "tokens_per_second": 922139,
166
- "minutes": 3.04,
167
- "mfu_percent": 22.2,
168
- "gpu_util_percent": 100,
169
- "gpu_memory_gb": 85.1
170
- },
171
- {
172
- "step": 600,
173
- "train_loss": 3.6009,
174
- "lr": 0.002982,
175
- "tokens_per_second": 921841,
176
- "minutes": 3.28,
177
- "mfu_percent": 22.2,
178
- "gpu_util_percent": 100,
179
- "gpu_memory_gb": 85.1
180
- },
181
- {
182
- "step": 650,
183
- "train_loss": 3.5049,
184
- "lr": 0.002978,
185
- "tokens_per_second": 921515,
186
- "minutes": 3.51,
187
- "mfu_percent": 22.2,
188
- "gpu_util_percent": 100,
189
- "gpu_memory_gb": 85.1
190
- },
191
- {
192
- "step": 700,
193
- "train_loss": 3.4728,
194
- "lr": 0.002975,
195
- "tokens_per_second": 921918,
196
- "minutes": 3.75,
197
- "mfu_percent": 22.2,
198
- "gpu_util_percent": 100,
199
- "gpu_memory_gb": 85.1
200
- },
201
- {
202
- "step": 750,
203
- "train_loss": 3.4877,
204
- "lr": 0.002971,
205
- "tokens_per_second": 921386,
206
- "minutes": 3.99,
207
- "mfu_percent": 22.2,
208
- "gpu_util_percent": 100,
209
- "gpu_memory_gb": 85.1
210
- },
211
- {
212
- "step": 800,
213
- "train_loss": 3.4264,
214
- "lr": 0.002967,
215
- "tokens_per_second": 921002,
216
- "minutes": 4.22,
217
- "mfu_percent": 22.2,
218
- "gpu_util_percent": 100,
219
- "gpu_memory_gb": 85.1
220
- },
221
- {
222
- "step": 850,
223
- "train_loss": 3.3612,
224
- "lr": 0.002963,
225
- "tokens_per_second": 920889,
226
- "minutes": 4.46,
227
- "mfu_percent": 22.2,
228
- "gpu_util_percent": 100,
229
- "gpu_memory_gb": 85.1
230
- },
231
- {
232
- "step": 900,
233
- "train_loss": 3.3516,
234
- "lr": 0.002959,
235
- "tokens_per_second": 920832,
236
- "minutes": 4.7,
237
- "mfu_percent": 22.2,
238
- "gpu_util_percent": 100,
239
- "gpu_memory_gb": 85.1
240
- },
241
- {
242
- "step": 950,
243
- "train_loss": 3.3742,
244
- "lr": 0.002954,
245
- "tokens_per_second": 920862,
246
- "minutes": 4.94,
247
- "mfu_percent": 22.2,
248
- "gpu_util_percent": 100,
249
- "gpu_memory_gb": 85.1
250
- },
251
- {
252
- "step": 1000,
253
- "train_loss": 3.3632,
254
- "lr": 0.002949,
255
- "tokens_per_second": 920554,
256
- "minutes": 5.17,
257
- "mfu_percent": 22.2,
258
- "gpu_util_percent": 100,
259
- "gpu_memory_gb": 85.1,
260
- "val_loss": 3.3796
261
- },
262
- {
263
- "step": 1050,
264
- "train_loss": 3.3061,
265
- "lr": 0.002944,
266
- "tokens_per_second": 920467,
267
- "minutes": 5.46,
268
- "mfu_percent": 22.2,
269
- "gpu_util_percent": 100,
270
- "gpu_memory_gb": 85.1
271
- },
272
- {
273
- "step": 1100,
274
- "train_loss": 3.3351,
275
- "lr": 0.002939,
276
- "tokens_per_second": 921248,
277
- "minutes": 5.69,
278
- "mfu_percent": 22.2,
279
- "gpu_util_percent": 100,
280
- "gpu_memory_gb": 85.1
281
- },
282
- {
283
- "step": 1150,
284
- "train_loss": 3.3238,
285
- "lr": 0.002933,
286
- "tokens_per_second": 921674,
287
- "minutes": 5.93,
288
- "mfu_percent": 22.2,
289
- "gpu_util_percent": 100,
290
- "gpu_memory_gb": 85.1
291
- },
292
- {
293
- "step": 1200,
294
- "train_loss": 3.3208,
295
- "lr": 0.002927,
296
- "tokens_per_second": 921693,
297
- "minutes": 6.17,
298
- "mfu_percent": 22.2,
299
- "gpu_util_percent": 100,
300
- "gpu_memory_gb": 85.1
301
- },
302
- {
303
- "step": 1250,
304
- "train_loss": 3.286,
305
- "lr": 0.002921,
306
- "tokens_per_second": 921893,
307
- "minutes": 6.41,
308
- "mfu_percent": 22.2,
309
- "gpu_util_percent": 100,
310
- "gpu_memory_gb": 85.1
311
- },
312
- {
313
- "step": 1300,
314
- "train_loss": 3.2941,
315
- "lr": 0.002914,
316
- "tokens_per_second": 922496,
317
- "minutes": 6.64,
318
- "mfu_percent": 22.2,
319
- "gpu_util_percent": 100,
320
- "gpu_memory_gb": 85.1
321
- },
322
- {
323
- "step": 1350,
324
- "train_loss": 3.2475,
325
- "lr": 0.002908,
326
- "tokens_per_second": 922535,
327
- "minutes": 6.88,
328
- "mfu_percent": 22.2,
329
- "gpu_util_percent": 100,
330
- "gpu_memory_gb": 85.1
331
- },
332
- {
333
- "step": 1400,
334
- "train_loss": 3.21,
335
- "lr": 0.002901,
336
- "tokens_per_second": 921917,
337
- "minutes": 7.12,
338
- "mfu_percent": 22.2,
339
- "gpu_util_percent": 100,
340
- "gpu_memory_gb": 85.1
341
- },
342
- {
343
- "step": 1450,
344
- "train_loss": 3.2507,
345
- "lr": 0.002894,
346
- "tokens_per_second": 921722,
347
- "minutes": 7.35,
348
- "mfu_percent": 22.2,
349
- "gpu_util_percent": 100,
350
- "gpu_memory_gb": 85.1
351
- },
352
- {
353
- "step": 1500,
354
- "train_loss": 3.2548,
355
- "lr": 0.002887,
356
- "tokens_per_second": 920926,
357
- "minutes": 7.59,
358
- "mfu_percent": 22.2,
359
- "gpu_util_percent": 100,
360
- "gpu_memory_gb": 85.1,
361
- "val_loss": 3.2689
362
- },
363
- {
364
- "step": 1550,
365
- "train_loss": 3.2187,
366
- "lr": 0.002879,
367
- "tokens_per_second": 920076,
368
- "minutes": 7.87,
369
- "mfu_percent": 22.2,
370
- "gpu_util_percent": 100,
371
- "gpu_memory_gb": 85.1
372
- },
373
- {
374
- "step": 1600,
375
- "train_loss": 3.2435,
376
- "lr": 0.002871,
377
- "tokens_per_second": 920390,
378
- "minutes": 8.11,
379
- "mfu_percent": 22.2,
380
- "gpu_util_percent": 100,
381
- "gpu_memory_gb": 85.1
382
- },
383
- {
384
- "step": 1650,
385
- "train_loss": 3.1958,
386
- "lr": 0.002863,
387
- "tokens_per_second": 920901,
388
- "minutes": 8.35,
389
- "mfu_percent": 22.2,
390
- "gpu_util_percent": 100,
391
- "gpu_memory_gb": 85.1
392
- },
393
- {
394
- "step": 1700,
395
- "train_loss": 3.1797,
396
- "lr": 0.002855,
397
- "tokens_per_second": 920930,
398
- "minutes": 8.59,
399
- "mfu_percent": 22.2,
400
- "gpu_util_percent": 100,
401
- "gpu_memory_gb": 85.1
402
- },
403
- {
404
- "step": 1750,
405
- "train_loss": 3.2016,
406
- "lr": 0.002846,
407
- "tokens_per_second": 921134,
408
- "minutes": 8.82,
409
- "mfu_percent": 22.2,
410
- "gpu_util_percent": 100,
411
- "gpu_memory_gb": 85.1
412
- },
413
- {
414
- "step": 1800,
415
- "train_loss": 3.1736,
416
- "lr": 0.002838,
417
- "tokens_per_second": 922208,
418
- "minutes": 9.06,
419
- "mfu_percent": 22.2,
420
- "gpu_util_percent": 100,
421
- "gpu_memory_gb": 85.1
422
- },
423
- {
424
- "step": 1850,
425
- "train_loss": 3.1912,
426
- "lr": 0.002829,
427
- "tokens_per_second": 922453,
428
- "minutes": 9.3,
429
- "mfu_percent": 22.2,
430
- "gpu_util_percent": 100,
431
- "gpu_memory_gb": 85.1
432
- },
433
- {
434
- "step": 1900,
435
- "train_loss": 3.1827,
436
- "lr": 0.00282,
437
- "tokens_per_second": 922660,
438
- "minutes": 9.53,
439
- "mfu_percent": 22.2,
440
- "gpu_util_percent": 100,
441
- "gpu_memory_gb": 85.1
442
- },
443
- {
444
- "step": 1950,
445
- "train_loss": 3.202,
446
- "lr": 0.00281,
447
- "tokens_per_second": 922623,
448
- "minutes": 9.77,
449
- "mfu_percent": 22.2,
450
- "gpu_util_percent": 100,
451
- "gpu_memory_gb": 85.1
452
- },
453
- {
454
- "step": 2000,
455
- "train_loss": 3.2288,
456
- "lr": 0.002801,
457
- "tokens_per_second": 922474,
458
- "minutes": 10.01,
459
- "mfu_percent": 22.2,
460
- "gpu_util_percent": 100,
461
- "gpu_memory_gb": 85.1,
462
- "val_loss": 3.208
463
- },
464
- {
465
- "step": 2050,
466
- "train_loss": 3.1591,
467
- "lr": 0.002791,
468
- "tokens_per_second": 922197,
469
- "minutes": 10.29,
470
- "mfu_percent": 22.2,
471
- "gpu_util_percent": 100,
472
- "gpu_memory_gb": 85.1
473
- },
474
- {
475
- "step": 2100,
476
- "train_loss": 3.2074,
477
- "lr": 0.002781,
478
- "tokens_per_second": 922026,
479
- "minutes": 10.53,
480
- "mfu_percent": 22.2,
481
- "gpu_util_percent": 100,
482
- "gpu_memory_gb": 85.1
483
- },
484
- {
485
- "step": 2150,
486
- "train_loss": 3.1784,
487
- "lr": 0.002771,
488
- "tokens_per_second": 922145,
489
- "minutes": 10.77,
490
- "mfu_percent": 22.2,
491
- "gpu_util_percent": 100,
492
- "gpu_memory_gb": 85.1
493
- },
494
- {
495
- "step": 2200,
496
- "train_loss": 3.1416,
497
- "lr": 0.00276,
498
- "tokens_per_second": 921690,
499
- "minutes": 11.0,
500
- "mfu_percent": 22.2,
501
- "gpu_util_percent": 100,
502
- "gpu_memory_gb": 85.1
503
- },
504
- {
505
- "step": 2250,
506
- "train_loss": 3.1531,
507
- "lr": 0.002749,
508
- "tokens_per_second": 921458,
509
- "minutes": 11.24,
510
- "mfu_percent": 22.2,
511
- "gpu_util_percent": 100,
512
- "gpu_memory_gb": 85.1
513
- },
514
- {
515
- "step": 2300,
516
- "train_loss": 3.1148,
517
- "lr": 0.002738,
518
- "tokens_per_second": 920727,
519
- "minutes": 11.48,
520
- "mfu_percent": 22.2,
521
- "gpu_util_percent": 100,
522
- "gpu_memory_gb": 85.1
523
- },
524
- {
525
- "step": 2350,
526
- "train_loss": 3.1005,
527
- "lr": 0.002727,
528
- "tokens_per_second": 921746,
529
- "minutes": 11.71,
530
- "mfu_percent": 22.2,
531
- "gpu_util_percent": 100,
532
- "gpu_memory_gb": 85.1
533
- },
534
- {
535
- "step": 2400,
536
- "train_loss": 3.2112,
537
- "lr": 0.002716,
538
- "tokens_per_second": 922555,
539
- "minutes": 11.95,
540
- "mfu_percent": 22.2,
541
- "gpu_util_percent": 100,
542
- "gpu_memory_gb": 85.1
543
- },
544
- {
545
- "step": 2450,
546
- "train_loss": 3.1437,
547
- "lr": 0.002705,
548
- "tokens_per_second": 922219,
549
- "minutes": 12.19,
550
- "mfu_percent": 22.2,
551
- "gpu_util_percent": 100,
552
- "gpu_memory_gb": 85.1
553
- },
554
- {
555
- "step": 2500,
556
- "train_loss": 3.114,
557
- "lr": 0.002693,
558
- "tokens_per_second": 922404,
559
- "minutes": 12.42,
560
- "mfu_percent": 22.2,
561
- "gpu_util_percent": 100,
562
- "gpu_memory_gb": 85.1,
563
- "val_loss": 3.1664
564
- },
565
- {
566
- "step": 2550,
567
- "train_loss": 3.1538,
568
- "lr": 0.002681,
569
- "tokens_per_second": 922093,
570
- "minutes": 12.71,
571
- "mfu_percent": 22.2,
572
- "gpu_util_percent": 100,
573
- "gpu_memory_gb": 85.1
574
- },
575
- {
576
- "step": 2600,
577
- "train_loss": 3.1874,
578
- "lr": 0.002669,
579
- "tokens_per_second": 921696,
580
- "minutes": 12.95,
581
- "mfu_percent": 22.2,
582
- "gpu_util_percent": 100,
583
- "gpu_memory_gb": 85.1
584
- },
585
- {
586
- "step": 2650,
587
- "train_loss": 3.1451,
588
- "lr": 0.002657,
589
- "tokens_per_second": 920726,
590
- "minutes": 13.18,
591
- "mfu_percent": 22.2,
592
- "gpu_util_percent": 100,
593
- "gpu_memory_gb": 85.1
594
- },
595
- {
596
- "step": 2700,
597
- "train_loss": 3.1138,
598
- "lr": 0.002644,
599
- "tokens_per_second": 920915,
600
- "minutes": 13.42,
601
- "mfu_percent": 22.2,
602
- "gpu_util_percent": 100,
603
- "gpu_memory_gb": 85.1
604
- },
605
- {
606
- "step": 2750,
607
- "train_loss": 3.1194,
608
- "lr": 0.002632,
609
- "tokens_per_second": 920910,
610
- "minutes": 13.66,
611
- "mfu_percent": 22.2,
612
- "gpu_util_percent": 100,
613
- "gpu_memory_gb": 85.1
614
- },
615
- {
616
- "step": 2800,
617
- "train_loss": 3.0835,
618
- "lr": 0.002619,
619
- "tokens_per_second": 920819,
620
- "minutes": 13.89,
621
- "mfu_percent": 22.2,
622
- "gpu_util_percent": 100,
623
- "gpu_memory_gb": 85.1
624
- },
625
- {
626
- "step": 2850,
627
- "train_loss": 3.1095,
628
- "lr": 0.002606,
629
- "tokens_per_second": 920420,
630
- "minutes": 14.13,
631
- "mfu_percent": 22.2,
632
- "gpu_util_percent": 100,
633
- "gpu_memory_gb": 85.1
634
- },
635
- {
636
- "step": 2900,
637
- "train_loss": 3.1067,
638
- "lr": 0.002593,
639
- "tokens_per_second": 920261,
640
- "minutes": 14.37,
641
- "mfu_percent": 22.2,
642
- "gpu_util_percent": 100,
643
- "gpu_memory_gb": 85.1
644
- },
645
- {
646
- "step": 2950,
647
- "train_loss": 3.0488,
648
- "lr": 0.002579,
649
- "tokens_per_second": 921100,
650
- "minutes": 14.61,
651
- "mfu_percent": 22.2,
652
- "gpu_util_percent": 100,
653
- "gpu_memory_gb": 85.1
654
- },
655
- {
656
- "step": 3000,
657
- "train_loss": 3.1089,
658
- "lr": 0.002566,
659
- "tokens_per_second": 921915,
660
- "minutes": 14.84,
661
- "mfu_percent": 22.2,
662
- "gpu_util_percent": 100,
663
- "gpu_memory_gb": 85.1,
664
- "val_loss": 3.1334
665
- },
666
- {
667
- "step": 3050,
668
- "train_loss": 3.0736,
669
- "lr": 0.002552,
670
- "tokens_per_second": 922085,
671
- "minutes": 15.13,
672
- "mfu_percent": 22.2,
673
- "gpu_util_percent": 100,
674
- "gpu_memory_gb": 85.1
675
- },
676
- {
677
- "step": 3100,
678
- "train_loss": 3.0915,
679
- "lr": 0.002538,
680
- "tokens_per_second": 921538,
681
- "minutes": 15.36,
682
- "mfu_percent": 22.2,
683
- "gpu_util_percent": 100,
684
- "gpu_memory_gb": 85.1
685
- },
686
- {
687
- "step": 3150,
688
- "train_loss": 3.0751,
689
- "lr": 0.002524,
690
- "tokens_per_second": 921498,
691
- "minutes": 15.6,
692
- "mfu_percent": 22.2,
693
- "gpu_util_percent": 100,
694
- "gpu_memory_gb": 85.1
695
- },
696
- {
697
- "step": 3200,
698
- "train_loss": 3.1093,
699
- "lr": 0.00251,
700
- "tokens_per_second": 920747,
701
- "minutes": 15.84,
702
- "mfu_percent": 22.2,
703
- "gpu_util_percent": 100,
704
- "gpu_memory_gb": 85.1
705
- },
706
- {
707
- "step": 3250,
708
- "train_loss": 3.1425,
709
- "lr": 0.002495,
710
- "tokens_per_second": 920376,
711
- "minutes": 16.08,
712
- "mfu_percent": 22.2,
713
- "gpu_util_percent": 100,
714
- "gpu_memory_gb": 85.1
715
- },
716
- {
717
- "step": 3300,
718
- "train_loss": 3.0762,
719
- "lr": 0.002481,
720
- "tokens_per_second": 920083,
721
- "minutes": 16.31,
722
- "mfu_percent": 22.2,
723
- "gpu_util_percent": 100,
724
- "gpu_memory_gb": 85.1
725
- },
726
- {
727
- "step": 3350,
728
- "train_loss": 3.1273,
729
- "lr": 0.002466,
730
- "tokens_per_second": 919889,
731
- "minutes": 16.55,
732
- "mfu_percent": 22.2,
733
- "gpu_util_percent": 100,
734
- "gpu_memory_gb": 85.1
735
- },
736
- {
737
- "step": 3400,
738
- "train_loss": 3.1,
739
- "lr": 0.002451,
740
- "tokens_per_second": 921166,
741
- "minutes": 16.79,
742
- "mfu_percent": 22.2,
743
- "gpu_util_percent": 100,
744
- "gpu_memory_gb": 85.1
745
- },
746
- {
747
- "step": 3450,
748
- "train_loss": 3.1428,
749
- "lr": 0.002436,
750
- "tokens_per_second": 921093,
751
- "minutes": 17.02,
752
- "mfu_percent": 22.2,
753
- "gpu_util_percent": 100,
754
- "gpu_memory_gb": 85.1
755
- },
756
- {
757
- "step": 3500,
758
- "train_loss": 3.0703,
759
- "lr": 0.002421,
760
- "tokens_per_second": 920938,
761
- "minutes": 17.26,
762
- "mfu_percent": 22.2,
763
- "gpu_util_percent": 100,
764
- "gpu_memory_gb": 85.1,
765
- "val_loss": 3.1114
766
- },
767
- {
768
- "step": 3550,
769
- "train_loss": 3.1048,
770
- "lr": 0.002406,
771
- "tokens_per_second": 921446,
772
- "minutes": 17.55,
773
- "mfu_percent": 22.2,
774
- "gpu_util_percent": 100,
775
- "gpu_memory_gb": 85.1
776
- },
777
- {
778
- "step": 3600,
779
- "train_loss": 3.0576,
780
- "lr": 0.00239,
781
- "tokens_per_second": 921917,
782
- "minutes": 17.78,
783
- "mfu_percent": 22.2,
784
- "gpu_util_percent": 100,
785
- "gpu_memory_gb": 85.1
786
- },
787
- {
788
- "step": 3650,
789
- "train_loss": 3.0815,
790
- "lr": 0.002375,
791
- "tokens_per_second": 921369,
792
- "minutes": 18.02,
793
- "mfu_percent": 22.2,
794
- "gpu_util_percent": 100,
795
- "gpu_memory_gb": 85.1
796
- },
797
- {
798
- "step": 3700,
799
- "train_loss": 3.102,
800
- "lr": 0.002359,
801
- "tokens_per_second": 921425,
802
- "minutes": 18.26,
803
- "mfu_percent": 22.2,
804
- "gpu_util_percent": 100,
805
- "gpu_memory_gb": 85.1
806
- },
807
- {
808
- "step": 3750,
809
- "train_loss": 3.0362,
810
- "lr": 0.002343,
811
- "tokens_per_second": 921350,
812
- "minutes": 18.49,
813
- "mfu_percent": 22.2,
814
- "gpu_util_percent": 100,
815
- "gpu_memory_gb": 85.1
816
- },
817
- {
818
- "step": 3800,
819
- "train_loss": 3.0936,
820
- "lr": 0.002327,
821
- "tokens_per_second": 920994,
822
- "minutes": 18.73,
823
- "mfu_percent": 22.2,
824
- "gpu_util_percent": 100,
825
- "gpu_memory_gb": 85.1
826
- },
827
- {
828
- "step": 3850,
829
- "train_loss": 3.0723,
830
- "lr": 0.002311,
831
- "tokens_per_second": 920745,
832
- "minutes": 18.97,
833
- "mfu_percent": 22.2,
834
- "gpu_util_percent": 100,
835
- "gpu_memory_gb": 85.1
836
- },
837
- {
838
- "step": 3900,
839
- "train_loss": 3.0621,
840
- "lr": 0.002295,
841
- "tokens_per_second": 920434,
842
- "minutes": 19.21,
843
- "mfu_percent": 22.2,
844
- "gpu_util_percent": 100,
845
- "gpu_memory_gb": 85.1
846
- },
847
- {
848
- "step": 3950,
849
- "train_loss": 3.1088,
850
- "lr": 0.002278,
851
- "tokens_per_second": 919905,
852
- "minutes": 19.44,
853
- "mfu_percent": 22.2,
854
- "gpu_util_percent": 100,
855
- "gpu_memory_gb": 85.1
856
- },
857
- {
858
- "step": 4000,
859
- "train_loss": 3.019,
860
- "lr": 0.002262,
861
- "tokens_per_second": 919709,
862
- "minutes": 19.68,
863
- "mfu_percent": 22.2,
864
- "gpu_util_percent": 100,
865
- "gpu_memory_gb": 85.1,
866
- "val_loss": 3.0871
867
- },
868
- {
869
- "step": 4050,
870
- "train_loss": 3.0537,
871
- "lr": 0.002245,
872
- "tokens_per_second": 919817,
873
- "minutes": 19.97,
874
- "mfu_percent": 22.2,
875
- "gpu_util_percent": 100,
876
- "gpu_memory_gb": 85.1
877
- },
878
- {
879
- "step": 4100,
880
- "train_loss": 3.0237,
881
- "lr": 0.002228,
882
- "tokens_per_second": 919826,
883
- "minutes": 20.2,
884
- "mfu_percent": 22.2,
885
- "gpu_util_percent": 100,
886
- "gpu_memory_gb": 85.1
887
- },
888
- {
889
- "step": 4150,
890
- "train_loss": 3.0252,
891
- "lr": 0.002212,
892
- "tokens_per_second": 920702,
893
- "minutes": 20.44,
894
- "mfu_percent": 22.2,
895
- "gpu_util_percent": 100,
896
- "gpu_memory_gb": 85.1
897
- },
898
- {
899
- "step": 4200,
900
- "train_loss": 2.9956,
901
- "lr": 0.002195,
902
- "tokens_per_second": 920999,
903
- "minutes": 20.68,
904
- "mfu_percent": 22.2,
905
- "gpu_util_percent": 100,
906
- "gpu_memory_gb": 85.1
907
- },
908
- {
909
- "step": 4250,
910
- "train_loss": 3.0576,
911
- "lr": 0.002178,
912
- "tokens_per_second": 920918,
913
- "minutes": 20.92,
914
- "mfu_percent": 22.2,
915
- "gpu_util_percent": 100,
916
- "gpu_memory_gb": 85.1
917
- },
918
- {
919
- "step": 4300,
920
- "train_loss": 3.0944,
921
- "lr": 0.00216,
922
- "tokens_per_second": 921070,
923
- "minutes": 21.15,
924
- "mfu_percent": 22.2,
925
- "gpu_util_percent": 100,
926
- "gpu_memory_gb": 85.1
927
- },
928
- {
929
- "step": 4350,
930
- "train_loss": 3.0655,
931
- "lr": 0.002143,
932
- "tokens_per_second": 921341,
933
- "minutes": 21.39,
934
- "mfu_percent": 22.2,
935
- "gpu_util_percent": 100,
936
- "gpu_memory_gb": 85.1
937
- },
938
- {
939
- "step": 4400,
940
- "train_loss": 3.0756,
941
- "lr": 0.002126,
942
- "tokens_per_second": 920880,
943
- "minutes": 21.63,
944
- "mfu_percent": 22.2,
945
- "gpu_util_percent": 100,
946
- "gpu_memory_gb": 85.1
947
- },
948
- {
949
- "step": 4450,
950
- "train_loss": 3.0513,
951
- "lr": 0.002108,
952
- "tokens_per_second": 921004,
953
- "minutes": 21.86,
954
- "mfu_percent": 22.2,
955
- "gpu_util_percent": 100,
956
- "gpu_memory_gb": 85.1
957
- },
958
- {
959
- "step": 4500,
960
- "train_loss": 3.0553,
961
- "lr": 0.002091,
962
- "tokens_per_second": 921256,
963
- "minutes": 22.1,
964
- "mfu_percent": 22.2,
965
- "gpu_util_percent": 100,
966
- "gpu_memory_gb": 85.1,
967
- "val_loss": 3.0698
968
- },
969
- {
970
- "step": 4550,
971
- "train_loss": 2.967,
972
- "lr": 0.002073,
973
- "tokens_per_second": 920961,
974
- "minutes": 22.39,
975
- "mfu_percent": 22.2,
976
- "gpu_util_percent": 100,
977
- "gpu_memory_gb": 85.1
978
- },
979
- {
980
- "step": 4600,
981
- "train_loss": 3.0567,
982
- "lr": 0.002056,
983
- "tokens_per_second": 920043,
984
- "minutes": 22.62,
985
- "mfu_percent": 22.2,
986
- "gpu_util_percent": 100,
987
- "gpu_memory_gb": 85.1
988
- },
989
- {
990
- "step": 4650,
991
- "train_loss": 3.0559,
992
- "lr": 0.002038,
993
- "tokens_per_second": 919645,
994
- "minutes": 22.86,
995
- "mfu_percent": 22.2,
996
- "gpu_util_percent": 100,
997
- "gpu_memory_gb": 85.1
998
- },
999
- {
1000
- "step": 4700,
1001
- "train_loss": 3.0584,
1002
- "lr": 0.00202,
1003
- "tokens_per_second": 920036,
1004
- "minutes": 23.1,
1005
- "mfu_percent": 22.2,
1006
- "gpu_util_percent": 100,
1007
- "gpu_memory_gb": 85.1
1008
- },
1009
- {
1010
- "step": 4750,
1011
- "train_loss": 3.0321,
1012
- "lr": 0.002002,
1013
- "tokens_per_second": 920584,
1014
- "minutes": 23.34,
1015
- "mfu_percent": 22.2,
1016
- "gpu_util_percent": 100,
1017
- "gpu_memory_gb": 85.1
1018
- },
1019
- {
1020
- "step": 4800,
1021
- "train_loss": 2.9678,
1022
- "lr": 0.001984,
1023
- "tokens_per_second": 920212,
1024
- "minutes": 23.57,
1025
- "mfu_percent": 22.2,
1026
- "gpu_util_percent": 100,
1027
- "gpu_memory_gb": 85.1
1028
- },
1029
- {
1030
- "step": 4850,
1031
- "train_loss": 2.9969,
1032
- "lr": 0.001966,
1033
- "tokens_per_second": 921129,
1034
- "minutes": 23.81,
1035
- "mfu_percent": 22.2,
1036
- "gpu_util_percent": 100,
1037
- "gpu_memory_gb": 85.1
1038
- },
1039
- {
1040
- "step": 4900,
1041
- "train_loss": 3.0317,
1042
- "lr": 0.001948,
1043
- "tokens_per_second": 921336,
1044
- "minutes": 24.05,
1045
- "mfu_percent": 22.2,
1046
- "gpu_util_percent": 100,
1047
- "gpu_memory_gb": 85.1
1048
- },
1049
- {
1050
- "step": 4950,
1051
- "train_loss": 3.0314,
1052
- "lr": 0.00193,
1053
- "tokens_per_second": 921674,
1054
- "minutes": 24.28,
1055
- "mfu_percent": 22.2,
1056
- "gpu_util_percent": 100,
1057
- "gpu_memory_gb": 85.1
1058
- },
1059
- {
1060
- "step": 5000,
1061
- "train_loss": 3.0467,
1062
- "lr": 0.001912,
1063
- "tokens_per_second": 922491,
1064
- "minutes": 24.52,
1065
- "mfu_percent": 22.2,
1066
- "gpu_util_percent": 100,
1067
- "gpu_memory_gb": 85.1,
1068
- "val_loss": 3.0507
1069
- },
1070
- {
1071
- "step": 5050,
1072
- "train_loss": 3.0208,
1073
- "lr": 0.001894,
1074
- "tokens_per_second": 922889,
1075
- "minutes": 24.8,
1076
- "mfu_percent": 22.3,
1077
- "gpu_util_percent": 100,
1078
- "gpu_memory_gb": 85.1
1079
- },
1080
- {
1081
- "step": 5100,
1082
- "train_loss": 2.9957,
1083
- "lr": 0.001875,
1084
- "tokens_per_second": 922887,
1085
- "minutes": 25.04,
1086
- "mfu_percent": 22.3,
1087
- "gpu_util_percent": 100,
1088
- "gpu_memory_gb": 85.1
1089
- },
1090
- {
1091
- "step": 5150,
1092
- "train_loss": 3.0355,
1093
- "lr": 0.001857,
1094
- "tokens_per_second": 922331,
1095
- "minutes": 25.28,
1096
- "mfu_percent": 22.2,
1097
- "gpu_util_percent": 100,
1098
- "gpu_memory_gb": 85.1
1099
- },
1100
- {
1101
- "step": 5200,
1102
- "train_loss": 3.0702,
1103
- "lr": 0.001839,
1104
- "tokens_per_second": 922142,
1105
- "minutes": 25.51,
1106
- "mfu_percent": 22.2,
1107
- "gpu_util_percent": 100,
1108
- "gpu_memory_gb": 85.1
1109
- },
1110
- {
1111
- "step": 5250,
1112
- "train_loss": 3.0055,
1113
- "lr": 0.00182,
1114
- "tokens_per_second": 922504,
1115
- "minutes": 25.75,
1116
- "mfu_percent": 22.2,
1117
- "gpu_util_percent": 100,
1118
- "gpu_memory_gb": 85.1
1119
- },
1120
- {
1121
- "step": 5300,
1122
- "train_loss": 2.9704,
1123
- "lr": 0.001802,
1124
- "tokens_per_second": 922274,
1125
- "minutes": 25.99,
1126
- "mfu_percent": 22.2,
1127
- "gpu_util_percent": 100,
1128
- "gpu_memory_gb": 85.1
1129
- },
1130
- {
1131
- "step": 5350,
1132
- "train_loss": 2.9492,
1133
- "lr": 0.001783,
1134
- "tokens_per_second": 921682,
1135
- "minutes": 26.23,
1136
- "mfu_percent": 22.2,
1137
- "gpu_util_percent": 100,
1138
- "gpu_memory_gb": 85.1
1139
- },
1140
- {
1141
- "step": 5400,
1142
- "train_loss": 3.0025,
1143
- "lr": 0.001765,
1144
- "tokens_per_second": 921085,
1145
- "minutes": 26.46,
1146
- "mfu_percent": 22.2,
1147
- "gpu_util_percent": 100,
1148
- "gpu_memory_gb": 85.1
1149
- },
1150
- {
1151
- "step": 5450,
1152
- "train_loss": 2.9997,
1153
- "lr": 0.001746,
1154
- "tokens_per_second": 921161,
1155
- "minutes": 26.7,
1156
- "mfu_percent": 22.2,
1157
- "gpu_util_percent": 100,
1158
- "gpu_memory_gb": 85.1
1159
- },
1160
- {
1161
- "step": 5500,
1162
- "train_loss": 3.012,
1163
- "lr": 0.001728,
1164
- "tokens_per_second": 921331,
1165
- "minutes": 26.94,
1166
- "mfu_percent": 22.2,
1167
- "gpu_util_percent": 100,
1168
- "gpu_memory_gb": 85.1,
1169
- "val_loss": 3.0312
1170
- },
1171
- {
1172
- "step": 5550,
1173
- "train_loss": 3.0025,
1174
- "lr": 0.001709,
1175
- "tokens_per_second": 921305,
1176
- "minutes": 27.22,
1177
- "mfu_percent": 22.2,
1178
- "gpu_util_percent": 100,
1179
- "gpu_memory_gb": 85.1
1180
- },
1181
- {
1182
- "step": 5600,
1183
- "train_loss": 2.9965,
1184
- "lr": 0.001691,
1185
- "tokens_per_second": 921367,
1186
- "minutes": 27.46,
1187
- "mfu_percent": 22.2,
1188
- "gpu_util_percent": 100,
1189
- "gpu_memory_gb": 85.1
1190
- },
1191
- {
1192
- "step": 5650,
1193
- "train_loss": 3.0261,
1194
- "lr": 0.001672,
1195
- "tokens_per_second": 921494,
1196
- "minutes": 27.7,
1197
- "mfu_percent": 22.2,
1198
- "gpu_util_percent": 100,
1199
- "gpu_memory_gb": 85.1
1200
- },
1201
- {
1202
- "step": 5700,
1203
- "train_loss": 2.9857,
1204
- "lr": 0.001654,
1205
- "tokens_per_second": 921931,
1206
- "minutes": 27.93,
1207
- "mfu_percent": 22.2,
1208
- "gpu_util_percent": 100,
1209
- "gpu_memory_gb": 85.1
1210
- },
1211
- {
1212
- "step": 5750,
1213
- "train_loss": 2.9916,
1214
- "lr": 0.001635,
1215
- "tokens_per_second": 921797,
1216
- "minutes": 28.17,
1217
- "mfu_percent": 22.2,
1218
- "gpu_util_percent": 100,
1219
- "gpu_memory_gb": 85.1
1220
- },
1221
- {
1222
- "step": 5800,
1223
- "train_loss": 2.9868,
1224
- "lr": 0.001616,
1225
- "tokens_per_second": 921701,
1226
- "minutes": 28.41,
1227
- "mfu_percent": 22.2,
1228
- "gpu_util_percent": 100,
1229
- "gpu_memory_gb": 85.1
1230
- },
1231
- {
1232
- "step": 5850,
1233
- "train_loss": 3.0135,
1234
- "lr": 0.001598,
1235
- "tokens_per_second": 921157,
1236
- "minutes": 28.64,
1237
- "mfu_percent": 22.2,
1238
- "gpu_util_percent": 100,
1239
- "gpu_memory_gb": 85.1
1240
- },
1241
- {
1242
- "step": 5900,
1243
- "train_loss": 3.0171,
1244
- "lr": 0.001579,
1245
- "tokens_per_second": 921347,
1246
- "minutes": 28.88,
1247
- "mfu_percent": 22.2,
1248
- "gpu_util_percent": 100,
1249
- "gpu_memory_gb": 85.1
1250
- },
1251
- {
1252
- "step": 5950,
1253
- "train_loss": 3.0381,
1254
- "lr": 0.001561,
1255
- "tokens_per_second": 921107,
1256
- "minutes": 29.12,
1257
- "mfu_percent": 22.2,
1258
- "gpu_util_percent": 100,
1259
- "gpu_memory_gb": 85.1
1260
- },
1261
- {
1262
- "step": 6000,
1263
- "train_loss": 3.0234,
1264
- "lr": 0.001542,
1265
- "tokens_per_second": 920618,
1266
- "minutes": 29.35,
1267
- "mfu_percent": 22.2,
1268
- "gpu_util_percent": 100,
1269
- "gpu_memory_gb": 85.1,
1270
- "val_loss": 3.014
1271
- },
1272
- {
1273
- "step": 6050,
1274
- "train_loss": 2.9671,
1275
- "lr": 0.001524,
1276
- "tokens_per_second": 920459,
1277
- "minutes": 29.64,
1278
- "mfu_percent": 22.2,
1279
- "gpu_util_percent": 100,
1280
- "gpu_memory_gb": 85.1
1281
- },
1282
- {
1283
- "step": 6100,
1284
- "train_loss": 3.0432,
1285
- "lr": 0.001505,
1286
- "tokens_per_second": 919920,
1287
- "minutes": 29.88,
1288
- "mfu_percent": 22.2,
1289
- "gpu_util_percent": 100,
1290
- "gpu_memory_gb": 85.1
1291
- },
1292
- {
1293
- "step": 6150,
1294
- "train_loss": 3.0124,
1295
- "lr": 0.001487,
1296
- "tokens_per_second": 920638,
1297
- "minutes": 30.11,
1298
- "mfu_percent": 22.2,
1299
- "gpu_util_percent": 100,
1300
- "gpu_memory_gb": 85.1
1301
- },
1302
- {
1303
- "step": 6200,
1304
- "train_loss": 3.0045,
1305
- "lr": 0.001468,
1306
- "tokens_per_second": 919978,
1307
- "minutes": 30.35,
1308
- "mfu_percent": 22.2,
1309
- "gpu_util_percent": 100,
1310
- "gpu_memory_gb": 85.1
1311
- },
1312
- {
1313
- "step": 6250,
1314
- "train_loss": 3.0096,
1315
- "lr": 0.00145,
1316
- "tokens_per_second": 919568,
1317
- "minutes": 30.59,
1318
- "mfu_percent": 22.2,
1319
- "gpu_util_percent": 100,
1320
- "gpu_memory_gb": 85.1
1321
- },
1322
- {
1323
- "step": 6300,
1324
- "train_loss": 2.9723,
1325
- "lr": 0.001432,
1326
- "tokens_per_second": 919292,
1327
- "minutes": 30.83,
1328
- "mfu_percent": 22.2,
1329
- "gpu_util_percent": 100,
1330
- "gpu_memory_gb": 85.1
1331
- },
1332
- {
1333
- "step": 6350,
1334
- "train_loss": 2.9286,
1335
- "lr": 0.001413,
1336
- "tokens_per_second": 919775,
1337
- "minutes": 31.06,
1338
- "mfu_percent": 22.2,
1339
- "gpu_util_percent": 100,
1340
- "gpu_memory_gb": 85.1
1341
- },
1342
- {
1343
- "step": 6400,
1344
- "train_loss": 3.0349,
1345
- "lr": 0.001395,
1346
- "tokens_per_second": 920505,
1347
- "minutes": 31.3,
1348
- "mfu_percent": 22.2,
1349
- "gpu_util_percent": 100,
1350
- "gpu_memory_gb": 85.1
1351
- },
1352
- {
1353
- "step": 6450,
1354
- "train_loss": 2.9374,
1355
- "lr": 0.001377,
1356
- "tokens_per_second": 920417,
1357
- "minutes": 31.54,
1358
- "mfu_percent": 22.2,
1359
- "gpu_util_percent": 100,
1360
- "gpu_memory_gb": 85.1
1361
- },
1362
- {
1363
- "step": 6500,
1364
- "train_loss": 2.9625,
1365
- "lr": 0.001359,
1366
- "tokens_per_second": 919773,
1367
- "minutes": 31.78,
1368
- "mfu_percent": 22.2,
1369
- "gpu_util_percent": 100,
1370
- "gpu_memory_gb": 85.1,
1371
- "val_loss": 2.9999
1372
- },
1373
- {
1374
- "step": 6550,
1375
- "train_loss": 2.9994,
1376
- "lr": 0.001341,
1377
- "tokens_per_second": 919974,
1378
- "minutes": 32.06,
1379
- "mfu_percent": 22.2,
1380
- "gpu_util_percent": 100,
1381
- "gpu_memory_gb": 85.1
1382
- },
1383
- {
1384
- "step": 6600,
1385
- "train_loss": 2.9899,
1386
- "lr": 0.001323,
1387
- "tokens_per_second": 920286,
1388
- "minutes": 32.3,
1389
- "mfu_percent": 22.2,
1390
- "gpu_util_percent": 100,
1391
- "gpu_memory_gb": 85.1
1392
- },
1393
- {
1394
- "step": 6650,
1395
- "train_loss": 2.9663,
1396
- "lr": 0.001305,
1397
- "tokens_per_second": 920398,
1398
- "minutes": 32.54,
1399
- "mfu_percent": 22.2,
1400
- "gpu_util_percent": 100,
1401
- "gpu_memory_gb": 85.1
1402
- },
1403
- {
1404
- "step": 6700,
1405
- "train_loss": 2.9463,
1406
- "lr": 0.001287,
1407
- "tokens_per_second": 921337,
1408
- "minutes": 32.77,
1409
- "mfu_percent": 22.2,
1410
- "gpu_util_percent": 100,
1411
- "gpu_memory_gb": 85.1
1412
- },
1413
- {
1414
- "step": 6750,
1415
- "train_loss": 2.9973,
1416
- "lr": 0.001269,
1417
- "tokens_per_second": 921370,
1418
- "minutes": 33.01,
1419
- "mfu_percent": 22.2,
1420
- "gpu_util_percent": 100,
1421
- "gpu_memory_gb": 85.1
1422
- },
1423
- {
1424
- "step": 6800,
1425
- "train_loss": 2.9206,
1426
- "lr": 0.001251,
1427
- "tokens_per_second": 920742,
1428
- "minutes": 33.25,
1429
- "mfu_percent": 22.2,
1430
- "gpu_util_percent": 100,
1431
- "gpu_memory_gb": 85.1
1432
- },
1433
- {
1434
- "step": 6850,
1435
- "train_loss": 2.9574,
1436
- "lr": 0.001233,
1437
- "tokens_per_second": 920284,
1438
- "minutes": 33.48,
1439
- "mfu_percent": 22.2,
1440
- "gpu_util_percent": 100,
1441
- "gpu_memory_gb": 85.1
1442
- },
1443
- {
1444
- "step": 6900,
1445
- "train_loss": 2.9734,
1446
- "lr": 0.001216,
1447
- "tokens_per_second": 919909,
1448
- "minutes": 33.72,
1449
- "mfu_percent": 22.2,
1450
- "gpu_util_percent": 100,
1451
- "gpu_memory_gb": 85.1
1452
- },
1453
- {
1454
- "step": 6950,
1455
- "train_loss": 2.992,
1456
- "lr": 0.001198,
1457
- "tokens_per_second": 919380,
1458
- "minutes": 33.96,
1459
- "mfu_percent": 22.2,
1460
- "gpu_util_percent": 100,
1461
- "gpu_memory_gb": 85.1
1462
- },
1463
- {
1464
- "step": 7000,
1465
- "train_loss": 2.9482,
1466
- "lr": 0.001181,
1467
- "tokens_per_second": 919305,
1468
- "minutes": 34.2,
1469
- "mfu_percent": 22.2,
1470
- "gpu_util_percent": 100,
1471
- "gpu_memory_gb": 85.1,
1472
- "val_loss": 2.9834
1473
- },
1474
- {
1475
- "step": 7050,
1476
- "train_loss": 2.9944,
1477
- "lr": 0.001163,
1478
- "tokens_per_second": 919402,
1479
- "minutes": 34.48,
1480
- "mfu_percent": 22.2,
1481
- "gpu_util_percent": 100,
1482
- "gpu_memory_gb": 85.1
1483
- },
1484
- {
1485
- "step": 7100,
1486
- "train_loss": 2.9649,
1487
- "lr": 0.001146,
1488
- "tokens_per_second": 919490,
1489
- "minutes": 34.72,
1490
- "mfu_percent": 22.2,
1491
- "gpu_util_percent": 100,
1492
- "gpu_memory_gb": 85.1
1493
- },
1494
- {
1495
- "step": 7150,
1496
- "train_loss": 2.9533,
1497
- "lr": 0.001129,
1498
- "tokens_per_second": 919450,
1499
- "minutes": 34.96,
1500
- "mfu_percent": 22.2,
1501
- "gpu_util_percent": 100,
1502
- "gpu_memory_gb": 85.1
1503
- },
1504
- {
1505
- "step": 7200,
1506
- "train_loss": 2.9467,
1507
- "lr": 0.001112,
1508
- "tokens_per_second": 919809,
1509
- "minutes": 35.19,
1510
- "mfu_percent": 22.2,
1511
- "gpu_util_percent": 100,
1512
- "gpu_memory_gb": 85.1
1513
- },
1514
- {
1515
- "step": 7250,
1516
- "train_loss": 2.9482,
1517
- "lr": 0.001095,
1518
- "tokens_per_second": 920118,
1519
- "minutes": 35.43,
1520
- "mfu_percent": 22.2,
1521
- "gpu_util_percent": 100,
1522
- "gpu_memory_gb": 85.1
1523
- },
1524
- {
1525
- "step": 7300,
1526
- "train_loss": 2.9288,
1527
- "lr": 0.001078,
1528
- "tokens_per_second": 920161,
1529
- "minutes": 35.67,
1530
- "mfu_percent": 22.2,
1531
- "gpu_util_percent": 100,
1532
- "gpu_memory_gb": 85.1
1533
- },
1534
- {
1535
- "step": 7350,
1536
- "train_loss": 2.9711,
1537
- "lr": 0.001061,
1538
- "tokens_per_second": 920166,
1539
- "minutes": 35.91,
1540
- "mfu_percent": 22.2,
1541
- "gpu_util_percent": 100,
1542
- "gpu_memory_gb": 85.1
1543
- },
1544
- {
1545
- "step": 7400,
1546
- "train_loss": 2.9711,
1547
- "lr": 0.001045,
1548
- "tokens_per_second": 920031,
1549
- "minutes": 36.14,
1550
- "mfu_percent": 22.2,
1551
- "gpu_util_percent": 100,
1552
- "gpu_memory_gb": 85.1
1553
- },
1554
- {
1555
- "step": 7450,
1556
- "train_loss": 2.9619,
1557
- "lr": 0.001028,
1558
- "tokens_per_second": 920234,
1559
- "minutes": 36.38,
1560
- "mfu_percent": 22.2,
1561
- "gpu_util_percent": 100,
1562
- "gpu_memory_gb": 85.1
1563
- },
1564
- {
1565
- "step": 7500,
1566
- "train_loss": 2.9199,
1567
- "lr": 0.001012,
1568
- "tokens_per_second": 920421,
1569
- "minutes": 36.62,
1570
- "mfu_percent": 22.2,
1571
- "gpu_util_percent": 100,
1572
- "gpu_memory_gb": 85.1,
1573
- "val_loss": 2.9683
1574
- },
1575
- {
1576
- "step": 7550,
1577
- "train_loss": 2.9091,
1578
- "lr": 0.000995,
1579
- "tokens_per_second": 921260,
1580
- "minutes": 36.9,
1581
- "mfu_percent": 22.2,
1582
- "gpu_util_percent": 100,
1583
- "gpu_memory_gb": 85.1
1584
- },
1585
- {
1586
- "step": 7600,
1587
- "train_loss": 2.9747,
1588
- "lr": 0.000979,
1589
- "tokens_per_second": 920906,
1590
- "minutes": 37.14,
1591
- "mfu_percent": 22.2,
1592
- "gpu_util_percent": 100,
1593
- "gpu_memory_gb": 85.1
1594
- },
1595
- {
1596
- "step": 7650,
1597
- "train_loss": 2.9445,
1598
- "lr": 0.000963,
1599
- "tokens_per_second": 920371,
1600
- "minutes": 37.38,
1601
- "mfu_percent": 22.2,
1602
- "gpu_util_percent": 100,
1603
- "gpu_memory_gb": 85.1
1604
- },
1605
- {
1606
- "step": 7700,
1607
- "train_loss": 2.9593,
1608
- "lr": 0.000947,
1609
- "tokens_per_second": 920018,
1610
- "minutes": 37.62,
1611
- "mfu_percent": 22.2,
1612
- "gpu_util_percent": 100,
1613
- "gpu_memory_gb": 85.1
1614
- },
1615
- {
1616
- "step": 7750,
1617
- "train_loss": 2.9826,
1618
- "lr": 0.000931,
1619
- "tokens_per_second": 920997,
1620
- "minutes": 37.85,
1621
- "mfu_percent": 22.2,
1622
- "gpu_util_percent": 100,
1623
- "gpu_memory_gb": 85.1
1624
- },
1625
- {
1626
- "step": 7800,
1627
- "train_loss": 2.933,
1628
- "lr": 0.000916,
1629
- "tokens_per_second": 921462,
1630
- "minutes": 38.09,
1631
- "mfu_percent": 22.2,
1632
- "gpu_util_percent": 100,
1633
- "gpu_memory_gb": 85.1
1634
- },
1635
- {
1636
- "step": 7850,
1637
- "train_loss": 2.9202,
1638
- "lr": 0.0009,
1639
- "tokens_per_second": 921036,
1640
- "minutes": 38.33,
1641
- "mfu_percent": 22.2,
1642
- "gpu_util_percent": 100,
1643
- "gpu_memory_gb": 85.1
1644
- },
1645
- {
1646
- "step": 7900,
1647
- "train_loss": 2.9152,
1648
- "lr": 0.000885,
1649
- "tokens_per_second": 920538,
1650
- "minutes": 38.56,
1651
- "mfu_percent": 22.2,
1652
- "gpu_util_percent": 100,
1653
- "gpu_memory_gb": 85.1
1654
- },
1655
- {
1656
- "step": 7950,
1657
- "train_loss": 2.926,
1658
- "lr": 0.00087,
1659
- "tokens_per_second": 919615,
1660
- "minutes": 38.8,
1661
- "mfu_percent": 22.2,
1662
- "gpu_util_percent": 100,
1663
- "gpu_memory_gb": 85.1
1664
- },
1665
- {
1666
- "step": 8000,
1667
- "train_loss": 2.8966,
1668
- "lr": 0.000855,
1669
- "tokens_per_second": 919288,
1670
- "minutes": 39.04,
1671
- "mfu_percent": 22.2,
1672
- "gpu_util_percent": 100,
1673
- "gpu_memory_gb": 85.1,
1674
- "val_loss": 2.9544
1675
- },
1676
- {
1677
- "step": 8050,
1678
- "train_loss": 2.9517,
1679
- "lr": 0.00084,
1680
- "tokens_per_second": 919884,
1681
- "minutes": 39.32,
1682
- "mfu_percent": 22.2,
1683
- "gpu_util_percent": 100,
1684
- "gpu_memory_gb": 85.1
1685
- },
1686
- {
1687
- "step": 8100,
1688
- "train_loss": 2.9257,
1689
- "lr": 0.000825,
1690
- "tokens_per_second": 921250,
1691
- "minutes": 39.56,
1692
- "mfu_percent": 22.2,
1693
- "gpu_util_percent": 100,
1694
- "gpu_memory_gb": 85.1
1695
- },
1696
- {
1697
- "step": 8150,
1698
- "train_loss": 2.9299,
1699
- "lr": 0.00081,
1700
- "tokens_per_second": 921425,
1701
- "minutes": 39.8,
1702
- "mfu_percent": 22.2,
1703
- "gpu_util_percent": 100,
1704
- "gpu_memory_gb": 85.1
1705
- },
1706
- {
1707
- "step": 8200,
1708
- "train_loss": 2.934,
1709
- "lr": 0.000796,
1710
- "tokens_per_second": 921296,
1711
- "minutes": 40.04,
1712
- "mfu_percent": 22.2,
1713
- "gpu_util_percent": 100,
1714
- "gpu_memory_gb": 85.1
1715
- },
1716
- {
1717
- "step": 8250,
1718
- "train_loss": 2.8999,
1719
- "lr": 0.000782,
1720
- "tokens_per_second": 920909,
1721
- "minutes": 40.27,
1722
- "mfu_percent": 22.2,
1723
- "gpu_util_percent": 100,
1724
- "gpu_memory_gb": 85.1
1725
- },
1726
- {
1727
- "step": 8300,
1728
- "train_loss": 2.9048,
1729
- "lr": 0.000767,
1730
- "tokens_per_second": 920173,
1731
- "minutes": 40.51,
1732
- "mfu_percent": 22.2,
1733
- "gpu_util_percent": 100,
1734
- "gpu_memory_gb": 85.1
1735
- },
1736
- {
1737
- "step": 8350,
1738
- "train_loss": 2.8714,
1739
- "lr": 0.000753,
1740
- "tokens_per_second": 919853,
1741
- "minutes": 40.75,
1742
- "mfu_percent": 22.2,
1743
- "gpu_util_percent": 100,
1744
- "gpu_memory_gb": 85.1
1745
- },
1746
- {
1747
- "step": 8400,
1748
- "train_loss": 2.8722,
1749
- "lr": 0.00074,
1750
- "tokens_per_second": 919551,
1751
- "minutes": 40.98,
1752
- "mfu_percent": 22.2,
1753
- "gpu_util_percent": 100,
1754
- "gpu_memory_gb": 85.1
1755
- },
1756
- {
1757
- "step": 8450,
1758
- "train_loss": 2.9693,
1759
- "lr": 0.000726,
1760
- "tokens_per_second": 920679,
1761
- "minutes": 41.22,
1762
- "mfu_percent": 22.2,
1763
- "gpu_util_percent": 100,
1764
- "gpu_memory_gb": 85.1
1765
- },
1766
- {
1767
- "step": 8500,
1768
- "train_loss": 2.9393,
1769
- "lr": 0.000713,
1770
- "tokens_per_second": 921776,
1771
- "minutes": 41.46,
1772
- "mfu_percent": 22.2,
1773
- "gpu_util_percent": 100,
1774
- "gpu_memory_gb": 85.1,
1775
- "val_loss": 2.9392
1776
- },
1777
- {
1778
- "step": 8550,
1779
- "train_loss": 2.8964,
1780
- "lr": 0.000699,
1781
- "tokens_per_second": 920913,
1782
- "minutes": 41.74,
1783
- "mfu_percent": 22.2,
1784
- "gpu_util_percent": 100,
1785
- "gpu_memory_gb": 85.1
1786
- },
1787
- {
1788
- "step": 8600,
1789
- "train_loss": 2.9192,
1790
- "lr": 0.000686,
1791
- "tokens_per_second": 919992,
1792
- "minutes": 41.98,
1793
- "mfu_percent": 22.2,
1794
- "gpu_util_percent": 100,
1795
- "gpu_memory_gb": 85.1
1796
- },
1797
- {
1798
- "step": 8650,
1799
- "train_loss": 2.9288,
1800
- "lr": 0.000673,
1801
- "tokens_per_second": 919914,
1802
- "minutes": 42.22,
1803
- "mfu_percent": 22.2,
1804
- "gpu_util_percent": 100,
1805
- "gpu_memory_gb": 85.1
1806
- },
1807
- {
1808
- "step": 8700,
1809
- "train_loss": 2.8246,
1810
- "lr": 0.000661,
1811
- "tokens_per_second": 919626,
1812
- "minutes": 42.46,
1813
- "mfu_percent": 22.2,
1814
- "gpu_util_percent": 100,
1815
- "gpu_memory_gb": 85.1
1816
- },
1817
- {
1818
- "step": 8750,
1819
- "train_loss": 2.9473,
1820
- "lr": 0.000648,
1821
- "tokens_per_second": 919635,
1822
- "minutes": 42.69,
1823
- "mfu_percent": 22.2,
1824
- "gpu_util_percent": 100,
1825
- "gpu_memory_gb": 85.1
1826
- },
1827
- {
1828
- "step": 8800,
1829
- "train_loss": 2.8781,
1830
- "lr": 0.000636,
1831
- "tokens_per_second": 921027,
1832
- "minutes": 42.93,
1833
- "mfu_percent": 22.2,
1834
- "gpu_util_percent": 100,
1835
- "gpu_memory_gb": 85.1
1836
- },
1837
- {
1838
- "step": 8850,
1839
- "train_loss": 2.8393,
1840
- "lr": 0.000624,
1841
- "tokens_per_second": 921693,
1842
- "minutes": 43.17,
1843
- "mfu_percent": 22.2,
1844
- "gpu_util_percent": 100,
1845
- "gpu_memory_gb": 85.1
1846
- },
1847
- {
1848
- "step": 8900,
1849
- "train_loss": 2.9105,
1850
- "lr": 0.000612,
1851
- "tokens_per_second": 922213,
1852
- "minutes": 43.4,
1853
- "mfu_percent": 22.2,
1854
- "gpu_util_percent": 100,
1855
- "gpu_memory_gb": 85.1
1856
- },
1857
- {
1858
- "step": 8950,
1859
- "train_loss": 2.9286,
1860
- "lr": 0.0006,
1861
- "tokens_per_second": 923184,
1862
- "minutes": 43.64,
1863
- "mfu_percent": 22.3,
1864
- "gpu_util_percent": 100,
1865
- "gpu_memory_gb": 85.1
1866
- },
1867
- {
1868
- "step": 9000,
1869
- "train_loss": 2.8668,
1870
- "lr": 0.000588,
1871
- "tokens_per_second": 923153,
1872
- "minutes": 43.88,
1873
- "mfu_percent": 22.3,
1874
- "gpu_util_percent": 100,
1875
- "gpu_memory_gb": 85.1,
1876
- "val_loss": 2.9286
1877
- },
1878
- {
1879
- "step": 9050,
1880
- "train_loss": 2.9063,
1881
- "lr": 0.000577,
1882
- "tokens_per_second": 922088,
1883
- "minutes": 44.16,
1884
- "mfu_percent": 22.2,
1885
- "gpu_util_percent": 100,
1886
- "gpu_memory_gb": 85.1
1887
- },
1888
- {
1889
- "step": 9100,
1890
- "train_loss": 2.9428,
1891
- "lr": 0.000566,
1892
- "tokens_per_second": 921296,
1893
- "minutes": 44.4,
1894
- "mfu_percent": 22.2,
1895
- "gpu_util_percent": 100,
1896
- "gpu_memory_gb": 85.1
1897
- },
1898
- {
1899
- "step": 9150,
1900
- "train_loss": 2.9146,
1901
- "lr": 0.000555,
1902
- "tokens_per_second": 920478,
1903
- "minutes": 44.64,
1904
- "mfu_percent": 22.2,
1905
- "gpu_util_percent": 100,
1906
- "gpu_memory_gb": 85.1
1907
- },
1908
- {
1909
- "step": 9200,
1910
- "train_loss": 2.9337,
1911
- "lr": 0.000544,
1912
- "tokens_per_second": 919857,
1913
- "minutes": 44.87,
1914
- "mfu_percent": 22.2,
1915
- "gpu_util_percent": 100,
1916
- "gpu_memory_gb": 85.1
1917
- },
1918
- {
1919
- "step": 9250,
1920
- "train_loss": 2.8898,
1921
- "lr": 0.000533,
1922
- "tokens_per_second": 919677,
1923
- "minutes": 45.11,
1924
- "mfu_percent": 22.2,
1925
- "gpu_util_percent": 100,
1926
- "gpu_memory_gb": 85.1
1927
- },
1928
- {
1929
- "step": 9300,
1930
- "train_loss": 2.8907,
1931
- "lr": 0.000523,
1932
- "tokens_per_second": 919018,
1933
- "minutes": 45.35,
1934
- "mfu_percent": 22.2,
1935
- "gpu_util_percent": 100,
1936
- "gpu_memory_gb": 85.1
1937
- },
1938
- {
1939
- "step": 9350,
1940
- "train_loss": 2.9104,
1941
- "lr": 0.000513,
1942
- "tokens_per_second": 919151,
1943
- "minutes": 45.59,
1944
- "mfu_percent": 22.2,
1945
- "gpu_util_percent": 100,
1946
- "gpu_memory_gb": 85.1
1947
- },
1948
- {
1949
- "step": 9400,
1950
- "train_loss": 2.9346,
1951
- "lr": 0.000503,
1952
- "tokens_per_second": 919820,
1953
- "minutes": 45.82,
1954
- "mfu_percent": 22.2,
1955
- "gpu_util_percent": 100,
1956
- "gpu_memory_gb": 85.1
1957
- },
1958
- {
1959
- "step": 9450,
1960
- "train_loss": 2.864,
1961
- "lr": 0.000493,
1962
- "tokens_per_second": 920435,
1963
- "minutes": 46.06,
1964
- "mfu_percent": 22.2,
1965
- "gpu_util_percent": 100,
1966
- "gpu_memory_gb": 85.1
1967
- },
1968
- {
1969
- "step": 9500,
1970
- "train_loss": 2.8496,
1971
- "lr": 0.000484,
1972
- "tokens_per_second": 920689,
1973
- "minutes": 46.3,
1974
- "mfu_percent": 22.2,
1975
- "gpu_util_percent": 100,
1976
- "gpu_memory_gb": 85.1,
1977
- "val_loss": 2.9166
1978
- },
1979
- {
1980
- "step": 9550,
1981
- "train_loss": 2.9794,
1982
- "lr": 0.000475,
1983
- "tokens_per_second": 920761,
1984
- "minutes": 46.58,
1985
- "mfu_percent": 22.2,
1986
- "gpu_util_percent": 100,
1987
- "gpu_memory_gb": 85.1
1988
- },
1989
- {
1990
- "step": 9600,
1991
- "train_loss": 2.8557,
1992
- "lr": 0.000466,
1993
- "tokens_per_second": 921094,
1994
- "minutes": 46.82,
1995
- "mfu_percent": 22.2,
1996
- "gpu_util_percent": 100,
1997
- "gpu_memory_gb": 85.1
1998
- },
1999
- {
2000
- "step": 9650,
2001
- "train_loss": 2.8992,
2002
- "lr": 0.000457,
2003
- "tokens_per_second": 921528,
2004
- "minutes": 47.06,
2005
- "mfu_percent": 22.2,
2006
- "gpu_util_percent": 100,
2007
- "gpu_memory_gb": 85.1
2008
- },
2009
- {
2010
- "step": 9700,
2011
- "train_loss": 2.835,
2012
- "lr": 0.000448,
2013
- "tokens_per_second": 920716,
2014
- "minutes": 47.29,
2015
- "mfu_percent": 22.2,
2016
- "gpu_util_percent": 100,
2017
- "gpu_memory_gb": 85.1
2018
- },
2019
- {
2020
- "step": 9750,
2021
- "train_loss": 2.9188,
2022
- "lr": 0.00044,
2023
- "tokens_per_second": 920417,
2024
- "minutes": 47.53,
2025
- "mfu_percent": 22.2,
2026
- "gpu_util_percent": 100,
2027
- "gpu_memory_gb": 85.1
2028
- },
2029
- {
2030
- "step": 9800,
2031
- "train_loss": 2.925,
2032
- "lr": 0.000432,
2033
- "tokens_per_second": 920052,
2034
- "minutes": 47.77,
2035
- "mfu_percent": 22.2,
2036
- "gpu_util_percent": 100,
2037
- "gpu_memory_gb": 85.1
2038
- },
2039
- {
2040
- "step": 9850,
2041
- "train_loss": 2.9457,
2042
- "lr": 0.000424,
2043
- "tokens_per_second": 919561,
2044
- "minutes": 48.01,
2045
- "mfu_percent": 22.2,
2046
- "gpu_util_percent": 100,
2047
- "gpu_memory_gb": 85.1
2048
- },
2049
- {
2050
- "step": 9900,
2051
- "train_loss": 2.9236,
2052
- "lr": 0.000416,
2053
- "tokens_per_second": 919301,
2054
- "minutes": 48.24,
2055
- "mfu_percent": 22.2,
2056
- "gpu_util_percent": 100,
2057
- "gpu_memory_gb": 85.1
2058
- },
2059
- {
2060
- "step": 9950,
2061
- "train_loss": 2.8542,
2062
- "lr": 0.000409,
2063
- "tokens_per_second": 919176,
2064
- "minutes": 48.48,
2065
- "mfu_percent": 22.2,
2066
- "gpu_util_percent": 100,
2067
- "gpu_memory_gb": 85.1
2068
- },
2069
- {
2070
- "step": 10000,
2071
- "train_loss": 2.8907,
2072
- "lr": 0.000402,
2073
- "tokens_per_second": 919788,
2074
- "minutes": 48.72,
2075
- "mfu_percent": 22.2,
2076
- "gpu_util_percent": 100,
2077
- "gpu_memory_gb": 85.1,
2078
- "val_loss": 2.9086
2079
- },
2080
- {
2081
- "step": 10050,
2082
- "train_loss": 2.7981,
2083
- "lr": 0.000395,
2084
- "tokens_per_second": 920621,
2085
- "minutes": 49.0,
2086
- "mfu_percent": 22.2,
2087
- "gpu_util_percent": 100,
2088
- "gpu_memory_gb": 85.1
2089
- },
2090
- {
2091
- "step": 10100,
2092
- "train_loss": 2.8218,
2093
- "lr": 0.000388,
2094
- "tokens_per_second": 920907,
2095
- "minutes": 49.24,
2096
- "mfu_percent": 22.2,
2097
- "gpu_util_percent": 100,
2098
- "gpu_memory_gb": 85.1
2099
- },
2100
- {
2101
- "step": 10150,
2102
- "train_loss": 2.8762,
2103
- "lr": 0.000382,
2104
- "tokens_per_second": 921101,
2105
- "minutes": 49.48,
2106
- "mfu_percent": 22.2,
2107
- "gpu_util_percent": 100,
2108
- "gpu_memory_gb": 85.1
2109
- },
2110
- {
2111
- "step": 10200,
2112
- "train_loss": 2.8884,
2113
- "lr": 0.000375,
2114
- "tokens_per_second": 920843,
2115
- "minutes": 49.72,
2116
- "mfu_percent": 22.2,
2117
- "gpu_util_percent": 100,
2118
- "gpu_memory_gb": 85.1
2119
- },
2120
- {
2121
- "step": 10250,
2122
- "train_loss": 2.8617,
2123
- "lr": 0.000369,
2124
- "tokens_per_second": 921002,
2125
- "minutes": 49.95,
2126
- "mfu_percent": 22.2,
2127
- "gpu_util_percent": 100,
2128
- "gpu_memory_gb": 85.1
2129
- },
2130
- {
2131
- "step": 10300,
2132
- "train_loss": 2.8414,
2133
- "lr": 0.000364,
2134
- "tokens_per_second": 921151,
2135
- "minutes": 50.19,
2136
- "mfu_percent": 22.2,
2137
- "gpu_util_percent": 100,
2138
- "gpu_memory_gb": 85.1
2139
- },
2140
- {
2141
- "step": 10350,
2142
- "train_loss": 2.8439,
2143
- "lr": 0.000358,
2144
- "tokens_per_second": 920309,
2145
- "minutes": 50.43,
2146
- "mfu_percent": 22.2,
2147
- "gpu_util_percent": 100,
2148
- "gpu_memory_gb": 85.1
2149
- },
2150
- {
2151
- "step": 10400,
2152
- "train_loss": 2.8992,
2153
- "lr": 0.000353,
2154
- "tokens_per_second": 919693,
2155
- "minutes": 50.66,
2156
- "mfu_percent": 22.2,
2157
- "gpu_util_percent": 100,
2158
- "gpu_memory_gb": 85.1
2159
- },
2160
- {
2161
- "step": 10450,
2162
- "train_loss": 2.8711,
2163
- "lr": 0.000348,
2164
- "tokens_per_second": 919270,
2165
- "minutes": 50.9,
2166
- "mfu_percent": 22.2,
2167
- "gpu_util_percent": 100,
2168
- "gpu_memory_gb": 85.1
2169
- },
2170
- {
2171
- "step": 10500,
2172
- "train_loss": 2.8533,
2173
- "lr": 0.000343,
2174
- "tokens_per_second": 920712,
2175
- "minutes": 51.14,
2176
- "mfu_percent": 22.2,
2177
- "gpu_util_percent": 100,
2178
- "gpu_memory_gb": 85.1,
2179
- "val_loss": 2.9005
2180
- },
2181
- {
2182
- "step": 10550,
2183
- "train_loss": 2.8638,
2184
- "lr": 0.000338,
2185
- "tokens_per_second": 921492,
2186
- "minutes": 51.42,
2187
- "mfu_percent": 22.2,
2188
- "gpu_util_percent": 100,
2189
- "gpu_memory_gb": 85.1
2190
- },
2191
- {
2192
- "step": 10600,
2193
- "train_loss": 2.8673,
2194
- "lr": 0.000334,
2195
- "tokens_per_second": 921466,
2196
- "minutes": 51.66,
2197
- "mfu_percent": 22.2,
2198
- "gpu_util_percent": 100,
2199
- "gpu_memory_gb": 85.1
2200
- },
2201
- {
2202
- "step": 10650,
2203
- "train_loss": 2.8849,
2204
- "lr": 0.00033,
2205
- "tokens_per_second": 920910,
2206
- "minutes": 51.9,
2207
- "mfu_percent": 22.2,
2208
- "gpu_util_percent": 100,
2209
- "gpu_memory_gb": 85.1
2210
- },
2211
- {
2212
- "step": 10700,
2213
- "train_loss": 2.8652,
2214
- "lr": 0.000326,
2215
- "tokens_per_second": 920277,
2216
- "minutes": 52.14,
2217
- "mfu_percent": 22.2,
2218
- "gpu_util_percent": 100,
2219
- "gpu_memory_gb": 85.1
2220
- },
2221
- {
2222
- "step": 10750,
2223
- "train_loss": 2.8523,
2224
- "lr": 0.000323,
2225
- "tokens_per_second": 919903,
2226
- "minutes": 52.37,
2227
- "mfu_percent": 22.2,
2228
- "gpu_util_percent": 100,
2229
- "gpu_memory_gb": 85.1
2230
- },
2231
- {
2232
- "step": 10800,
2233
- "train_loss": 2.8797,
2234
- "lr": 0.00032,
2235
- "tokens_per_second": 919671,
2236
- "minutes": 52.61,
2237
- "mfu_percent": 22.2,
2238
- "gpu_util_percent": 100,
2239
- "gpu_memory_gb": 85.1
2240
- },
2241
- {
2242
- "step": 10850,
2243
- "train_loss": 2.858,
2244
- "lr": 0.000317,
2245
- "tokens_per_second": 919122,
2246
- "minutes": 52.85,
2247
- "mfu_percent": 22.2,
2248
- "gpu_util_percent": 100,
2249
- "gpu_memory_gb": 85.1
2250
- },
2251
- {
2252
- "step": 10900,
2253
- "train_loss": 2.8607,
2254
- "lr": 0.000314,
2255
- "tokens_per_second": 919161,
2256
- "minutes": 53.09,
2257
- "mfu_percent": 22.2,
2258
- "gpu_util_percent": 100,
2259
- "gpu_memory_gb": 85.1
2260
- },
2261
- {
2262
- "step": 10950,
2263
- "train_loss": 2.8733,
2264
- "lr": 0.000311,
2265
- "tokens_per_second": 920086,
2266
- "minutes": 53.32,
2267
- "mfu_percent": 22.2,
2268
- "gpu_util_percent": 100,
2269
- "gpu_memory_gb": 85.1
2270
- },
2271
- {
2272
- "step": 11000,
2273
- "train_loss": 2.8539,
2274
- "lr": 0.000309,
2275
- "tokens_per_second": 920688,
2276
- "minutes": 53.56,
2277
- "mfu_percent": 22.2,
2278
- "gpu_util_percent": 100,
2279
- "gpu_memory_gb": 85.1,
2280
- "val_loss": 2.8962
2281
- },
2282
- {
2283
- "step": 11050,
2284
- "train_loss": 2.8992,
2285
- "lr": 0.000307,
2286
- "tokens_per_second": 920928,
2287
- "minutes": 53.84,
2288
- "mfu_percent": 22.2,
2289
- "gpu_util_percent": 100,
2290
- "gpu_memory_gb": 85.1
2291
- },
2292
- {
2293
- "step": 11100,
2294
- "train_loss": 2.8486,
2295
- "lr": 0.000305,
2296
- "tokens_per_second": 920127,
2297
- "minutes": 54.08,
2298
- "mfu_percent": 22.2,
2299
- "gpu_util_percent": 100,
2300
- "gpu_memory_gb": 85.1
2301
- },
2302
- {
2303
- "step": 11150,
2304
- "train_loss": 2.8515,
2305
- "lr": 0.000304,
2306
- "tokens_per_second": 919904,
2307
- "minutes": 54.32,
2308
- "mfu_percent": 22.2,
2309
- "gpu_util_percent": 100,
2310
- "gpu_memory_gb": 85.1
2311
- },
2312
- {
2313
- "step": 11200,
2314
- "train_loss": 2.8647,
2315
- "lr": 0.000302,
2316
- "tokens_per_second": 919524,
2317
- "minutes": 54.56,
2318
- "mfu_percent": 22.2,
2319
- "gpu_util_percent": 100,
2320
- "gpu_memory_gb": 85.1
2321
- },
2322
- {
2323
- "step": 11250,
2324
- "train_loss": 2.8809,
2325
- "lr": 0.000301,
2326
- "tokens_per_second": 920127,
2327
- "minutes": 54.79,
2328
- "mfu_percent": 22.2,
2329
- "gpu_util_percent": 100,
2330
- "gpu_memory_gb": 85.1
2331
- },
2332
- {
2333
- "step": 11300,
2334
- "train_loss": 2.8752,
2335
- "lr": 0.000301,
2336
- "tokens_per_second": 921273,
2337
- "minutes": 55.03,
2338
- "mfu_percent": 22.2,
2339
- "gpu_util_percent": 100,
2340
- "gpu_memory_gb": 85.1
2341
- },
2342
- {
2343
- "step": 11350,
2344
- "train_loss": 2.9045,
2345
- "lr": 0.0003,
2346
- "tokens_per_second": 920772,
2347
- "minutes": 55.27,
2348
- "mfu_percent": 22.2,
2349
- "gpu_util_percent": 100,
2350
- "gpu_memory_gb": 85.1
2351
- },
2352
- {
2353
- "step": 11400,
2354
- "train_loss": 2.7934,
2355
- "lr": 0.0003,
2356
- "tokens_per_second": 920858,
2357
- "minutes": 55.51,
2358
- "mfu_percent": 22.2,
2359
- "gpu_util_percent": 100,
2360
- "gpu_memory_gb": 85.1
2361
- },
2362
- {
2363
- "step": 11420,
2364
- "train_loss": 2.8882,
2365
- "lr": 0.0003,
2366
- "tokens_per_second": 921250,
2367
- "minutes": 55.6,
2368
- "mfu_percent": 22.2,
2369
- "gpu_util_percent": 100,
2370
- "gpu_memory_gb": 85.1,
2371
- "val_loss": 2.8934
2372
- }
2373
- ],
2374
- "exports": {
2375
- "parity_prompts": 300,
2376
- "parity_steps_per_prompt": 5,
2377
- "float": {
2378
- "megabytes": 60.81,
2379
- "same_first_token": 1.0,
2380
- "same_five_greedy_tokens": 1.0,
2381
- "cached_step_ms_p50_cpu": 5.544
2382
- },
2383
- "int8": {
2384
- "megabytes": 15.64,
2385
- "same_first_token": 0.0,
2386
- "same_five_greedy_tokens": 0.0,
2387
- "cached_step_ms_p50_cpu": 4.808
2388
- }
2389
- }
2390
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
v2/experiments/tinynext-v2-3b/tokenizer.json DELETED
The diff for this file is too large to render. See raw diff
 
v2/experiments/tinynext-v2-3b/train.py DELETED
@@ -1,691 +0,0 @@
1
- # /// script
2
- # requires-python = ">=3.11,<3.14"
3
- # dependencies = [
4
- # "torch>=2.6,<2.8",
5
- # "datasets>=3.0",
6
- # "numpy<3",
7
- # "pyarrow>=15",
8
- # "tokenizers>=0.20",
9
- # "transformers>=4.46",
10
- # "onnx>=1.17",
11
- # "onnxruntime>=1.20",
12
- # "safetensors>=0.4",
13
- # "huggingface_hub>=0.30",
14
- # "nvidia-ml-py>=12",
15
- # "trackio>=0.2",
16
- # ]
17
- # ///
18
- """tinynext v2: a small word-piece transformer for in-browser autocomplete that can also fill in the middle.
19
-
20
- One script does everything: it trains a tokenizer, builds a mix of general text, conversation and email,
21
- trains the model, scores it with eval.py (the same harness as tinynext v1 and SmolLM2), exports ONNX with a
22
- key/value cache for the browser, and uploads the lot to the model repo under v2/. Training curves, throughput
23
- and GPU use go to a Trackio dashboard.
24
-
25
- hf jobs uv run --namespace huggingface --flavor a100-large --secrets HF_TOKEN train.py
26
- hf jobs uv run --namespace huggingface --flavor a10g-small --secrets HF_TOKEN train.py --smoke --no-push
27
-
28
- The data is prepared on every CPU core before training starts, and the whole token array then sits in GPU
29
- memory, so the GPU never waits on Python between steps.
30
- """
31
-
32
- import argparse
33
- import importlib.util
34
- import json
35
- import math
36
- import os
37
- import random
38
- import shutil
39
- import sys
40
- import time
41
- from pathlib import Path
42
-
43
- import numpy as np
44
- import torch
45
- import torch.nn as nn
46
- import torch.nn.functional as F
47
-
48
- HERE = Path(__file__).parent
49
- SPECIAL = ["<|endoftext|>", "<|pre|>", "<|suf|>", "<|mid|>"]
50
- EOT, PRE, SUF, MID = range(4)
51
-
52
- FINEWEB = "hf://datasets/HuggingFaceFW/fineweb-edu/sample/10BT/{:03d}_00000.parquet"
53
- SMOLTALK = "hf://datasets/HuggingFaceTB/smoltalk/data/all/train-{:05d}-of-00009.parquet"
54
- ENRON = "hf://datasets/corbt/enron-emails/data/train-{:05d}-of-00003.parquet"
55
-
56
-
57
- def cpus() -> int:
58
- return len(os.sched_getaffinity(0)) if hasattr(os, "sched_getaffinity") else os.cpu_count() or 1
59
-
60
-
61
- # ---- Shared eval code ------------------------------------------------------------------------------------------
62
-
63
-
64
- def load_eval_module(repo: str, folder: str):
65
- """Uses eval.py and eval_set.json next to this script, or fetches them from the repo, so every model is scored
66
- by one implementation on the same text. Registered as a module so worker processes can use it too."""
67
- path = HERE / "eval.py"
68
- if not path.exists():
69
- from huggingface_hub import hf_hub_download
70
-
71
- for name in ("eval.py", "eval_set.json"):
72
- shutil.copy(hf_hub_download(repo, f"{folder}/{name}"), HERE / name)
73
- spec = importlib.util.spec_from_file_location("tinynext_eval", path)
74
- module = importlib.util.module_from_spec(spec)
75
- sys.modules["tinynext_eval"] = module
76
- spec.loader.exec_module(module)
77
- return module
78
-
79
-
80
- # ---- Data ------------------------------------------------------------------------------------------------------
81
-
82
-
83
- def to_ascii(text: str) -> str:
84
- """The browser model only sees keyboard characters, so it trains on the same."""
85
- import tinynext_eval as ev
86
-
87
- return text.translate(ev.SMART_CHARS).encode("ascii", "ignore").decode().strip()
88
-
89
-
90
- def smoltalk_text(batch):
91
- return {"text": [to_ascii("\n\n".join(m["content"] for m in turns if m["role"] in ("user", "assistant"))) for turns in batch["messages"]]}
92
-
93
-
94
- def enron_text(batch):
95
- """Training senders only: the eval's held-out senders and enron-autocomplete's validation senders are skipped."""
96
- import hashlib
97
-
98
- import tinynext_eval as ev
99
-
100
- texts = []
101
- for sender, body in zip(batch["from"], batch["body"]):
102
- sender = (sender or "").lower()
103
- keep = "@enron.com" in sender and not ev.BULK_SENDER.search(sender)
104
- keep = keep and int(hashlib.sha1(sender.encode()).hexdigest(), 16) % 100 >= 10
105
- texts.append(to_ascii("\n\n".join(ev.clean_email(body or ""))) if keep else "")
106
- return {"text": texts}
107
-
108
-
109
- # Byte-level BPE with an 8K vocabulary averages a little over 4 characters per token on English. Reading 40% more
110
- # text than that covers the variance, and anything short gets repeated (and logged) in flatten().
111
- CHARS_PER_TOKEN = 4.0
112
- TEXT_MARGIN = 1.4
113
-
114
-
115
- def enough_rows(ds, budget_tokens: int, lengths: np.ndarray, seed: int):
116
- """A random subset of rows whose text adds up to roughly the token budget, so only that much gets cleaned."""
117
- order = np.random.default_rng(seed).permutation(len(ds))
118
- needed = np.searchsorted(np.cumsum(lengths[order]), budget_tokens * CHARS_PER_TOKEN * TEXT_MARGIN) + 1
119
- return ds.select(np.sort(order[:needed]))
120
-
121
-
122
- def load_sources(args, budgets: dict) -> dict:
123
- """Downloads parquet files, keeps only as many documents as each source's budget needs, and cleans them on
124
- every core."""
125
- import pyarrow.compute as pc
126
- from datasets import load_dataset
127
-
128
- procs = cpus()
129
- fineweb = load_dataset("parquet", data_files=[FINEWEB.format(i) for i in range(args.fineweb_files)], split="train")
130
- fineweb = fineweb.select_columns(["text"])
131
- fineweb = enough_rows(fineweb, budgets["fineweb"], pc.utf8_length(fineweb.data.column("text")).to_numpy(), seed=0)
132
- fineweb = fineweb.map(lambda b: {"text": [to_ascii(t) for t in b["text"]]}, batched=True, num_proc=procs)
133
- smoltalk = load_dataset("parquet", data_files=[SMOLTALK.format(i) for i in range(args.smoltalk_files)], split="train")
134
- sample = smoltalk.shuffle(seed=0).select(range(min(2000, len(smoltalk))))
135
- average = np.mean([sum(len(m["content"]) for m in row["messages"]) for row in sample])
136
- smoltalk = enough_rows(smoltalk, budgets["smoltalk"], np.full(len(smoltalk), average), seed=1)
137
- smoltalk = smoltalk.map(smoltalk_text, batched=True, num_proc=procs, remove_columns=smoltalk.column_names)
138
- enron = load_dataset("parquet", data_files=[ENRON.format(i) for i in range(3)], split="train")
139
- enron = enron.map(enron_text, batched=True, num_proc=procs, remove_columns=enron.column_names)
140
- sources = {"fineweb": fineweb, "smoltalk": smoltalk, "enron": enron}
141
- return {name: ds.filter(lambda b: [len(t) >= 40 for t in b["text"]], batched=True, num_proc=procs) for name, ds in sources.items()}
142
-
143
-
144
- def train_tokenizer(sources: dict, weights: dict, vocab: int, sample_docs: int):
145
- from tokenizers import Tokenizer, decoders, models, pre_tokenizers, trainers
146
-
147
- def sample():
148
- for name, weight in weights.items():
149
- ds = sources[name].shuffle(seed=0)
150
- for row in ds.select(range(min(len(ds), int(sample_docs * weight)))):
151
- yield row["text"]
152
-
153
- tokenizer = Tokenizer(models.BPE())
154
- tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
155
- tokenizer.decoder = decoders.ByteLevel()
156
- trainer = trainers.BpeTrainer(vocab_size=vocab, special_tokens=SPECIAL, min_frequency=2,
157
- initial_alphabet=pre_tokenizers.ByteLevel.alphabet())
158
- tokenizer.train_from_iterator(sample(), trainer=trainer)
159
- return tokenizer
160
-
161
-
162
- def fim(ids: list[int], rng: random.Random, max_middle: int, max_suffix: int, max_prefix: int) -> list[int]:
163
- """Suffix first, then prefix, then the middle, so typing at the cursor only appends to the prompt."""
164
- if len(ids) < 8:
165
- return ids + [EOT]
166
- start = rng.randint(1, len(ids) - 2)
167
- end = min(len(ids), start + rng.randint(1, max_middle))
168
- prefix, middle, suffix = ids[max(0, start - max_prefix):start], ids[start:end], ids[end:end + max_suffix]
169
- if rng.random() < 0.25:
170
- suffix = [] # also learn the plain "nothing after the cursor" case in this format
171
- return [SUF, *suffix, PRE, *prefix, MID, *middle, EOT]
172
-
173
-
174
- def make_encoder(tokenizer_json: str, seq: int, fim_rate: float):
175
- """Tokenizes a batch and turns each document into training pieces: plain chunks, or fill-in-the-middle examples."""
176
-
177
- def encode(batch, indices):
178
- from tokenizers import Tokenizer
179
-
180
- tokenizer = Tokenizer.from_str(tokenizer_json)
181
- rng = random.Random(indices[0])
182
- out = []
183
- for encoding in tokenizer.encode_batch(batch["text"]):
184
- ids, pieces = encoding.ids, []
185
- for at in range(0, len(ids), seq - 8):
186
- chunk = ids[at: at + seq - 8]
187
- pieces += fim(chunk, rng, 24, 64, seq - 100) if rng.random() < fim_rate else chunk + [EOT]
188
- out.append(pieces)
189
- return {"tokens": out}
190
-
191
- return encode
192
-
193
-
194
- def flatten(ds, budget: int) -> np.ndarray:
195
- """All of a source's tokens as one array, cut to its share of the budget (repeated if the source is small)."""
196
- import pyarrow.compute as pc
197
-
198
- column = ds.data.column("tokens")
199
- tokens = pc.list_flatten(column).to_numpy().astype(np.uint16)
200
- if len(tokens) < budget:
201
- print(f" only {len(tokens) / 1e6:.0f}M tokens, repeating to reach {budget / 1e6:.0f}M", flush=True)
202
- tokens = np.tile(tokens, math.ceil(budget / len(tokens)))
203
- return tokens[:budget]
204
-
205
-
206
- def build_rows(sources: dict, tokenizer, weights: dict, args) -> tuple[np.ndarray, np.ndarray, dict]:
207
- encode = make_encoder(tokenizer.to_str(), args.seq, args.fim_rate)
208
- train_parts, val_parts, counts = [], [], {}
209
- for name, weight in weights.items():
210
- started = time.time()
211
- split = sources[name].train_test_split(test_size=0.002, seed=0)
212
- encoded = {part: split[part].map(encode, batched=True, batch_size=512, with_indices=True, num_proc=cpus(),
213
- remove_columns=["text"]) for part in ("train", "test")}
214
- budget = int(args.tokens * weight)
215
- train_parts.append(flatten(encoded["train"], budget))
216
- val_parts.append(flatten(encoded["test"], int(args.val_tokens * weight)))
217
- counts[name] = {"docs": len(split["train"]), "train_tokens": int(len(train_parts[-1]))}
218
- print(f" {name}: {len(split['train']):,} docs → {len(train_parts[-1]) / 1e6:.0f}M tokens in {time.time() - started:.0f}s", flush=True)
219
-
220
- def rows(parts):
221
- tokens = np.concatenate(parts)
222
- count = len(tokens) // (args.seq + 1)
223
- return tokens[: count * (args.seq + 1)].reshape(count, args.seq + 1)
224
-
225
- return rows(train_parts), rows(val_parts), counts
226
-
227
-
228
- # ---- Model -----------------------------------------------------------------------------------------------------
229
-
230
-
231
- class RMSNorm(nn.Module):
232
- def __init__(self, dim: int):
233
- super().__init__()
234
- self.weight = nn.Parameter(torch.ones(dim))
235
-
236
- def forward(self, x):
237
- return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + 1e-6) * self.weight
238
-
239
-
240
- def rotate(x, cos, sin):
241
- half = x.shape[-1] // 2
242
- x1, x2 = x[..., :half], x[..., half:]
243
- return torch.cat([x1 * cos - x2 * sin, x2 * cos + x1 * sin], dim=-1)
244
-
245
-
246
- class Block(nn.Module):
247
- def __init__(self, dim: int, heads: int, ffn: int):
248
- super().__init__()
249
- self.heads, self.head_dim = heads, dim // heads
250
- self.norm1, self.norm2 = RMSNorm(dim), RMSNorm(dim)
251
- self.qkv = nn.Linear(dim, 3 * dim, bias=False)
252
- self.out = nn.Linear(dim, dim, bias=False)
253
- self.gate_up = nn.Linear(dim, 2 * ffn, bias=False)
254
- self.down = nn.Linear(ffn, dim, bias=False)
255
-
256
- def forward(self, x, cos, sin, past_k, past_v, mask):
257
- batch, length, _ = x.shape
258
- q, k, v = self.qkv(self.norm1(x)).view(batch, length, 3, self.heads, self.head_dim).unbind(2)
259
- q, k, v = rotate(q.transpose(1, 2), cos, sin), rotate(k.transpose(1, 2), cos, sin), v.transpose(1, 2)
260
- if past_k is not None:
261
- k, v = torch.cat([past_k, k], dim=2), torch.cat([past_v, v], dim=2)
262
- if mask is None:
263
- attended = F.scaled_dot_product_attention(q, k, v, is_causal=True)
264
- else:
265
- attended = F.scaled_dot_product_attention(q, k, v, attn_mask=mask)
266
- x = x + self.out(attended.transpose(1, 2).reshape(batch, length, -1))
267
- gate, up = self.gate_up(self.norm2(x)).chunk(2, dim=-1)
268
- return x + self.down(F.silu(gate) * up), k, v
269
-
270
-
271
- class TinyNext(nn.Module):
272
- def __init__(self, vocab: int, dim: int, layers: int, heads: int, ffn: int):
273
- super().__init__()
274
- self.config = {"vocab": vocab, "dim": dim, "layers": layers, "heads": heads, "ffn": ffn}
275
- self.embed = nn.Embedding(vocab, dim)
276
- self.blocks = nn.ModuleList(Block(dim, heads, ffn) for _ in range(layers))
277
- self.norm = RMSNorm(dim)
278
- self.head = None # set only for export: an untied copy of the output weights, so int8 quantization covers it
279
- self.head_dim = dim // heads
280
- inverse = 1.0 / (10000 ** (torch.arange(0, self.head_dim, 2).float() / self.head_dim))
281
- self.register_buffer("inverse_frequency", inverse, persistent=False)
282
- nn.init.normal_(self.embed.weight, std=0.02)
283
-
284
- def forward(self, ids, past_k=None, past_v=None):
285
- """ids: [batch, length]. past_k/past_v: [layers, batch, heads, past, head_dim] or None.
286
- Returns logits for every position and the updated cache."""
287
- past = 0 if past_k is None else past_k.shape[3]
288
- length = ids.shape[1]
289
- positions = torch.arange(length, device=ids.device) + past
290
- angles = positions[:, None].float() * self.inverse_frequency[None, :]
291
- cos, sin = angles.cos()[None, None], angles.sin()[None, None]
292
- mask = None
293
- if past_k is not None:
294
- keys = torch.arange(past + length, device=ids.device)
295
- mask = keys[None, :] <= positions[:, None]
296
- x = self.embed(ids)
297
- new_k, new_v = [], []
298
- for index, block in enumerate(self.blocks):
299
- x, k, v = block(x, cos, sin, None if past_k is None else past_k[index], None if past_v is None else past_v[index], mask)
300
- new_k.append(k)
301
- new_v.append(v)
302
- logits = self.norm(x) @ (self.embed.weight.T if self.head is None else self.head)
303
- return logits, torch.stack(new_k), torch.stack(new_v)
304
-
305
-
306
- class BrowserStep(nn.Module):
307
- """The ONNX graph: always takes a cache (possibly empty) and returns only the last position's logits."""
308
-
309
- def __init__(self, model: TinyNext):
310
- super().__init__()
311
- self.model = model
312
-
313
- def forward(self, ids, past_k, past_v):
314
- logits, k, v = self.model(ids, past_k, past_v)
315
- return logits[:, -1], k, v
316
-
317
-
318
- # ---- Training --------------------------------------------------------------------------------------------------
319
-
320
-
321
- class GpuMonitor:
322
- """Reads GPU utilization and memory through NVML, so the logs show whether the GPU is actually busy."""
323
-
324
- def __init__(self):
325
- try:
326
- import pynvml
327
-
328
- pynvml.nvmlInit()
329
- self.nvml, self.handle = pynvml, pynvml.nvmlDeviceGetHandleByIndex(0)
330
- except Exception as error: # no NVIDIA GPU (a laptop smoke run): report nothing rather than fail
331
- print(f"GPU monitoring off: {error}", flush=True)
332
- self.nvml = None
333
-
334
- def read(self) -> dict:
335
- if not self.nvml:
336
- return {}
337
- rates = self.nvml.nvmlDeviceGetUtilizationRates(self.handle)
338
- memory = self.nvml.nvmlDeviceGetMemoryInfo(self.handle)
339
- return {"gpu_util_percent": rates.gpu, "gpu_memory_gb": round(memory.used / 1e9, 1)}
340
-
341
-
342
- def evaluate_loss(model, rows: torch.Tensor, device, batch: int) -> float:
343
- model.eval()
344
- losses = []
345
- with torch.no_grad(), torch.autocast(device.type, dtype=torch.bfloat16, enabled=device.type == "cuda"):
346
- for at in range(0, len(rows), batch):
347
- chunk = rows[at: at + batch].long()
348
- logits, _, _ = model(chunk[:, :-1])
349
- losses.append(F.cross_entropy(logits.float().flatten(0, 1), chunk[:, 1:].flatten()).item())
350
- model.train()
351
- return float(np.mean(losses))
352
-
353
-
354
- def train(model, rows: torch.Tensor, val_rows: torch.Tensor, args, device, tracker) -> list[dict]:
355
- steps = int(args.epochs * len(rows) // args.batch)
356
- decay = [p for p in model.parameters() if p.dim() >= 2]
357
- no_decay = [p for p in model.parameters() if p.dim() < 2]
358
- optimizer = torch.optim.AdamW([{"params": decay, "weight_decay": 0.1}, {"params": no_decay, "weight_decay": 0.0}],
359
- lr=args.lr, betas=(0.9, 0.95), fused=device.type == "cuda")
360
- warmup = max(1, steps // 50)
361
- schedule = lambda step: min(1, step / warmup) * (0.1 + 0.9 * 0.5 * (1 + math.cos(math.pi * min(1, step / steps))))
362
- scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, schedule)
363
- compiled = torch.compile(model) if device.type == "cuda" else model
364
- parameters = sum(p.numel() for p in model.parameters())
365
- gpu, history = GpuMonitor(), []
366
- generator = torch.Generator(device=device).manual_seed(0)
367
- window_started, window_tokens, started = time.time(), 0, time.time()
368
- print(f"training {steps:,} steps of {args.batch * args.seq:,} tokens", flush=True)
369
- for step in range(steps):
370
- index = torch.randint(0, len(rows), (args.batch,), device=device, generator=generator)
371
- chunk = rows[index].long()
372
- with torch.autocast(device.type, dtype=torch.bfloat16, enabled=device.type == "cuda"):
373
- logits, _, _ = compiled(chunk[:, :-1])
374
- loss = F.cross_entropy(logits.float().flatten(0, 1), chunk[:, 1:].flatten())
375
- optimizer.zero_grad(set_to_none=True)
376
- loss.backward()
377
- torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
378
- optimizer.step()
379
- scheduler.step()
380
- window_tokens += args.batch * args.seq
381
- if step % args.log_every == 0 or step == steps - 1:
382
- loss_value = loss.item() # syncs the GPU, so throughput below is real
383
- seconds = time.time() - window_started
384
- tokens_per_second = window_tokens / max(seconds, 1e-9)
385
- entry = {
386
- "step": step, "train_loss": round(loss_value, 4), "lr": round(scheduler.get_last_lr()[0], 6),
387
- "tokens_per_second": round(tokens_per_second), "minutes": round((time.time() - started) / 60, 2),
388
- # Training compute is about 6 FLOPs per parameter per token; an A100 does 312 TFLOP/s in bf16.
389
- "mfu_percent": round(100 * 6 * parameters * tokens_per_second / 312e12, 1), **gpu.read(),
390
- }
391
- if step % (args.log_every * 10) == 0 or step == steps - 1:
392
- entry["val_loss"] = round(evaluate_loss(model, val_rows, device, args.batch), 4)
393
- history.append(entry)
394
- tracker.log(entry, step=step)
395
- print(json.dumps(entry), flush=True)
396
- window_started, window_tokens = time.time(), 0
397
- return history
398
-
399
-
400
- # ---- Eval, export --------------------------------------------------------------------------------------------
401
-
402
-
403
- def as_token_lm(ev, name: str, model: TinyNext, tokenizer, device, fim: bool = True):
404
- texts = [tokenizer.decode([i], skip_special_tokens=False) if i >= len(SPECIAL) else "" for i in range(tokenizer.get_vocab_size())]
405
-
406
- @torch.no_grad()
407
- def next_logits(ids, cache):
408
- past_k, past_v = cache if cache else (None, None)
409
- logits, k, v = model(torch.tensor([ids], device=device), past_k, past_v)
410
- return logits[0, -1].float().cpu().numpy(), (k, v)
411
-
412
- encode = lambda text: tokenizer.encode(text).ids or [EOT]
413
- # A model trained without fill-in-the-middle never saw the special tokens, so it only gets the text before.
414
- prompt = (lambda prefix, suffix: prefix if not suffix else [SUF, *suffix, PRE, *prefix, MID]) if fim else None
415
- return ev.TokenLM(name, next_logits, encode, texts, set(range(len(SPECIAL))), prompt=prompt)
416
-
417
-
418
- def parity_prompts(ev, tokenizer, count: int = 300) -> list[list[int]]:
419
- """Real text from the eval set, cut at random points, as token prompts."""
420
- rng = random.Random(0)
421
- texts = [p for domain in ev.load_eval_set().values() for doc in domain for p in doc]
422
- prompts = []
423
- for text in rng.sample(texts, min(count, len(texts))):
424
- ids = tokenizer.encode(text[: rng.randint(40, len(text))]).ids[-300:]
425
- if len(ids) >= 4:
426
- prompts.append(ids)
427
- return prompts
428
-
429
-
430
- def greedy_tokens(step, ids: list[int], empty, steps: int) -> list[int]:
431
- """Prompt, then `steps` cached greedy steps; returns the top token at each point."""
432
- logits, k, v = step(np.array([ids]), empty, empty)
433
- tops = [int(logits.argmax())]
434
- for _ in range(steps):
435
- logits, k, v = step(np.array([[tops[-1]]]), k, v)
436
- tops.append(int(logits.argmax()))
437
- return tops
438
-
439
-
440
- def export(model: TinyNext, output: Path, device, prompts: list[list[int]]) -> dict:
441
- """Float and int8 ONNX for the browser, checked against PyTorch on real prompts over several cached steps."""
442
- import onnxruntime as ort
443
- from onnxruntime.quantization import QuantType, quantize_dynamic
444
-
445
- model = model.float().eval().to("cpu")
446
- model.head = nn.Parameter(model.embed.weight.detach().T.contiguous().clone())
447
- cfg = model.config
448
- head_dim = cfg["dim"] // cfg["heads"]
449
- empty = np.zeros((cfg["layers"], 1, cfg["heads"], 0, head_dim), np.float32)
450
- # Trace with a non-empty cache so no shape gets fixed at zero; the checks below start from an empty one.
451
- with torch.no_grad():
452
- _, trace_k, trace_v = model(torch.tensor([[1, 2]]))
453
- float_path, int8_path = output / "model.onnx", output / "model_int8.onnx"
454
- torch.onnx.export(
455
- BrowserStep(model), (torch.tensor([[5, 6, 7]]), trace_k, trace_v), float_path, opset_version=17,
456
- input_names=["input_ids", "past_k", "past_v"], output_names=["logits", "present_k", "present_v"],
457
- dynamic_axes={"input_ids": {1: "length"}, "past_k": {3: "past"}, "past_v": {3: "past"},
458
- "present_k": {3: "total"}, "present_v": {3: "total"}},
459
- dynamo=False,
460
- )
461
- quantize_dynamic(float_path, int8_path, weight_type=QuantType.QInt8, op_types_to_quantize=["MatMul", "Gather"], per_channel=True)
462
-
463
- @torch.no_grad()
464
- def torch_step(ids, k, v):
465
- past = None if k.shape[3] == 0 else (torch.from_numpy(k), torch.from_numpy(v))
466
- logits, nk, nv = model(torch.from_numpy(ids), *(past or (None, None)))
467
- return logits[0, -1].numpy(), nk.numpy(), nv.numpy()
468
-
469
- expected = [greedy_tokens(torch_step, ids, empty, 4) for ids in prompts]
470
- report = {"parity_prompts": len(prompts), "parity_steps_per_prompt": 5}
471
- for name, path in (("float", float_path), ("int8", int8_path)):
472
- session = ort.InferenceSession(str(path), providers=["CPUExecutionProvider"])
473
- onnx_step = lambda ids, k, v: (lambda out: (out[0][0], out[1], out[2]))(
474
- session.run(None, {"input_ids": ids.astype(np.int64), "past_k": k, "past_v": v}))
475
- got = [greedy_tokens(onnx_step, ids, empty, 4) for ids in prompts]
476
- first = np.mean([g[0] == e[0] for g, e in zip(got, expected)])
477
- all_steps = np.mean([g == e for g, e in zip(got, expected)])
478
- _, pk, pv = onnx_step(np.array([prompts[0]]), empty, empty)
479
- timings = []
480
- for _ in range(200):
481
- began = time.perf_counter()
482
- onnx_step(np.array([[8]]), pk, pv)
483
- timings.append((time.perf_counter() - began) * 1000)
484
- report[name] = {
485
- "megabytes": round(path.stat().st_size / 1e6, 2),
486
- "same_first_token": round(float(first), 4),
487
- "same_five_greedy_tokens": round(float(all_steps), 4),
488
- "cached_step_ms_p50_cpu": round(float(np.median(timings)), 3),
489
- }
490
- model.head = None
491
- model.to(device)
492
- return report
493
-
494
-
495
- def headline(scored: dict) -> dict:
496
- """The few eval numbers worth a chart: typing saved and 2+ word suggestions at the app's cutoff."""
497
- table = scored["cutoffs"]["0.5"]
498
- out = {}
499
- for key, m in table.items():
500
- slug = key.replace("/", "_")
501
- out[f"eval/{slug}/saved_with_tab"] = m["saved_with_tab"]
502
- out[f"eval/{slug}/right"] = m["right"]
503
- out[f"eval/{slug}/multiword_shown"] = m["multiword_shown"]
504
- return out
505
-
506
-
507
- # ---- Prepared data ---------------------------------------------------------------------------------------------
508
-
509
-
510
- def data_key(args) -> str:
511
- """Prepared data depends only on these settings, so a training run can find the matching files."""
512
- return f"{args.name}-v{args.vocab}-s{args.seq}-t{int(args.tokens / 1e6)}M-fim{args.fim_rate}-{args.mix}".replace(",", "_").replace("=", "")
513
-
514
-
515
- def prepare(args, weights: dict, output: Path):
516
- budgets = {name: int((args.tokens + args.val_tokens) * weight) for name, weight in weights.items()}
517
- started = time.time()
518
- sources = load_sources(args, budgets)
519
- print(f"sources ready in {time.time() - started:.0f}s: " + ", ".join(f"{n} {len(d):,} docs" for n, d in sources.items()), flush=True)
520
- tokenizer = train_tokenizer(sources, weights, args.vocab, args.tokenizer_docs)
521
- tokenizer.save(str(output / "tokenizer.json"))
522
- rows, val_rows, counts = build_rows(sources, tokenizer, weights, args)
523
- return tokenizer, rows, val_rows, counts
524
-
525
-
526
- def upload_prepared(args, output: Path, rows: np.ndarray, val_rows: np.ndarray, counts: dict, minutes: float):
527
- from huggingface_hub import HfApi
528
-
529
- folder = output / "data"
530
- folder.mkdir(exist_ok=True)
531
- rows.astype(np.uint16).tofile(folder / "train.bin")
532
- val_rows.astype(np.uint16).tofile(folder / "val.bin")
533
- shutil.copy(output / "tokenizer.json", folder / "tokenizer.json")
534
- meta = {"seq": args.seq, "train_rows": len(rows), "val_rows": len(val_rows), "counts": counts, "minutes": round(minutes, 1), "args": vars(args)}
535
- (folder / "meta.json").write_text(json.dumps(meta, indent=1))
536
- api = HfApi(token=os.environ.get("HF_TOKEN"))
537
- api.create_repo(args.data_repo, repo_type="dataset", private=True, exist_ok=True)
538
- api.upload_folder(folder_path=str(folder), repo_id=args.data_repo, repo_type="dataset", path_in_repo=data_key(args),
539
- commit_message=f"prepared data: {data_key(args)}")
540
- print(f"Prepared data at https://huggingface.co/datasets/{args.data_repo}/tree/main/{data_key(args)}", flush=True)
541
-
542
-
543
- def download_prepared(args, output: Path):
544
- from huggingface_hub import snapshot_download
545
- from tokenizers import Tokenizer
546
-
547
- local = Path(snapshot_download(args.data_repo, repo_type="dataset", allow_patterns=[f"{data_key(args)}/*"], max_workers=16))
548
- folder = local / data_key(args)
549
- meta = json.loads((folder / "meta.json").read_text())
550
- shutil.copy(folder / "tokenizer.json", output / "tokenizer.json")
551
- rows = np.fromfile(folder / "train.bin", dtype=np.uint16).reshape(meta["train_rows"], meta["seq"] + 1)
552
- val_rows = np.fromfile(folder / "val.bin", dtype=np.uint16).reshape(meta["val_rows"], meta["seq"] + 1)
553
- return Tokenizer.from_file(str(output / "tokenizer.json")), rows, val_rows, meta["counts"]
554
-
555
-
556
- # ---- Main ------------------------------------------------------------------------------------------------------
557
-
558
-
559
- def parse_args():
560
- parser = argparse.ArgumentParser()
561
- parser.add_argument("--vocab", type=int, default=8192)
562
- parser.add_argument("--dim", type=int, default=320)
563
- parser.add_argument("--layers", type=int, default=8)
564
- parser.add_argument("--heads", type=int, default=5)
565
- parser.add_argument("--ffn", type=int, default=864)
566
- parser.add_argument("--seq", type=int, default=512)
567
- parser.add_argument("--tokens", type=float, default=1.5e9, help="Training tokens")
568
- parser.add_argument("--val-tokens", type=float, default=4e6)
569
- parser.add_argument("--epochs", type=float, default=1.0)
570
- parser.add_argument("--batch", type=int, default=512)
571
- parser.add_argument("--lr", type=float, default=3e-3)
572
- parser.add_argument("--fim-rate", type=float, default=0.5)
573
- parser.add_argument("--mix", default="fineweb=0.6,smoltalk=0.3,enron=0.1")
574
- parser.add_argument("--fineweb-files", type=int, default=2, help="Each is about 2 GB of text, roughly 0.9B tokens")
575
- parser.add_argument("--smoltalk-files", type=int, default=9)
576
- parser.add_argument("--tokenizer-docs", type=int, default=200_000)
577
- parser.add_argument("--eval-pauses", type=int, default=1000)
578
- parser.add_argument("--log-every", type=int, default=50)
579
- parser.add_argument("--repo", default="cfahlgren1/tinynext")
580
- parser.add_argument("--folder", default="v2", help="Where this run's outputs are uploaded")
581
- parser.add_argument("--eval-folder", default="v2", help="Where the shared eval.py and eval_set.json live")
582
- parser.add_argument("--name", default="tinynext-v2")
583
- parser.add_argument("--trackio-space", default="cfahlgren1/tinynext-trackio")
584
- parser.add_argument("--stage", choices=("all", "prepare", "train"), default="all",
585
- help="prepare: build the tokenizer and token arrays on a CPU job and save them to --data-repo. "
586
- "train: download them and train on the GPU. all: both in one job.")
587
- parser.add_argument("--data-repo", default="cfahlgren1/tinynext-data")
588
- parser.add_argument("--smoke", action="store_true", help="Tiny settings to check the pipeline end to end")
589
- parser.add_argument("--no-push", action="store_true")
590
- args = parser.parse_args()
591
- if args.smoke:
592
- args.vocab, args.dim, args.layers, args.heads, args.ffn, args.seq = 2048, 64, 2, 2, 128, 256
593
- args.tokens, args.val_tokens, args.batch, args.tokenizer_docs = 5e6, 2e5, 64, 5000
594
- args.fineweb_files, args.smoltalk_files, args.eval_pauses, args.log_every = 1, 1, 20, 10
595
- args.name = "tinynext-v2-smoke"
596
- return args
597
-
598
-
599
- class NoTracker:
600
- def log(self, *_, **__):
601
- pass
602
-
603
- def finish(self):
604
- pass
605
-
606
-
607
- def start_tracker(args):
608
- if args.no_push and not os.environ.get("HF_TOKEN"):
609
- return NoTracker()
610
- import trackio
611
-
612
- trackio.init(project="tinynext", name=args.name, space_id=args.trackio_space, config=vars(args))
613
- return trackio
614
-
615
-
616
- def main():
617
- args = parse_args()
618
- device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu")
619
- torch.manual_seed(0)
620
- torch.backends.cuda.matmul.allow_tf32 = True
621
- torch.backends.cudnn.allow_tf32 = True
622
- output = HERE / "output"
623
- output.mkdir(exist_ok=True)
624
- ev = load_eval_module(args.repo, args.eval_folder)
625
- weights = {k: float(v) for k, v in (part.split("=") for part in args.mix.split(","))}
626
- print(f"device {device}, {cpus()} CPUs, mix {weights}", flush=True)
627
- tracker = start_tracker(args)
628
-
629
- started = time.time()
630
- if args.stage == "train":
631
- tokenizer, rows, val_rows, counts = download_prepared(args, output)
632
- else:
633
- tokenizer, rows, val_rows, counts = prepare(args, weights, output)
634
- data_minutes = (time.time() - started) / 60
635
- print(f"data ready in {data_minutes:.1f} min: {rows.size / 1e6:.0f}M train tokens, {val_rows.size / 1e6:.1f}M val", flush=True)
636
- if args.stage == "prepare":
637
- upload_prepared(args, output, rows, val_rows, counts, data_minutes)
638
- return
639
-
640
- # The whole token array lives on the GPU; each step just indexes into it.
641
- rows_gpu = torch.from_numpy(rows.astype(np.int32)).to(device)
642
- val_gpu = torch.from_numpy(val_rows.astype(np.int32)).to(device)
643
- model = TinyNext(tokenizer.get_vocab_size(), args.dim, args.layers, args.heads, args.ffn).to(device)
644
- parameters = sum(p.numel() for p in model.parameters())
645
- print(f"{parameters / 1e6:.2f}M parameters", flush=True)
646
- started = time.time()
647
- history = train(model, rows_gpu, val_gpu, args, device, tracker)
648
- train_minutes = (time.time() - started) / 60
649
-
650
- model.eval()
651
- from safetensors.torch import save_file
652
-
653
- save_file({k: v.contiguous() for k, v in model.state_dict().items()}, output / "model.safetensors")
654
- scored = ev.score(as_token_lm(ev, args.name, model, tokenizer, device, fim=args.fim_rate > 0), ev.pauses(ev.load_eval_set(), args.eval_pauses))
655
- (output / "metrics").mkdir(exist_ok=True)
656
- (output / "metrics" / f"{args.name}.json").write_text(json.dumps(scored, indent=1))
657
- tracker.log(headline(scored))
658
- exported = export(model, output, device, parity_prompts(ev, tokenizer))
659
-
660
- config = {
661
- **model.config, "parameters": parameters, "seq": args.seq, "special_tokens": dict(zip(SPECIAL, range(len(SPECIAL)))),
662
- "prompt": "No text after the cursor: the text before it. Otherwise: <|suf|> after <|pre|> before <|mid|>.",
663
- }
664
- (output / "config.json").write_text(json.dumps(config, indent=1))
665
- report = {"args": vars(args), "parameters": parameters, "data": counts, "data_minutes": round(data_minutes, 1),
666
- "train_minutes": round(train_minutes, 1), "history": history, "exports": exported}
667
- (output / "report.json").write_text(json.dumps(report, indent=1))
668
- print(json.dumps(exported, indent=1))
669
- print(ev.table([output / "metrics" / f"{args.name}.json"]))
670
- tracker.finish()
671
-
672
- for name in ("train.py", "eval.py", "eval_set.json"):
673
- shutil.copy(HERE / name, output / name)
674
- if (HERE / "metrics").exists():
675
- for path in (HERE / "metrics").glob("*.json"):
676
- if not (output / "metrics" / path.name).exists():
677
- shutil.copy(path, output / "metrics" / path.name)
678
- if args.no_push:
679
- print(f"Skipping upload; everything is in {output}")
680
- return
681
- from huggingface_hub import HfApi
682
-
683
- HfApi(token=os.environ.get("HF_TOKEN")).upload_folder(
684
- folder_path=str(output), repo_id=args.repo, path_in_repo=args.folder, repo_type="model",
685
- commit_message=f"{args.name}: {parameters / 1e6:.1f}M params, {train_minutes:.0f} min on GPU",
686
- )
687
- print(f"Uploaded to https://huggingface.co/{args.repo}/tree/main/{args.folder}")
688
-
689
-
690
- if __name__ == "__main__":
691
- main()