JinghuiLuAstronaut commited on
Commit
0badcf2
·
verified ·
1 Parent(s): 9cfc8ba

Add files using upload-large-folder tool

Browse files
Files changed (20) hide show
  1. LTA_openwebtext_dualt/scripts/_tmp_flowtext_decode_lab_nospecial_prompt.py +484 -0
  2. LTA_openwebtext_dualt/scripts/eval_lm1b_linear_simplex_genppl.py +314 -0
  3. LTA_openwebtext_dualt/scripts/eval_train8_overfit_sweep.sh +54 -0
  4. LTA_openwebtext_dualt/scripts/launch_ar_openwebtext_duo_small_8gpu_1m.sh +99 -0
  5. LTA_openwebtext_dualt/scripts/launch_lm1b_flm_8gpu_repro_20260506.sh +123 -0
  6. LTA_openwebtext_dualt/scripts/launch_lta_lm1b_categorical_fullvocab_c1024_gaussian_linear_mean_fullycoupled_8gpu_small_1m.sh +156 -0
  7. LTA_openwebtext_dualt/scripts/launch_lta_lm1b_compact_gpt2bpe_v8192_len128_fullycoupled_4gpu.sh +219 -0
  8. LTA_openwebtext_dualt/scripts/launch_lta_openwebtext_dualt_8gpu_aligned.sh +113 -0
  9. LTA_openwebtext_dualt/scripts/launch_lta_owt_compact_gpt2bpe_v2048_elfaligned_logitnormal_tokenized_8gpu.sh +34 -0
  10. LTA_openwebtext_dualt/scripts/launch_lta_owt_fullycoupled_logitnormal_mid_mask1_wd0p1_fp32_8gpu.sh +204 -0
  11. LTA_openwebtext_dualt/scripts/launch_lta_owt_t5_adaln_adamw_wd0p1_rollin_grad_k1_rho025_8gpu.sh +168 -0
  12. LTA_openwebtext_dualt/scripts/make_duo_integral_cache.py +77 -0
  13. LTA_openwebtext_dualt/scripts/prepare_elf_wmt14_deen_t5.sh +32 -0
  14. LTA_openwebtext_dualt/scripts/run_lta_lm1b_bert_absrope_time4_dirichlet_len128_C1_to_1024_4gpu_1m_mask1_sameT_save1k.sh +29 -0
  15. LTA_openwebtext_dualt/scripts/run_lta_owt_dirichlet_len1024_Cv_to_2v_4gpu_abspos_specialloss_watch.sh +42 -0
  16. LTA_openwebtext_dualt/scripts/run_lta_owt_dirichlet_len1024_Cv_to_2v_8gpu_save1k_with_gumbel_watch.sh +404 -0
  17. LTA_openwebtext_dualt/scripts/run_lta_owt_t5_len128_uniform10k_then_lognsr_4gpu.sh +60 -0
  18. LTA_openwebtext_dualt/scripts/run_train8_ctx1024_sampleds_sweep_4gpu.sh +282 -0
  19. LTA_openwebtext_dualt/scripts/run_train8_decode_algo_sweep_len256_latest.sh +113 -0
  20. LTA_openwebtext_dualt/scripts/sweep_categorical_c1024_late_refresh_20260506.py +281 -0
LTA_openwebtext_dualt/scripts/_tmp_flowtext_decode_lab_nospecial_prompt.py ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Decode-sweep lab for FlowText OpenWebText checkpoints.
3
+
4
+ The goal is to debug inference without touching training. We try several
5
+ simplex-valid update rules, generate many candidates, and rank them with
6
+ anti-collapse diagnostics instead of pure self-likelihood.
7
+
8
+ Run from the flowtext_standard_bench repository root.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import argparse
14
+ import json
15
+ import math
16
+ import re
17
+ import sys
18
+ from collections import Counter
19
+ from dataclasses import dataclass, asdict
20
+ from pathlib import Path
21
+ from typing import Iterable, List, Sequence
22
+
23
+ import torch
24
+ import torch.nn.functional as F
25
+
26
+ REPO_ROOT = Path(__file__).resolve().parents[1]
27
+ if str(REPO_ROOT) not in sys.path:
28
+ sys.path.insert(0, str(REPO_ROOT))
29
+
30
+ from eval import build_model_from_ckpt
31
+ from flowtext_lab.bridges import smooth_onehot
32
+ from flowtext_lab.decode import model_time_for_step, sample_noise_simplex, state_for_model
33
+ from flowtext_lab.tokenization import BpeTextTokenizer
34
+
35
+
36
+ WORD_RE = re.compile(r"[A-Za-z]+|\d+|[^\sA-Za-z\d]")
37
+
38
+
39
+ @dataclass
40
+ class DecodeConfig:
41
+ label: str
42
+ rule: str
43
+ steps: int = 64
44
+ model_t_mode: str = "flow"
45
+ eta: float = 0.5
46
+ damping: float = 1.0
47
+ max_gamma: float = 1.0
48
+ endpoint_temp: float = 1.0
49
+ state_floor: float = 1e-8
50
+ final_from: str = "state"
51
+ noise_mix: float = 0.0
52
+ noise_decay: str = "linear"
53
+ eos_logit_bias: float = 0.0
54
+
55
+
56
+ def tokenize_for_metrics(text: str) -> list[str]:
57
+ return WORD_RE.findall(text)
58
+
59
+
60
+ def repeated_ngram_frac(tokens: Sequence[str], n: int) -> float:
61
+ if len(tokens) < n:
62
+ return 0.0
63
+ grams = list(zip(*[tokens[i:] for i in range(n)]))
64
+ counts = Counter(grams)
65
+ return sum(v - 1 for v in counts.values() if v > 1) / max(len(grams), 1)
66
+
67
+
68
+ def text_metrics(text: str) -> dict:
69
+ toks = tokenize_for_metrics(text)
70
+ words = [t.lower() for t in toks if re.fullmatch(r"[A-Za-z]+", t)]
71
+ n_tok = max(len(toks), 1)
72
+ n_words = max(len(words), 1)
73
+ word_counts = Counter(words)
74
+ max_word_frac = word_counts.most_common(1)[0][1] / n_words if word_counts else 1.0
75
+ distinct1 = len(set(words)) / n_words if words else 0.0
76
+ bigrams = list(zip(words, words[1:]))
77
+ distinct2 = len(set(bigrams)) / max(len(bigrams), 1) if bigrams else 0.0
78
+ digit_frac = sum(t.isdigit() for t in toks) / n_tok
79
+ punct_frac = sum(bool(re.fullmatch(r"[,.;:!?]+", t)) for t in toks) / n_tok
80
+ eos_count = text.count("<|endoftext|>")
81
+ bad_char_count = text.count("�")
82
+ rep3 = repeated_ngram_frac([t.lower() for t in toks], 3)
83
+ rep4 = repeated_ngram_frac([t.lower() for t in toks], 4)
84
+ # This score is deliberately simple and non-oracle. It rewards length and
85
+ # lexical variety while heavily penalizing classic collapse artifacts.
86
+ quality = (
87
+ min(len(text) / 700.0, 1.0)
88
+ + 0.35 * distinct2
89
+ + 0.15 * distinct1
90
+ - 0.30 * eos_count
91
+ - 2.60 * rep3
92
+ - 1.60 * rep4
93
+ - 1.30 * digit_frac
94
+ - 0.65 * punct_frac
95
+ - 1.35 * max_word_frac
96
+ - 0.35 * bad_char_count
97
+ )
98
+ return {
99
+ "quality": float(quality),
100
+ "chars": len(text),
101
+ "tokens": len(toks),
102
+ "words": len(words),
103
+ "eos_count": eos_count,
104
+ "bad_char_count": bad_char_count,
105
+ "rep3": float(rep3),
106
+ "rep4": float(rep4),
107
+ "distinct1": float(distinct1),
108
+ "distinct2": float(distinct2),
109
+ "digit_frac": float(digit_frac),
110
+ "punct_frac": float(punct_frac),
111
+ "max_word_frac": float(max_word_frac),
112
+ }
113
+
114
+
115
+ def decode_text(tokenizer: BpeTextTokenizer, ids: Sequence[int]) -> str:
116
+ return tokenizer.decode(ids, stop_at_eos=False, skip_special_tokens=False)
117
+
118
+
119
+ def encode_prompt(tokenizer: BpeTextTokenizer, prompt: str, max_len: int) -> list[int]:
120
+ # Prefix-continuation mode: lock [CLS] + prompt tokens, but do NOT lock an early [SEP].
121
+ # tokenizers.Tokenizer.encode(..., add_special_tokens=False) avoids the default BERT wrapper.
122
+ core = list(tokenizer.tokenizer.encode(prompt, add_special_tokens=False).ids)
123
+ bos = tokenizer.bos_id
124
+ ids = ([bos] if bos is not None and bos >= 0 else []) + core
125
+ return ids[:max_len]
126
+
127
+
128
+ @torch.no_grad()
129
+ def build_initial_state(
130
+ tokenizer: BpeTextTokenizer,
131
+ prompts: list[str],
132
+ restarts: int,
133
+ max_len: int,
134
+ target_prob: float,
135
+ eps: float,
136
+ noise_init: str,
137
+ noise_sigma: float,
138
+ dirichlet_init_concentration: float,
139
+ device: torch.device,
140
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor, list[str]]:
141
+ expanded: list[str] = []
142
+ prompt_ids: list[list[int]] = []
143
+ for prompt in prompts:
144
+ ids = encode_prompt(tokenizer, prompt, max_len=max_len)
145
+ for _ in range(restarts):
146
+ expanded.append(prompt)
147
+ prompt_ids.append(ids)
148
+
149
+ batch = len(prompt_ids)
150
+ attn = torch.ones((batch, max_len), dtype=torch.bool, device=device)
151
+ probs = sample_noise_simplex(
152
+ (batch, max_len),
153
+ tokenizer.vocab_size,
154
+ device,
155
+ eps,
156
+ noise_mode=noise_init,
157
+ target_prob=target_prob,
158
+ noise_sigma=noise_sigma,
159
+ dirichlet_concentration=dirichlet_init_concentration,
160
+ )
161
+ lock = torch.zeros((batch, max_len), dtype=torch.bool, device=device)
162
+ lock_probs = torch.zeros((batch, max_len, tokenizer.vocab_size), dtype=torch.float32, device=device)
163
+ for row, ids in enumerate(prompt_ids):
164
+ if not ids:
165
+ continue
166
+ ids_t = torch.tensor(ids, dtype=torch.long, device=device).unsqueeze(0)
167
+ sp = smooth_onehot(ids_t, tokenizer.vocab_size, target_prob, eps)[0]
168
+ probs[row, : len(ids)] = sp
169
+ lock_probs[row, : len(ids)] = sp
170
+ lock[row, : len(ids)] = True
171
+ return probs, attn, lock, lock_probs, expanded
172
+
173
+
174
+ def flowmap_gamma(step: int, steps: int, damping: float, max_gamma: float, eps: float) -> float:
175
+ s = step / max(steps, 1)
176
+ t_next = (step + 1) / max(steps, 1)
177
+ base_gamma = (t_next - s) / max(1.0 - s, eps)
178
+ gamma = float(damping) * base_gamma
179
+ return min(gamma, float(max_gamma)) if max_gamma > 0 else gamma
180
+
181
+
182
+ @torch.no_grad()
183
+ def decode_batch(
184
+ model,
185
+ init_probs: torch.Tensor,
186
+ attn: torch.Tensor,
187
+ lock: torch.Tensor,
188
+ lock_probs: torch.Tensor,
189
+ cfg: DecodeConfig,
190
+ eps: float,
191
+ eos_id: int | None = None,
192
+ ) -> torch.Tensor:
193
+ probs = init_probs.float().clone()
194
+ device = probs.device
195
+ last_endpoint = probs
196
+ for step in range(cfg.steps):
197
+ t = model_time_for_step(cfg.model_t_mode, step, cfg.steps, probs.size(0), device, dtype=torch.float32)
198
+ logits = model(state_for_model(model, probs, eps), t, attn).float()
199
+ if cfg.endpoint_temp != 1.0:
200
+ logits = logits / float(cfg.endpoint_temp)
201
+ if cfg.eos_logit_bias != 0.0 and eos_id is not None and 0 <= eos_id < logits.size(-1):
202
+ logits[..., eos_id] = logits[..., eos_id] + float(cfg.eos_logit_bias)
203
+ endpoint = F.softmax(logits, dim=-1)
204
+ last_endpoint = endpoint
205
+
206
+ if cfg.rule == "flowmap":
207
+ gamma = flowmap_gamma(step, cfg.steps, cfg.damping, cfg.max_gamma, eps)
208
+ new_probs = probs + gamma * (endpoint - probs)
209
+ elif cfg.rule == "replace":
210
+ new_probs = (1.0 - cfg.eta) * probs + cfg.eta * endpoint
211
+ elif cfg.rule == "geometric":
212
+ log_mix = (1.0 - cfg.eta) * torch.log(probs.clamp_min(eps)) + cfg.eta * torch.log(endpoint.clamp_min(eps))
213
+ new_probs = F.softmax(log_mix, dim=-1)
214
+ elif cfg.rule == "centered_residual":
215
+ # Add a zero-sum probability residual, then project back to simplex.
216
+ residual = endpoint - probs
217
+ residual = residual - residual.mean(dim=-1, keepdim=True)
218
+ new_probs = probs + cfg.eta * residual
219
+ else:
220
+ raise ValueError(f"Unknown decode rule: {cfg.rule}")
221
+
222
+ if cfg.noise_mix > 0:
223
+ if cfg.noise_decay == "linear":
224
+ lam = cfg.noise_mix * (1.0 - (step + 1) / max(cfg.steps, 1))
225
+ elif cfg.noise_decay == "sqrt":
226
+ lam = cfg.noise_mix * math.sqrt(max(0.0, 1.0 - (step + 1) / max(cfg.steps, 1)))
227
+ else:
228
+ lam = cfg.noise_mix
229
+ if lam > 0:
230
+ uniform = torch.full_like(new_probs, 1.0 / new_probs.size(-1))
231
+ new_probs = (1.0 - lam) * new_probs + lam * uniform
232
+
233
+ new_probs = new_probs.clamp_min(max(float(cfg.state_floor), eps))
234
+ new_probs = new_probs / new_probs.sum(dim=-1, keepdim=True).clamp_min(eps)
235
+ new_probs = torch.where(lock.unsqueeze(-1), lock_probs, new_probs)
236
+ probs = new_probs
237
+
238
+ if cfg.final_from == "endpoint":
239
+ out = last_endpoint
240
+ out = torch.where(lock.unsqueeze(-1), lock_probs, out)
241
+ return out / out.sum(dim=-1, keepdim=True).clamp_min(eps)
242
+ if cfg.final_from == "blend":
243
+ out = 0.5 * probs + 0.5 * last_endpoint
244
+ out = torch.where(lock.unsqueeze(-1), lock_probs, out)
245
+ return out / out.sum(dim=-1, keepdim=True).clamp_min(eps)
246
+ return probs
247
+
248
+
249
+ @torch.no_grad()
250
+ def pseudo_likelihood_scores(
251
+ model,
252
+ tokenizer: BpeTextTokenizer,
253
+ probs: torch.Tensor,
254
+ attn: torch.Tensor,
255
+ lock: torch.Tensor,
256
+ target_prob: float,
257
+ eps: float,
258
+ repeats: int,
259
+ mask_frac: float,
260
+ rerank_t: float,
261
+ ) -> torch.Tensor:
262
+ ids = probs.argmax(dim=-1)
263
+ endpoint = smooth_onehot(ids, tokenizer.vocab_size, target_prob, eps)
264
+ eligible = attn & (~lock)
265
+ scores = torch.zeros(ids.size(0), dtype=torch.float32, device=ids.device)
266
+ counts = torch.zeros_like(scores)
267
+ for _ in range(max(1, repeats)):
268
+ score_mask = (torch.rand_like(ids.float()) < mask_frac) & eligible
269
+ for row in range(ids.size(0)):
270
+ if eligible[row].any() and not score_mask[row].any():
271
+ choices = torch.nonzero(eligible[row], as_tuple=False).flatten()
272
+ score_mask[row, choices[torch.randint(0, choices.numel(), (1,), device=ids.device)]] = True
273
+ noise = sample_noise_simplex(
274
+ (ids.size(0), ids.size(1)),
275
+ tokenizer.vocab_size,
276
+ ids.device,
277
+ eps,
278
+ noise_mode="logistic_normal",
279
+ target_prob=target_prob,
280
+ noise_sigma=-1.0,
281
+ )
282
+ inp = torch.where(score_mask.unsqueeze(-1), noise, endpoint)
283
+ inp = torch.where(lock.unsqueeze(-1), probs, inp)
284
+ t = torch.full((ids.size(0),), float(rerank_t), dtype=torch.float32, device=ids.device)
285
+ logits = model(state_for_model(model, inp, eps), t, attn).float()
286
+ logp = F.log_softmax(logits, dim=-1).gather(-1, ids.unsqueeze(-1)).squeeze(-1)
287
+ scores += (logp * score_mask.float()).sum(dim=-1)
288
+ counts += score_mask.float().sum(dim=-1)
289
+ return scores / counts.clamp_min(1.0)
290
+
291
+
292
+ def default_configs(steps: int, config_set: str) -> list[DecodeConfig]:
293
+ if config_set == "focused_flowmap":
294
+ return [
295
+ DecodeConfig("flowmap_t1p00_d1p0", "flowmap", steps=steps, damping=1.0, max_gamma=1.0),
296
+ DecodeConfig("flowmap_t1p10_d1p0", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.10),
297
+ DecodeConfig("flowmap_t1p25_d1p0", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.25),
298
+ DecodeConfig("flowmap_t1p40_d1p0", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.40),
299
+ DecodeConfig("flowmap_t1p60_d1p0", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.60),
300
+ DecodeConfig("flowmap_t1p25_d0p7", "flowmap", steps=steps, damping=0.7, max_gamma=1.0, endpoint_temp=1.25),
301
+ DecodeConfig("flowmap_t1p40_d0p7", "flowmap", steps=steps, damping=0.7, max_gamma=1.0, endpoint_temp=1.40),
302
+ DecodeConfig("flowmap_t1p60_d0p7", "flowmap", steps=steps, damping=0.7, max_gamma=1.0, endpoint_temp=1.60),
303
+ DecodeConfig("flowmap_t1p25_g0p5", "flowmap", steps=steps, damping=1.0, max_gamma=0.5, endpoint_temp=1.25),
304
+ DecodeConfig("flowmap_t1p40_g0p5", "flowmap", steps=steps, damping=1.0, max_gamma=0.5, endpoint_temp=1.40),
305
+ ]
306
+ if config_set == "best_flowmap":
307
+ return [
308
+ DecodeConfig("flowmap_t1p25_d0p7", "flowmap", steps=steps, damping=0.7, max_gamma=1.0, endpoint_temp=1.25),
309
+ DecodeConfig("flowmap_t1p25_d1p0", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.25),
310
+ DecodeConfig("flowmap_t1p35_d1p0", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.35),
311
+ DecodeConfig("flowmap_t1p40_d1p0", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.40),
312
+ ]
313
+ if config_set == "final_projection":
314
+ return [
315
+ DecodeConfig("flowmap_t1p35_state", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.35, final_from="state"),
316
+ DecodeConfig("flowmap_t1p35_endpoint", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.35, final_from="endpoint"),
317
+ DecodeConfig("flowmap_t1p35_blend", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.35, final_from="blend"),
318
+ DecodeConfig("flowmap_t1p40_state", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.40, final_from="state"),
319
+ DecodeConfig("flowmap_t1p40_endpoint", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.40, final_from="endpoint"),
320
+ DecodeConfig("flowmap_t1p40_blend", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.40, final_from="blend"),
321
+ DecodeConfig("flowmap_t1p25_d0p7_state", "flowmap", steps=steps, damping=0.7, max_gamma=1.0, endpoint_temp=1.25, final_from="state"),
322
+ DecodeConfig("flowmap_t1p25_d0p7_endpoint", "flowmap", steps=steps, damping=0.7, max_gamma=1.0, endpoint_temp=1.25, final_from="endpoint"),
323
+ DecodeConfig("flowmap_t1p25_d0p7_blend", "flowmap", steps=steps, damping=0.7, max_gamma=1.0, endpoint_temp=1.25, final_from="blend"),
324
+ ]
325
+ if config_set == "eos_sweep":
326
+ return [
327
+ DecodeConfig("flowmap_t1p35_eos0", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.35, eos_logit_bias=0.0),
328
+ DecodeConfig("flowmap_t1p35_eos-1", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.35, eos_logit_bias=-1.0),
329
+ DecodeConfig("flowmap_t1p35_eos-2", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.35, eos_logit_bias=-2.0),
330
+ DecodeConfig("flowmap_t1p35_eos-3", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.35, eos_logit_bias=-3.0),
331
+ DecodeConfig("flowmap_t1p40_eos-2", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.40, eos_logit_bias=-2.0),
332
+ DecodeConfig("flowmap_t1p25_d0p7_eos-2", "flowmap", steps=steps, damping=0.7, max_gamma=1.0, endpoint_temp=1.25, eos_logit_bias=-2.0),
333
+ ]
334
+ if config_set != "broad":
335
+ raise ValueError(f"Unknown config_set: {config_set}")
336
+ return [
337
+ DecodeConfig("flowmap64", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, final_from="state"),
338
+ DecodeConfig("flowmap_temp1p25", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=1.25),
339
+ DecodeConfig("flowmap_temp0p85", "flowmap", steps=steps, damping=1.0, max_gamma=1.0, endpoint_temp=0.85),
340
+ DecodeConfig("replace_eta0p35", "replace", steps=steps, eta=0.35),
341
+ DecodeConfig("replace_eta0p50", "replace", steps=steps, eta=0.50),
342
+ DecodeConfig("replace_eta0p65", "replace", steps=steps, eta=0.65),
343
+ DecodeConfig("replace_eta0p50_temp1p25", "replace", steps=steps, eta=0.50, endpoint_temp=1.25),
344
+ DecodeConfig("geometric_eta0p25", "geometric", steps=steps, eta=0.25),
345
+ DecodeConfig("geometric_eta0p50", "geometric", steps=steps, eta=0.50),
346
+ DecodeConfig("centered_residual_eta0p20", "centered_residual", steps=steps, eta=0.20),
347
+ DecodeConfig("replace_eta0p50_floor1e6", "replace", steps=steps, eta=0.50, state_floor=1e-6),
348
+ DecodeConfig("replace_eta0p50_leak", "replace", steps=steps, eta=0.50, noise_mix=0.03, noise_decay="sqrt"),
349
+ ]
350
+
351
+
352
+ def aggregate(rows: list[dict]) -> dict:
353
+ keys = ["quality", "eos_count", "rep3", "rep4", "distinct1", "distinct2", "digit_frac", "max_word_frac"]
354
+ return {f"mean_{k}": sum(float(r[k]) for r in rows) / max(len(rows), 1) for k in keys}
355
+
356
+
357
+ def main() -> None:
358
+ parser = argparse.ArgumentParser()
359
+ parser.add_argument("--checkpoint", required=True)
360
+ parser.add_argument("--tokenizer_path", required=True)
361
+ parser.add_argument("--max_len", type=int, default=128)
362
+ parser.add_argument("--steps", type=int, default=64)
363
+ parser.add_argument("--restarts", type=int, default=64)
364
+ parser.add_argument("--target_prob", type=float, default=0.99)
365
+ parser.add_argument("--eps", type=float, default=1e-8)
366
+ parser.add_argument("--model_t_mode", choices=["linear", "flow", "const0", "const05", "const1", "random"], default="flow")
367
+ parser.add_argument("--noise_init", choices=["uniform", "logistic_normal", "dirichlet"], default="dirichlet")
368
+ parser.add_argument("--noise_sigma", type=float, default=-1.0)
369
+ parser.add_argument("--dirichlet_init_concentration", type=float, default=1.0)
370
+ parser.add_argument("--prompts", default="|The|In the early morning|Scientists have|The company said|A young woman")
371
+ parser.add_argument("--score_repeats", type=int, default=0)
372
+ parser.add_argument("--score_mask_frac", type=float, default=0.5)
373
+ parser.add_argument("--rerank_t", type=float, default=0.5)
374
+ parser.add_argument("--pl_weight", type=float, default=0.0)
375
+ parser.add_argument("--output", default="runs/decode_lab/latest_decode_lab.jsonl")
376
+ parser.add_argument("--config_set", default="broad", choices=["broad", "focused_flowmap", "best_flowmap", "final_projection", "eos_sweep"])
377
+ parser.add_argument("--decode_batch_size", type=int, default=0)
378
+ parser.add_argument("--topk", type=int, default=5)
379
+ parser.add_argument("--seed", type=int, default=20260428)
380
+ args = parser.parse_args()
381
+
382
+ torch.manual_seed(args.seed)
383
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
384
+ tokenizer = BpeTextTokenizer.from_file(args.tokenizer_path)
385
+ ckpt = torch.load(args.checkpoint, map_location="cpu")
386
+ model = build_model_from_ckpt(ckpt, tokenizer.vocab_size, args.max_len, device)
387
+ model.eval()
388
+
389
+ prompts = args.prompts.split("|")
390
+ # Keep the first empty prompt: it is unconditional generation.
391
+ print(f"[info] device={device} prompts={prompts} restarts={args.restarts} steps={args.steps}")
392
+ print(f"[info] checkpoint={args.checkpoint}")
393
+
394
+ out_path = Path(args.output)
395
+ out_path.parent.mkdir(parents=True, exist_ok=True)
396
+ configs = default_configs(args.steps, args.config_set)
397
+ for cfg in configs:
398
+ cfg.model_t_mode = args.model_t_mode
399
+ with out_path.open("w") as f:
400
+ for cfg in configs:
401
+ init, attn, lock, lock_probs, expanded = build_initial_state(
402
+ tokenizer=tokenizer,
403
+ prompts=prompts,
404
+ restarts=args.restarts,
405
+ max_len=args.max_len,
406
+ target_prob=args.target_prob,
407
+ eps=args.eps,
408
+ noise_init=args.noise_init,
409
+ noise_sigma=args.noise_sigma,
410
+ dirichlet_init_concentration=args.dirichlet_init_concentration,
411
+ device=device,
412
+ )
413
+ if args.decode_batch_size > 0 and init.size(0) > args.decode_batch_size:
414
+ decoded_parts = []
415
+ for start in range(0, init.size(0), args.decode_batch_size):
416
+ end = min(start + args.decode_batch_size, init.size(0))
417
+ part = decode_batch(
418
+ model,
419
+ init[start:end],
420
+ attn[start:end],
421
+ lock[start:end],
422
+ lock_probs[start:end],
423
+ cfg,
424
+ args.eps,
425
+ tokenizer.eos_id,
426
+ )
427
+ decoded_parts.append(part.detach().cpu())
428
+ print(f"[chunk] {cfg.label} decoded {end}/{init.size(0)}", flush=True)
429
+ decoded = torch.cat(decoded_parts, dim=0)
430
+ else:
431
+ decoded = decode_batch(model, init, attn, lock, lock_probs, cfg, args.eps, tokenizer.eos_id)
432
+ ids = decoded.argmax(dim=-1).detach().cpu().tolist()
433
+ texts = [decode_text(tokenizer, row) for row in ids]
434
+ rows = []
435
+ for i, text in enumerate(texts):
436
+ m = text_metrics(text)
437
+ m.update({"candidate": i, "prompt": expanded[i], "text": text})
438
+ rows.append(m)
439
+ if args.score_repeats > 0:
440
+ decoded_for_score = decoded.to(device) if decoded.device != device else decoded
441
+ pl = pseudo_likelihood_scores(
442
+ model,
443
+ tokenizer,
444
+ decoded_for_score,
445
+ attn,
446
+ lock,
447
+ args.target_prob,
448
+ args.eps,
449
+ repeats=args.score_repeats,
450
+ mask_frac=args.score_mask_frac,
451
+ rerank_t=args.rerank_t,
452
+ ).detach().cpu().tolist()
453
+ for row, score in zip(rows, pl):
454
+ row["pseudo_logp"] = float(score)
455
+ row["rank_score"] = float(row["quality"] + args.pl_weight * score)
456
+ else:
457
+ for row in rows:
458
+ row["pseudo_logp"] = None
459
+ row["rank_score"] = float(row["quality"])
460
+
461
+ summary = {"type": "summary", "config": asdict(cfg), "agg": aggregate(rows)}
462
+ f.write(json.dumps(summary, ensure_ascii=False) + "\n")
463
+ print("\n" + "=" * 96)
464
+ print("[config]", cfg.label, asdict(cfg))
465
+ print("[metrics]", json.dumps(summary["agg"], ensure_ascii=False))
466
+ for prompt in prompts:
467
+ subset = [r for r in rows if r["prompt"] == prompt]
468
+ subset.sort(key=lambda r: r["rank_score"], reverse=True)
469
+ for rank, row in enumerate(subset[: args.topk], 1):
470
+ rec = {"type": "sample", "config": asdict(cfg), "rank": rank, **row}
471
+ f.write(json.dumps(rec, ensure_ascii=False) + "\n")
472
+ if rank <= 1:
473
+ print(f"\n--- best prompt={prompt!r} rank_score={row['rank_score']:.4f} quality={row['quality']:.4f} ---")
474
+ print(row["text"])
475
+
476
+ del init, attn, lock, lock_probs, decoded
477
+ if torch.cuda.is_available():
478
+ torch.cuda.empty_cache()
479
+
480
+ print(f"[done] wrote {out_path}")
481
+
482
+
483
+ if __name__ == "__main__":
484
+ main()
LTA_openwebtext_dualt/scripts/eval_lm1b_linear_simplex_genppl.py ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Algebraic simplex-linear GenPPL eval for endpoint models.
3
+
4
+ This decoder matches the supervised bridge:
5
+
6
+ p_t = (1 - t) * p0 + t * x1
7
+
8
+ Inference keeps the sampled p0 fixed and replaces the unknown x1 with the
9
+ model's current endpoint prediction:
10
+
11
+ p_{t_next} = (1 - t_next) * p0 + t_next * a_theta(p_t, t).
12
+
13
+ There is no Dirichlet/Gamma resampling in the loop.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import argparse
19
+ import json
20
+ import math
21
+ import sys
22
+ from pathlib import Path
23
+
24
+ import torch
25
+ import torch.nn.functional as F
26
+ from transformers import AutoModelForCausalLM, AutoTokenizer
27
+
28
+ REPO_ROOT = Path(__file__).resolve().parents[1]
29
+ if str(REPO_ROOT) not in sys.path:
30
+ sys.path.insert(0, str(REPO_ROOT))
31
+
32
+ from flowtext_lab.decode import sample_noise_simplex, state_for_model
33
+ from flowtext_lab.genppl import filter_generated_texts, summarize_token_diversity
34
+ from flowtext_lab.tokenization import BpeTextTokenizer
35
+
36
+ from eval_lm1b_c1024_fullycoupled_sde_genppl import (
37
+ build_model,
38
+ collect_special_token_ids,
39
+ filter_endpoint_probs,
40
+ score_with_gpt2,
41
+ )
42
+
43
+
44
+ def lerp(a: float, b: float, t: float) -> float:
45
+ return float(a) + float(t) * (float(b) - float(a))
46
+
47
+
48
+ def project_endpoint(
49
+ logits: torch.Tensor,
50
+ *,
51
+ temp: float,
52
+ projection: str,
53
+ top_k: int,
54
+ top_p: float,
55
+ banned_ids: list[int],
56
+ gumbel_tau: float,
57
+ gumbel_noise_scale: float,
58
+ eps: float,
59
+ ) -> torch.Tensor:
60
+ endpoint = F.softmax(logits / max(float(temp), eps), dim=-1)
61
+ endpoint = filter_endpoint_probs(
62
+ endpoint,
63
+ top_k=top_k,
64
+ top_p=top_p,
65
+ banned_ids=banned_ids,
66
+ eps=eps,
67
+ )
68
+ if projection == "soft":
69
+ return endpoint
70
+ if projection == "argmax":
71
+ ids = endpoint.argmax(dim=-1)
72
+ return torch.zeros_like(endpoint).scatter_(-1, ids.unsqueeze(-1), 1.0)
73
+ if projection == "sample":
74
+ ids = torch.multinomial(endpoint.reshape(-1, endpoint.size(-1)), 1).view(*endpoint.shape[:-1])
75
+ return torch.zeros_like(endpoint).scatter_(-1, ids.unsqueeze(-1), 1.0)
76
+ if projection == "gumbel_softmax":
77
+ u = torch.rand_like(endpoint).clamp_(min=eps, max=1.0 - eps)
78
+ g = -torch.log(-torch.log(u))
79
+ z = (endpoint.clamp_min(eps).log() + float(gumbel_noise_scale) * g) / max(float(gumbel_tau), eps)
80
+ y = F.softmax(z, dim=-1).clamp_min(eps)
81
+ return y / y.sum(dim=-1, keepdim=True).clamp_min(eps)
82
+ raise ValueError(f"unknown endpoint_projection: {projection}")
83
+
84
+
85
+ @torch.inference_mode()
86
+ def decode_linear_simplex(
87
+ model,
88
+ tokenizer: BpeTextTokenizer,
89
+ *,
90
+ n_samples: int,
91
+ batch_size: int,
92
+ max_len: int,
93
+ steps: int,
94
+ seed: int,
95
+ device: torch.device,
96
+ noise_init: str,
97
+ noise_sigma: float,
98
+ noise_dirichlet_concentration: float,
99
+ endpoint_temp_start: float,
100
+ endpoint_temp_end: float,
101
+ endpoint_projection: str,
102
+ endpoint_top_k: int,
103
+ endpoint_top_p: float,
104
+ ban_special_tokens: bool,
105
+ gumbel_tau_start: float,
106
+ gumbel_tau_end: float,
107
+ gumbel_noise_scale_start: float,
108
+ gumbel_noise_scale_end: float,
109
+ final_from: str,
110
+ ) -> tuple[list[list[int]], list[str], dict]:
111
+ torch.manual_seed(seed)
112
+ eps = 1e-8
113
+ all_ids: list[list[int]] = []
114
+ all_texts: list[str] = []
115
+ remaining = n_samples
116
+ banned_endpoint_ids = collect_special_token_ids(tokenizer) if ban_special_tokens else []
117
+
118
+ while remaining > 0:
119
+ bs = min(batch_size, remaining)
120
+ p0 = sample_noise_simplex(
121
+ (bs, max_len),
122
+ tokenizer.vocab_size,
123
+ device,
124
+ eps,
125
+ noise_mode=noise_init,
126
+ target_prob=1.0,
127
+ noise_sigma=noise_sigma,
128
+ dirichlet_concentration=noise_dirichlet_concentration,
129
+ )
130
+ probs = p0.clone()
131
+ attn = torch.ones((bs, max_len), dtype=torch.bool, device=device)
132
+ last_endpoint = probs
133
+
134
+ for step in range(steps):
135
+ cur_t = step / max(steps, 1)
136
+ next_t = (step + 1) / max(steps, 1)
137
+ t = torch.full((bs,), float(cur_t), dtype=torch.float32, device=device)
138
+ logits = model(state_for_model(model, probs, eps), t, attn).float()
139
+
140
+ endpoint = project_endpoint(
141
+ logits,
142
+ temp=lerp(endpoint_temp_start, endpoint_temp_end, cur_t),
143
+ projection=endpoint_projection,
144
+ top_k=endpoint_top_k,
145
+ top_p=endpoint_top_p,
146
+ banned_ids=banned_endpoint_ids,
147
+ gumbel_tau=lerp(gumbel_tau_start, gumbel_tau_end, cur_t),
148
+ gumbel_noise_scale=lerp(gumbel_noise_scale_start, gumbel_noise_scale_end, cur_t),
149
+ eps=eps,
150
+ )
151
+ last_endpoint = endpoint
152
+ probs = (1.0 - next_t) * p0 + next_t * endpoint
153
+ probs = probs.clamp_min(eps)
154
+ probs = probs / probs.sum(dim=-1, keepdim=True).clamp_min(eps)
155
+
156
+ if final_from == "blend_0.5":
157
+ final_probs = 0.5 * probs + 0.5 * last_endpoint
158
+ ids = final_probs.argmax(dim=-1).detach().cpu().tolist()
159
+ elif final_from == "model_t1":
160
+ t = torch.ones((bs,), dtype=torch.float32, device=device)
161
+ final_logits = model(state_for_model(model, probs, eps), t, attn).float()
162
+ ids = final_logits.argmax(dim=-1).detach().cpu().tolist()
163
+ else:
164
+ raise ValueError(f"unknown final_from: {final_from}")
165
+
166
+ all_ids.extend(ids)
167
+ all_texts.extend(tokenizer.decode(row, stop_at_eos=False, skip_special_tokens=False) for row in ids)
168
+ remaining -= bs
169
+ print(f"[linear] generated {n_samples - remaining}/{n_samples}", flush=True)
170
+
171
+ cfg = {
172
+ "decode_rule": "linear_simplex_algebraic",
173
+ "steps": steps,
174
+ "noise_init": noise_init,
175
+ "noise_sigma": noise_sigma,
176
+ "noise_dirichlet_concentration": noise_dirichlet_concentration,
177
+ "endpoint_temp_start": endpoint_temp_start,
178
+ "endpoint_temp_end": endpoint_temp_end,
179
+ "endpoint_projection": endpoint_projection,
180
+ "endpoint_top_k": endpoint_top_k,
181
+ "endpoint_top_p": endpoint_top_p,
182
+ "ban_special_tokens": ban_special_tokens,
183
+ "banned_endpoint_ids": banned_endpoint_ids,
184
+ "gumbel_tau_start": gumbel_tau_start,
185
+ "gumbel_tau_end": gumbel_tau_end,
186
+ "gumbel_noise_scale_start": gumbel_noise_scale_start,
187
+ "gumbel_noise_scale_end": gumbel_noise_scale_end,
188
+ "final_from": final_from,
189
+ "n_samples": n_samples,
190
+ "seed": seed,
191
+ }
192
+ return all_ids, all_texts, cfg
193
+
194
+
195
+ def parse_args() -> argparse.Namespace:
196
+ p = argparse.ArgumentParser(description="Linear-simplex algebraic GenPPL eval")
197
+ p.add_argument("--checkpoint", required=True)
198
+ p.add_argument("--tokenizer_path", required=True)
199
+ p.add_argument("--scorer", required=True)
200
+ p.add_argument("--out_dir", required=True)
201
+ p.add_argument("--n_samples", type=int, default=128)
202
+ p.add_argument("--max_len", type=int, default=128)
203
+ p.add_argument("--steps", type=int, default=128)
204
+ p.add_argument("--batch_size", type=int, default=16)
205
+ p.add_argument("--score_batch", type=int, default=8)
206
+ p.add_argument("--score_max_length", type=int, default=1024)
207
+ p.add_argument("--noise_init", choices=["uniform", "logistic_normal", "dirichlet"], default="logistic_normal")
208
+ p.add_argument("--noise_sigma", type=float, default=3.0)
209
+ p.add_argument("--noise_dirichlet_concentration", type=float, default=1.0)
210
+ p.add_argument("--endpoint_temp_start", type=float, default=1.45)
211
+ p.add_argument("--endpoint_temp_end", type=float, default=0.8)
212
+ p.add_argument("--endpoint_projection", choices=["soft", "sample", "argmax", "gumbel_softmax"], default="soft")
213
+ p.add_argument("--endpoint_top_k", type=int, default=0)
214
+ p.add_argument("--endpoint_top_p", type=float, default=1.0)
215
+ p.add_argument("--ban_special_tokens", action="store_true")
216
+ p.add_argument("--gumbel_tau_start", type=float, default=1.0)
217
+ p.add_argument("--gumbel_tau_end", type=float, default=0.2)
218
+ p.add_argument("--gumbel_noise_scale_start", type=float, default=1.0)
219
+ p.add_argument("--gumbel_noise_scale_end", type=float, default=0.0)
220
+ p.add_argument("--final_from", choices=["blend_0.5", "model_t1"], default="model_t1")
221
+ p.add_argument("--seed", type=int, default=20260524)
222
+ return p.parse_args()
223
+
224
+
225
+ @torch.no_grad()
226
+ def main() -> None:
227
+ args = parse_args()
228
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
229
+ print(f"[load] {args.checkpoint}", flush=True)
230
+ ckpt = torch.load(args.checkpoint, map_location="cpu", weights_only=False)
231
+ step = ckpt.get("step")
232
+ print(f"[ckpt] step={step}", flush=True)
233
+
234
+ tokenizer = BpeTextTokenizer.from_file(args.tokenizer_path)
235
+ model = build_model(ckpt, tokenizer, device)
236
+ ids, texts, decode_cfg = decode_linear_simplex(
237
+ model,
238
+ tokenizer,
239
+ n_samples=args.n_samples,
240
+ batch_size=args.batch_size,
241
+ max_len=args.max_len,
242
+ steps=args.steps,
243
+ seed=args.seed,
244
+ device=device,
245
+ noise_init=args.noise_init,
246
+ noise_sigma=args.noise_sigma,
247
+ noise_dirichlet_concentration=args.noise_dirichlet_concentration,
248
+ endpoint_temp_start=args.endpoint_temp_start,
249
+ endpoint_temp_end=args.endpoint_temp_end,
250
+ endpoint_projection=args.endpoint_projection,
251
+ endpoint_top_k=args.endpoint_top_k,
252
+ endpoint_top_p=args.endpoint_top_p,
253
+ ban_special_tokens=args.ban_special_tokens,
254
+ gumbel_tau_start=args.gumbel_tau_start,
255
+ gumbel_tau_end=args.gumbel_tau_end,
256
+ gumbel_noise_scale_start=args.gumbel_noise_scale_start,
257
+ gumbel_noise_scale_end=args.gumbel_noise_scale_end,
258
+ final_from=args.final_from,
259
+ )
260
+ del model
261
+ if torch.cuda.is_available():
262
+ torch.cuda.empty_cache()
263
+
264
+ def strip_special(t: str) -> str:
265
+ import re
266
+ t = t.replace("[CLS]", " ").replace("[SEP]", " ").replace("[PAD]", " ")
267
+ t = t.replace("<|endoftext|>", " ")
268
+ return re.sub(r"\s+", " ", t).strip()
269
+
270
+ stripped = [strip_special(t) for t in texts]
271
+ kept_raw, _ = filter_generated_texts(texts, min_chars=1, normalize_whitespace=False, drop_empty=True)
272
+ kept_stripped, _ = filter_generated_texts(stripped, min_chars=1, normalize_whitespace=True, drop_empty=True)
273
+ diversity = summarize_token_diversity(ids).__dict__
274
+
275
+ print(f"[score] loading scorer: {args.scorer}", flush=True)
276
+ scorer_tok = AutoTokenizer.from_pretrained(args.scorer)
277
+ if scorer_tok.pad_token_id is None:
278
+ scorer_tok.pad_token = scorer_tok.eos_token
279
+ scorer_tok.pad_token_id = scorer_tok.eos_token_id
280
+ scorer = AutoModelForCausalLM.from_pretrained(args.scorer).to(device).eval()
281
+ if getattr(scorer.config, "pad_token_id", None) is None:
282
+ scorer.config.pad_token_id = scorer_tok.pad_token_id
283
+
284
+ raw_ppl = score_with_gpt2(
285
+ kept_raw, scorer, scorer_tok,
286
+ batch_size=args.score_batch, max_length=args.score_max_length, device=device,
287
+ )
288
+ stripped_ppl = score_with_gpt2(
289
+ kept_stripped, scorer, scorer_tok,
290
+ batch_size=args.score_batch, max_length=args.score_max_length, device=device,
291
+ )
292
+ summary = {
293
+ "type": "summary",
294
+ "checkpoint": args.checkpoint,
295
+ "step": step,
296
+ "decode": decode_cfg,
297
+ "raw_genppl": raw_ppl,
298
+ "stripped_genppl": stripped_ppl,
299
+ "diversity": diversity,
300
+ }
301
+
302
+ out_dir = Path(args.out_dir)
303
+ out_dir.mkdir(parents=True, exist_ok=True)
304
+ out_jsonl = out_dir / f"linear_steps{args.steps}_samples{args.n_samples}_scored.jsonl"
305
+ with out_jsonl.open("w", encoding="utf-8") as f:
306
+ f.write(json.dumps(summary, ensure_ascii=False) + "\n")
307
+ for i, (raw, clean) in enumerate(zip(texts, stripped)):
308
+ f.write(json.dumps({"type": "sample", "index": i, "raw_text": raw, "stripped_text": clean}, ensure_ascii=False) + "\n")
309
+ print("[summary]", json.dumps(summary, ensure_ascii=False, indent=2), flush=True)
310
+ print(f"[done] {out_jsonl}", flush=True)
311
+
312
+
313
+ if __name__ == "__main__":
314
+ main()
LTA_openwebtext_dualt/scripts/eval_train8_overfit_sweep.sh ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ STAMP="${STAMP:?set STAMP used by run_train8_overfit_sweep_4gpu.sh}"
7
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/models/flowtext_scorers/gpt2-standard/tokenizer.json}"
8
+ CACHE_DIR="${CACHE_DIR:-/e2e-data/evad-tech-vla/wanghan58/data/small_benchmarks/langflow_2604_11748/openwebtext_lta_cached_chunks/gpt2_len1024_train8_overfit}"
9
+ OUT_ROOT="${OUT_ROOT:-docs/lta_samples/metrics_20260517/train8_overfit_${STAMP}}"
10
+ export OUT_ROOT
11
+ mkdir -p "${OUT_ROOT}"
12
+
13
+ for run in \
14
+ "train8_n1024_hard_ce_onehot_${STAMP}" \
15
+ "train8_n1024_hard_ce_bridge_${STAMP}" \
16
+ "train8_n1024_linear_soft_kl_onehot_${STAMP}" \
17
+ "train8_n1024_linear_soft_kl_bridge_${STAMP}"
18
+ do
19
+ echo "[eval-overfit] ${run}"
20
+ python scripts/eval_train8_overfit_ckpts.py \
21
+ --run_dir "runs/${run}" \
22
+ --cache_dir "${CACHE_DIR}" \
23
+ --tokenizer_path "${TOKENIZER_PATH}" \
24
+ --out_dir "${OUT_ROOT}/${run}" \
25
+ --max_len 1024 \
26
+ --limit 8 \
27
+ --t_values 0.125,0.25,0.5,0.75,1.0 \
28
+ --seeds 123,456,789
29
+ done
30
+
31
+ python - <<'PY'
32
+ import json
33
+ import os
34
+ from pathlib import Path
35
+ root = Path(os.environ["OUT_ROOT"])
36
+ rows = []
37
+ for p in sorted(root.glob("*/result.json")):
38
+ r = json.loads(p.read_text())
39
+ last = r["last"]
40
+ rows.append({
41
+ "run": p.parent.name,
42
+ "first_fit_step": r["first_fit_step"],
43
+ "best_acc": r["best_acc"],
44
+ "best_objective": r["best_objective"],
45
+ "last_acc": last["gold_acc_mean"],
46
+ "last_objective": last["objective_mean"],
47
+ "last_ce": last["gold_ce_mean"],
48
+ })
49
+ with (root / "combined.tsv").open("w") as f:
50
+ f.write("run\tfirst_fit_step\tbest_acc\tbest_objective\tlast_acc\tlast_objective\tlast_ce\n")
51
+ for r in rows:
52
+ f.write("\t".join(str(r[k]) for k in ["run","first_fit_step","best_acc","best_objective","last_acc","last_objective","last_ce"]) + "\n")
53
+ print(root / "combined.tsv")
54
+ PY
LTA_openwebtext_dualt/scripts/launch_ar_openwebtext_duo_small_8gpu_1m.sh ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
6
+ export TOKENIZERS_PARALLELISM=false
7
+ export PYTHONUNBUFFERED=1
8
+ export NCCL_DEBUG="${NCCL_DEBUG:-WARN}"
9
+ export TORCH_DISTRIBUTED_TIMEOUT="${TORCH_DISTRIBUTED_TIMEOUT:-3600}"
10
+
11
+ RUN_NAME="${RUN_NAME:-ar_owt_flmpack_gpt2_small_len1024_gbs512_8gpu_1m}"
12
+ DATA_PATH="${DATA_PATH:-/e2e-data/evad-tech-vla/wanghan58/data/small_benchmarks/langflow_2604_11748/openwebtext}"
13
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/models/flowtext_scorers/gpt2-standard/tokenizer.json}"
14
+ TEXT_COLUMN="${TEXT_COLUMN:-text}"
15
+ OPENWEBTEXT_SPLIT="${OPENWEBTEXT_SPLIT:-train_minus_100k}"
16
+ SAVE_DIR="${SAVE_DIR:-runs/${RUN_NAME}}"
17
+ LOG_FILE="${LOG_FILE:-logs/${RUN_NAME}.log}"
18
+
19
+ NNODES="${NNODES:-1}"
20
+ NPROC_PER_NODE="${NPROC_PER_NODE:-8}"
21
+ NODE_RANK="${NODE_RANK:-0}"
22
+ MASTER_ADDR="${MASTER_ADDR:-127.0.0.1}"
23
+ MASTER_PORT="${MASTER_PORT:-29643}"
24
+
25
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
26
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-32}"
27
+ TOTAL_STEPS="${TOTAL_STEPS:-1000000}"
28
+ WARMUP_STEPS="${WARMUP_STEPS:-2500}"
29
+ MAX_LEN="${MAX_LEN:-1024}"
30
+ NUM_WORKERS="${NUM_WORKERS:-4}"
31
+ LOG_EVERY="${LOG_EVERY:-100}"
32
+ SAVE_EVERY="${SAVE_EVERY:-20000}"
33
+ LATEST_EVERY="${LATEST_EVERY:-1000}"
34
+ SAMPLE_EVERY="${SAMPLE_EVERY:-0}"
35
+ RESUME_PATH="${RESUME_PATH:-}"
36
+ ALLOW_EXISTING_SAVE_DIR="${ALLOW_EXISTING_SAVE_DIR:-0}"
37
+ ENABLE_TORCH_COMPILE="${ENABLE_TORCH_COMPILE:-0}"
38
+
39
+ COMPILE_ARGS=()
40
+ if [[ "${ENABLE_TORCH_COMPILE}" == "1" ]]; then
41
+ COMPILE_ARGS+=(--torch_compile --compile_mode reduce-overhead)
42
+ fi
43
+ RESUME_ARGS=()
44
+ if [[ -n "${RESUME_PATH}" ]]; then
45
+ RESUME_ARGS+=(--resume_path "${RESUME_PATH}")
46
+ fi
47
+ TEXT_COLUMN_ARGS=()
48
+ if [[ -n "${TEXT_COLUMN}" ]]; then
49
+ TEXT_COLUMN_ARGS+=(--text_column "${TEXT_COLUMN}")
50
+ fi
51
+
52
+ if [[ -f "${SAVE_DIR}/args.json" && -z "${RESUME_PATH}" && "${ALLOW_EXISTING_SAVE_DIR}" != "1" ]]; then
53
+ echo "Refusing to start because SAVE_DIR already contains args.json: ${SAVE_DIR}" >&2
54
+ echo "Use a new RUN_NAME/SAVE_DIR, set RESUME_PATH to resume, or set ALLOW_EXISTING_SAVE_DIR=1 intentionally." >&2
55
+ exit 2
56
+ fi
57
+
58
+ mkdir -p logs runs "${SAVE_DIR}"
59
+
60
+ python -m torch.distributed.run \
61
+ --nnodes="${NNODES}" \
62
+ --nproc_per_node="${NPROC_PER_NODE}" \
63
+ --node_rank="${NODE_RANK}" \
64
+ --master_addr="${MASTER_ADDR}" \
65
+ --master_port="${MASTER_PORT}" \
66
+ train_ar.py \
67
+ --data_path "${DATA_PATH}" \
68
+ "${TEXT_COLUMN_ARGS[@]}" \
69
+ --openwebtext_split "${OPENWEBTEXT_SPLIT}" \
70
+ --tokenizer_path "${TOKENIZER_PATH}" \
71
+ --save_dir "${SAVE_DIR}" \
72
+ --wrap \
73
+ --max_len "${MAX_LEN}" \
74
+ --batch_size "${PER_GPU_BATCH_SIZE}" \
75
+ --num_workers "${NUM_WORKERS}" \
76
+ --global_batch_size "${GLOBAL_BATCH_SIZE}" \
77
+ --total_steps "${TOTAL_STEPS}" \
78
+ --log_every "${LOG_EVERY}" \
79
+ --save_every "${SAVE_EVERY}" \
80
+ --latest_every "${LATEST_EVERY}" \
81
+ --sample_every "${SAMPLE_EVERY}" \
82
+ --lr 3e-4 \
83
+ --weight_decay 0 \
84
+ --adam_beta1 0.9 \
85
+ --adam_beta2 0.999 \
86
+ --adam_eps 1e-8 \
87
+ --warmup_steps "${WARMUP_STEPS}" \
88
+ --lr_schedule constant_warmup \
89
+ --grad_clip 1.0 \
90
+ --seed 123 \
91
+ --d_model 768 \
92
+ --n_layers 12 \
93
+ --n_heads 12 \
94
+ --dim_ff 3072 \
95
+ --dropout 0.1 \
96
+ --tie_embeddings \
97
+ "${RESUME_ARGS[@]}" \
98
+ "${COMPILE_ARGS[@]}" \
99
+ --bf16 2>&1 | tee -a "${LOG_FILE}"
LTA_openwebtext_dualt/scripts/launch_lm1b_flm_8gpu_repro_20260506.sh ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
6
+ export TOKENIZERS_PARALLELISM=false
7
+ export PYTHONUNBUFFERED=1
8
+ export NCCL_DEBUG="${NCCL_DEBUG:-WARN}"
9
+ export TORCH_DISTRIBUTED_TIMEOUT="${TORCH_DISTRIBUTED_TIMEOUT:-3600}"
10
+ export CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7}"
11
+
12
+ # Unified LM1B FLM baseline.
13
+ # This uses the same tokenizer/data/model/optimizer setup as MDLM/DUO.
14
+
15
+ RUN_TAG="${RUN_TAG:-20260506_repro}"
16
+ RUN_NAME="${RUN_NAME:-lm1b_flm_unified_ddit_small_len128_gbs512_8gpu_1m_${RUN_TAG}}"
17
+ DATA_PATH="${DATA_PATH:-data/lm1b_train_parquet}"
18
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/workspace/imagenet_handoff_20260327/nlp_dts_light/assets/distilbert-base-uncased/tokenizer.json}"
19
+ TEXT_COLUMN="${TEXT_COLUMN:-}"
20
+ OPENWEBTEXT_SPLIT="${OPENWEBTEXT_SPLIT:-all}"
21
+ SAVE_DIR="${SAVE_DIR:-runs/${RUN_NAME}}"
22
+ LOG_FILE="${LOG_FILE:-logs/${RUN_NAME}.log}"
23
+
24
+ NNODES="${NNODES:-1}"
25
+ NPROC_PER_NODE="${NPROC_PER_NODE:-8}"
26
+ NODE_RANK="${NODE_RANK:-0}"
27
+ MASTER_ADDR="${MASTER_ADDR:-127.0.0.1}"
28
+ MASTER_PORT="${MASTER_PORT:-29646}"
29
+
30
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
31
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-64}"
32
+ TOTAL_STEPS="${TOTAL_STEPS:-1000000}"
33
+ WARMUP_STEPS="${WARMUP_STEPS:-2500}"
34
+ MAX_LEN="${MAX_LEN:-128}"
35
+ WRAP_MODE="${WRAP_MODE:-stream}"
36
+ WRAP_RECORD_BUFFER_SIZE="${WRAP_RECORD_BUFFER_SIZE:-200}"
37
+ NUM_WORKERS="${NUM_WORKERS:-0}"
38
+ LOG_EVERY="${LOG_EVERY:-100}"
39
+ SAVE_EVERY="${SAVE_EVERY:-20000}"
40
+ LATEST_EVERY="${LATEST_EVERY:-1000}"
41
+ RESUME_PATH="${RESUME_PATH:-}"
42
+ ALLOW_EXISTING_SAVE_DIR="${ALLOW_EXISTING_SAVE_DIR:-0}"
43
+ ENABLE_TORCH_COMPILE="${ENABLE_TORCH_COMPILE:-0}"
44
+ FORCE_DISABLE_TORCH_COMPILE="${FORCE_DISABLE_TORCH_COMPILE:-1}"
45
+
46
+ if [[ "${FORCE_DISABLE_TORCH_COMPILE}" == "1" ]]; then
47
+ ENABLE_TORCH_COMPILE=0
48
+ fi
49
+ if [[ "${DATA_PATH}" == *"lm1b_train_parquet"* && "${NUM_WORKERS}" != "0" ]]; then
50
+ echo "LM1B has only 9 parquet shards; forcing NUM_WORKERS=0 to avoid empty DDP dataloader shards." >&2
51
+ NUM_WORKERS=0
52
+ fi
53
+
54
+ COMPILE_ARGS=()
55
+ if [[ "${ENABLE_TORCH_COMPILE}" == "1" ]]; then
56
+ COMPILE_ARGS+=(--torch_compile --compile_mode reduce-overhead)
57
+ fi
58
+ RESUME_ARGS=()
59
+ if [[ -n "${RESUME_PATH}" ]]; then
60
+ RESUME_ARGS+=(--resume_path "${RESUME_PATH}")
61
+ fi
62
+ TEXT_COLUMN_ARGS=()
63
+ if [[ -n "${TEXT_COLUMN}" ]]; then
64
+ TEXT_COLUMN_ARGS+=(--text_column "${TEXT_COLUMN}")
65
+ fi
66
+
67
+ if [[ -f "${SAVE_DIR}/args.json" && -z "${RESUME_PATH}" && "${ALLOW_EXISTING_SAVE_DIR}" != "1" ]]; then
68
+ echo "Refusing to start because SAVE_DIR already contains args.json: ${SAVE_DIR}" >&2
69
+ echo "Use a new RUN_NAME/SAVE_DIR, set RESUME_PATH to resume, or set ALLOW_EXISTING_SAVE_DIR=1 intentionally." >&2
70
+ exit 2
71
+ fi
72
+
73
+ mkdir -p logs runs "${SAVE_DIR}"
74
+ echo "[launch] method=flm host=$(hostname) time=$(date -Iseconds)"
75
+ echo "[launch] cwd=$(pwd)"
76
+ echo "[launch] run_name=${RUN_NAME}"
77
+ echo "[launch] save_dir=${SAVE_DIR}"
78
+ echo "[launch] log_file=${LOG_FILE}"
79
+ echo "[launch] nproc_per_node=${NPROC_PER_NODE} global_batch_size=${GLOBAL_BATCH_SIZE} per_gpu_batch_size=${PER_GPU_BATCH_SIZE}"
80
+
81
+ python -m torch.distributed.run \
82
+ --nnodes="${NNODES}" \
83
+ --nproc_per_node="${NPROC_PER_NODE}" \
84
+ --node_rank="${NODE_RANK}" \
85
+ --master_addr="${MASTER_ADDR}" \
86
+ --master_port="${MASTER_PORT}" \
87
+ train_baseline.py \
88
+ --baseline_method flm \
89
+ --data_path "${DATA_PATH}" \
90
+ "${TEXT_COLUMN_ARGS[@]}" \
91
+ --openwebtext_split "${OPENWEBTEXT_SPLIT}" \
92
+ --tokenizer_path "${TOKENIZER_PATH}" \
93
+ --save_dir "${SAVE_DIR}" \
94
+ --max_len "${MAX_LEN}" \
95
+ --batch_size "${PER_GPU_BATCH_SIZE}" \
96
+ --num_workers "${NUM_WORKERS}" \
97
+ --global_batch_size "${GLOBAL_BATCH_SIZE}" \
98
+ --wrap_mode "${WRAP_MODE}" \
99
+ --wrap_record_buffer_size "${WRAP_RECORD_BUFFER_SIZE}" \
100
+ --total_steps "${TOTAL_STEPS}" \
101
+ --log_every "${LOG_EVERY}" \
102
+ --save_every "${SAVE_EVERY}" \
103
+ --latest_every "${LATEST_EVERY}" \
104
+ --lr 3e-4 \
105
+ --weight_decay 0 \
106
+ --adam_beta1 0.9 \
107
+ --adam_beta2 0.999 \
108
+ --adam_eps 1e-8 \
109
+ --warmup_steps "${WARMUP_STEPS}" \
110
+ --lr_schedule constant_warmup \
111
+ --grad_clip 1.0 \
112
+ --seed 123 \
113
+ --d_model 768 \
114
+ --cond_dim 128 \
115
+ --n_layers 12 \
116
+ --n_heads 12 \
117
+ --dim_ff 3072 \
118
+ --dropout 0.1 \
119
+ --model_type ddit \
120
+ --sampling_eps 1e-3 \
121
+ "${RESUME_ARGS[@]}" \
122
+ "${COMPILE_ARGS[@]}" \
123
+ --bf16 2>&1 | tee -a "${LOG_FILE}"
LTA_openwebtext_dualt/scripts/launch_lta_lm1b_categorical_fullvocab_c1024_gaussian_linear_mean_fullycoupled_8gpu_small_1m.sh ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
6
+ export TOKENIZERS_PARALLELISM=false
7
+ export PYTHONUNBUFFERED=1
8
+ export NCCL_DEBUG="${NCCL_DEBUG:-WARN}"
9
+ export TORCH_DISTRIBUTED_TIMEOUT="${TORCH_DISTRIBUTED_TIMEOUT:-3600}"
10
+
11
+ # Gaussian/logistic-normal center-mixture with probability-linear mean:
12
+ # model_t == support t == semantic endpoint t
13
+ # endpoint is categorical full-vocab, state is logistic-normal around
14
+ # mu_c(t) = (1 - t) uniform + t onehot(center)
15
+ RUN_NAME="${RUN_NAME:-lta_lm1b_logisticnormal_linearmean_categorical_fullvocab_c1024_fullycoupled_flmpack_onehot_hardce_ddit_small_len128_gbs512_8gpu_1m_nw0}"
16
+ DATA_PATH="${DATA_PATH:-data/lm1b_train_parquet}"
17
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/workspace/imagenet_handoff_20260327/nlp_dts_light/assets/distilbert-base-uncased/tokenizer.json}"
18
+ TEXT_COLUMN="${TEXT_COLUMN:-}"
19
+ OPENWEBTEXT_SPLIT="${OPENWEBTEXT_SPLIT:-all}"
20
+ SAVE_DIR="${SAVE_DIR:-runs/${RUN_NAME}}"
21
+ LOG_FILE="${LOG_FILE:-logs/${RUN_NAME}.log}"
22
+
23
+ NNODES="${NNODES:-1}"
24
+ NPROC_PER_NODE="${NPROC_PER_NODE:-8}"
25
+ NODE_RANK="${NODE_RANK:-0}"
26
+ MASTER_ADDR="${MASTER_ADDR:-127.0.0.1}"
27
+ MASTER_PORT="${MASTER_PORT:-29631}"
28
+
29
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
30
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-64}"
31
+ TOTAL_STEPS="${TOTAL_STEPS:-1000000}"
32
+ WARMUP_STEPS="${WARMUP_STEPS:-2500}"
33
+ MAX_LEN="${MAX_LEN:-128}"
34
+ WRAP_MODE="${WRAP_MODE:-stream}"
35
+ WRAP_RECORD_BUFFER_SIZE="${WRAP_RECORD_BUFFER_SIZE:-200}"
36
+ NUM_WORKERS="${NUM_WORKERS:-0}"
37
+ LOG_EVERY="${LOG_EVERY:-100}"
38
+ SAVE_EVERY="${SAVE_EVERY:-20000}"
39
+ LATEST_EVERY="${LATEST_EVERY:-1000}"
40
+ EVAL_EVERY="${EVAL_EVERY:-0}"
41
+ RESUME_PATH="${RESUME_PATH:-}"
42
+ ALLOW_EXISTING_SAVE_DIR="${ALLOW_EXISTING_SAVE_DIR:-0}"
43
+ ENABLE_TORCH_COMPILE="${ENABLE_TORCH_COMPILE:-0}"
44
+ FORCE_DISABLE_TORCH_COMPILE="${FORCE_DISABLE_TORCH_COMPILE:-1}"
45
+
46
+ if [[ "${FORCE_DISABLE_TORCH_COMPILE}" == "1" ]]; then
47
+ ENABLE_TORCH_COMPILE=0
48
+ fi
49
+ if [[ "${DATA_PATH}" == *"lm1b_train_parquet"* && "${NUM_WORKERS}" != "0" ]]; then
50
+ echo "LM1B has only 9 parquet shards; forcing NUM_WORKERS=0 to avoid empty DDP dataloader shards." >&2
51
+ NUM_WORKERS=0
52
+ fi
53
+
54
+ COMPILE_ARGS=()
55
+ if [[ "${ENABLE_TORCH_COMPILE}" == "1" ]]; then
56
+ COMPILE_ARGS+=(--torch_compile --compile_mode reduce-overhead)
57
+ fi
58
+ RESUME_ARGS=()
59
+ if [[ -n "${RESUME_PATH}" ]]; then
60
+ RESUME_ARGS+=(--resume_path "${RESUME_PATH}")
61
+ fi
62
+ TEXT_COLUMN_ARGS=()
63
+ if [[ -n "${TEXT_COLUMN}" ]]; then
64
+ TEXT_COLUMN_ARGS+=(--text_column "${TEXT_COLUMN}")
65
+ fi
66
+
67
+ if [[ -f "${SAVE_DIR}/args.json" && -z "${RESUME_PATH}" && "${ALLOW_EXISTING_SAVE_DIR}" != "1" ]]; then
68
+ echo "Refusing to start because SAVE_DIR already contains args.json: ${SAVE_DIR}" >&2
69
+ echo "Use a new RUN_NAME/SAVE_DIR, set RESUME_PATH to resume, or set ALLOW_EXISTING_SAVE_DIR=1 intentionally." >&2
70
+ exit 2
71
+ fi
72
+
73
+ mkdir -p logs runs "${SAVE_DIR}"
74
+ echo "[launch] method=logisticnormal_linearmean_categorical_fullvocab_c1024_fullycoupled host=$(hostname) time=$(date -Iseconds)"
75
+ echo "[launch] cwd=$(pwd)"
76
+ echo "[launch] run_name=${RUN_NAME}"
77
+ echo "[launch] save_dir=${SAVE_DIR}"
78
+ echo "[launch] log_file=${LOG_FILE}"
79
+
80
+ python -m torch.distributed.run \
81
+ --nnodes="${NNODES}" \
82
+ --nproc_per_node="${NPROC_PER_NODE}" \
83
+ --node_rank="${NODE_RANK}" \
84
+ --master_addr="${MASTER_ADDR}" \
85
+ --master_port="${MASTER_PORT}" \
86
+ train.py \
87
+ --data_path "${DATA_PATH}" \
88
+ "${TEXT_COLUMN_ARGS[@]}" \
89
+ --openwebtext_split "${OPENWEBTEXT_SPLIT}" \
90
+ --tokenizer_path "${TOKENIZER_PATH}" \
91
+ --save_dir "${SAVE_DIR}" \
92
+ --wrap \
93
+ --wrap_mode "${WRAP_MODE}" \
94
+ --wrap_record_buffer_size "${WRAP_RECORD_BUFFER_SIZE}" \
95
+ --max_len "${MAX_LEN}" \
96
+ --batch_size "${PER_GPU_BATCH_SIZE}" \
97
+ --num_workers "${NUM_WORKERS}" \
98
+ --global_batch_size "${GLOBAL_BATCH_SIZE}" \
99
+ --total_steps "${TOTAL_STEPS}" \
100
+ --log_every "${LOG_EVERY}" \
101
+ --eval_every "${EVAL_EVERY}" \
102
+ --save_every "${SAVE_EVERY}" \
103
+ --latest_every "${LATEST_EVERY}" \
104
+ --lr 3e-4 \
105
+ --weight_decay 0 \
106
+ --adam_beta1 0.9 \
107
+ --adam_beta2 0.999 \
108
+ --adam_eps 1e-8 \
109
+ --warmup_steps "${WARMUP_STEPS}" \
110
+ --lr_schedule constant_warmup \
111
+ --grad_clip 1.0 \
112
+ --seed 123 \
113
+ --d_model 768 \
114
+ --cond_dim 128 \
115
+ --n_layers 12 \
116
+ --n_heads 12 \
117
+ --dim_ff 3072 \
118
+ --dropout 0.1 \
119
+ --model_type ddit \
120
+ --state_format prob \
121
+ --bridge dirichlet \
122
+ --target_loss hard_ce \
123
+ --target_prob 1.0 \
124
+ --min_t 0.0 \
125
+ --max_t 1.0 \
126
+ --dual_t \
127
+ --corrupt_t_mode same \
128
+ --corrupt_min_t 0.0 \
129
+ --corrupt_max_t 1.0 \
130
+ --min_mask_ratio 0.1 \
131
+ --max_mask_ratio 1.0 \
132
+ --wrong_token_replace_prob 1.0 \
133
+ --wrong_token_schedule linear_t \
134
+ --wrong_token_exp_k 1.0 \
135
+ --dirichlet_concentration_min 1.0 \
136
+ --dirichlet_concentration_max 1024.0 \
137
+ --dirichlet_endpoint_mode categorical_dual_t \
138
+ --dirichlet_semantic_t_mode same \
139
+ --dirichlet_semantic_t_value 0.0 \
140
+ --categorical_wrong_from_full_vocab \
141
+ --simplex_bridge_sampler logistic_normal_linear_mean \
142
+ --logistic_normal_sigma_min 0.18 \
143
+ --logistic_normal_sigma_max 2.2 \
144
+ --logistic_normal_tau_min 0.65 \
145
+ --logistic_normal_tau_max 1.15 \
146
+ --eps 1e-8 \
147
+ --infer_steps 128 \
148
+ --decode_damping 1.0 \
149
+ --max_gamma 1.0 \
150
+ --decode_solver flowmap \
151
+ --noise_init logistic_normal \
152
+ --bridge_noise_init logistic_normal \
153
+ --noise_sigma -1 \
154
+ "${RESUME_ARGS[@]}" \
155
+ "${COMPILE_ARGS[@]}" \
156
+ --bf16 2>&1 | tee -a "${LOG_FILE}"
LTA_openwebtext_dualt/scripts/launch_lta_lm1b_compact_gpt2bpe_v8192_len128_fullycoupled_4gpu.sh ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ export CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0,1,2,3}"
7
+ export OMP_NUM_THREADS="${OMP_NUM_THREADS:-1}"
8
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
9
+ export TOKENIZERS_PARALLELISM=false
10
+ export PYTHONUNBUFFERED=1
11
+ export NCCL_DEBUG="${NCCL_DEBUG:-WARN}"
12
+ export TORCH_DISTRIBUTED_TIMEOUT="${TORCH_DISTRIBUTED_TIMEOUT:-3600}"
13
+
14
+ DATA_PATH="${DATA_PATH:-/e2e-data/evad-tech-vla/wanghan58/data/embedded-language-flows/lm1b-compact-gpt2bpe-v8192-stream128}"
15
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/models/lta_tokenizers/owt_compact_gpt2bpe_v8192/tokenizer.json}"
16
+
17
+ NNODES="${NNODES:-1}"
18
+ NPROC_PER_NODE="${NPROC_PER_NODE:-4}"
19
+ NODE_RANK="${NODE_RANK:-0}"
20
+ MASTER_ADDR="${MASTER_ADDR:-127.0.0.1}"
21
+ MASTER_PORT="${MASTER_PORT:-32381}"
22
+
23
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-64}"
24
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
25
+ TOTAL_STEPS="${TOTAL_STEPS:-1000000}"
26
+ WARMUP_STEPS="${WARMUP_STEPS:-2000}"
27
+ NUM_WORKERS="${NUM_WORKERS:-8}"
28
+ DATALOADER_PREFETCH_FACTOR="${DATALOADER_PREFETCH_FACTOR:-4}"
29
+ LOG_EVERY="${LOG_EVERY:-50}"
30
+ SAVE_EVERY="${SAVE_EVERY:-10000}"
31
+ LATEST_EVERY="${LATEST_EVERY:-1000}"
32
+ EVAL_EVERY="${EVAL_EVERY:-0}"
33
+ ALLOW_EXISTING_SAVE_DIR="${ALLOW_EXISTING_SAVE_DIR:-0}"
34
+ ALLOW_TF32="${ALLOW_TF32:-1}"
35
+ DRY_RUN="${DRY_RUN:-0}"
36
+ RESUME_PATH="${RESUME_PATH:-}"
37
+
38
+ LR="${LR:-6e-4}"
39
+ MIN_LR="${MIN_LR:-6e-5}"
40
+ WEIGHT_DECAY="${WEIGHT_DECAY:-0.1}"
41
+ OUTPUT_WEIGHT_DECAY="${OUTPUT_WEIGHT_DECAY:--1}"
42
+ ADAM_BETA1="${ADAM_BETA1:-0.9}"
43
+ ADAM_BETA2="${ADAM_BETA2:-0.95}"
44
+ ADAM_EPS="${ADAM_EPS:-1e-8}"
45
+ GRAD_CLIP="${GRAD_CLIP:-1.0}"
46
+ EMA_DECAY="${EMA_DECAY:-0.0}"
47
+ EMA_START_STEP="${EMA_START_STEP:-0}"
48
+
49
+ T_SAMPLING_MODE="${T_SAMPLING_MODE:-uniform}"
50
+ T_SAMPLING_POWER="${T_SAMPLING_POWER:-1.0}"
51
+ T_SAMPLING_EPS="${T_SAMPLING_EPS:-1e-4}"
52
+ T_SAMPLING_LOGIT_MEAN="${T_SAMPLING_LOGIT_MEAN:--1.5}"
53
+ T_SAMPLING_LOGIT_STD="${T_SAMPLING_LOGIT_STD:-0.8}"
54
+ MIN_MASK_RATIO="${MIN_MASK_RATIO:-1.0}"
55
+ MAX_MASK_RATIO="${MAX_MASK_RATIO:-1.0}"
56
+
57
+ LOSS_T_WEIGHT_MODE="${LOSS_T_WEIGHT_MODE:-none}"
58
+ LOSS_T_MIN_WEIGHT="${LOSS_T_MIN_WEIGHT:-0.0}"
59
+ LOSS_T_DROP_BELOW="${LOSS_T_DROP_BELOW:-0.2}"
60
+
61
+ RUN_NAME="${RUN_NAME:-lta_lm1b_compact_gpt2bpe_v8192_len128_fullycoupled_rmsnorm_nobias_adamw_wd0p1_${T_SAMPLING_MODE}t_hardce_mask${MIN_MASK_RATIO}-${MAX_MASK_RATIO}_fp32_ddit768x12_gbs${GLOBAL_BATCH_SIZE}_4gpu_1m_$(date +%Y%m%d_%H%M%S)}"
62
+ SAVE_DIR="${SAVE_DIR:-runs/${RUN_NAME}}"
63
+ LOG_DIR="${LOG_DIR:-logs/lm1b_compact_gpt2bpe_v8192_len128_fullycoupled_4gpu}"
64
+ LOG_FILE="${LOG_FILE:-${LOG_DIR}/${RUN_NAME}.log}"
65
+
66
+ if [[ ! -f "${TOKENIZER_PATH}" ]]; then
67
+ echo "Missing tokenizer: ${TOKENIZER_PATH}" >&2
68
+ exit 2
69
+ fi
70
+ if [[ ! -d "${DATA_PATH}" ]]; then
71
+ echo "Missing tokenized dataset: ${DATA_PATH}" >&2
72
+ echo "Build it with: bash scripts/build_lta_lm1b_compact_gpt2bpe_v8192_stream128_np8.sh" >&2
73
+ exit 2
74
+ fi
75
+ if [[ -f "${SAVE_DIR}/args.json" && "${ALLOW_EXISTING_SAVE_DIR}" != "1" ]]; then
76
+ echo "Refusing to start because SAVE_DIR already contains args.json: ${SAVE_DIR}" >&2
77
+ exit 2
78
+ fi
79
+
80
+ mkdir -p "${LOG_DIR}" "${SAVE_DIR}"
81
+
82
+ TF32_FLAG="--allow_tf32"
83
+ TF32_LABEL="true"
84
+ if [[ "${ALLOW_TF32}" == "0" || "${ALLOW_TF32}" == "false" || "${ALLOW_TF32}" == "False" ]]; then
85
+ TF32_FLAG="--no-allow_tf32"
86
+ TF32_LABEL="false"
87
+ fi
88
+
89
+ NUM_EXAMPLES=$(python - <<PY
90
+ import json
91
+ from pathlib import Path
92
+ from datasets import Sequence, load_from_disk
93
+ from datasets.features import features as hf_features
94
+ hf_features._FEATURE_TYPES.setdefault("List", Sequence)
95
+ root = Path("${DATA_PATH}")
96
+ meta = root / "elf_multi_part_meta.json"
97
+ if meta.exists():
98
+ print(int(json.loads(meta.read_text()).get("num_examples", 0)))
99
+ else:
100
+ parts = root / "parts"
101
+ if parts.is_dir():
102
+ print(sum(len(load_from_disk(str(p))) for p in sorted(parts.iterdir()) if p.is_dir()))
103
+ else:
104
+ print(len(load_from_disk(str(root))))
105
+ PY
106
+ )
107
+
108
+ WORLD_SIZE=$(( NNODES * NPROC_PER_NODE ))
109
+ GRAD_ACCUM=$(( (GLOBAL_BATCH_SIZE + PER_GPU_BATCH_SIZE * WORLD_SIZE - 1) / (PER_GPU_BATCH_SIZE * WORLD_SIZE) ))
110
+
111
+ echo "[launch-lm1b-v8192] run_name=${RUN_NAME}"
112
+ echo "[launch-lm1b-v8192] save_dir=${SAVE_DIR}"
113
+ echo "[launch-lm1b-v8192] log_file=${LOG_FILE}"
114
+ echo "[launch-lm1b-v8192] data_path=${DATA_PATH}"
115
+ echo "[launch-lm1b-v8192] tokenizer=${TOKENIZER_PATH}"
116
+ echo "[launch-lm1b-v8192] examples=${NUM_EXAMPLES} max_len=128 total_steps=${TOTAL_STEPS} world_size=${WORLD_SIZE} grad_accum=${GRAD_ACCUM} save_every=${SAVE_EVERY}"
117
+ echo "[launch-lm1b-v8192] model=ddit d768 x12 h12 ff3072 rmsnorm no_bias dropout0"
118
+ echo "[launch-lm1b-v8192] recipe=dirichlet categorical_dual_t hard_ce target_prob1 mask=${MIN_MASK_RATIO}->${MAX_MASK_RATIO} t=${T_SAMPLING_MODE} tf32=${TF32_LABEL}"
119
+
120
+ if [[ "${DRY_RUN}" == "1" || "${DRY_RUN}" == "true" || "${DRY_RUN}" == "True" ]]; then
121
+ echo "[launch-lm1b-v8192] DRY_RUN=1, validated setup; skipping torchrun."
122
+ exit 0
123
+ fi
124
+
125
+ RESUME_ARGS=()
126
+ if [[ -n "${RESUME_PATH}" ]]; then
127
+ RESUME_ARGS+=(--resume_path "${RESUME_PATH}")
128
+ fi
129
+
130
+ python -m torch.distributed.run \
131
+ --nnodes="${NNODES}" \
132
+ --nproc_per_node="${NPROC_PER_NODE}" \
133
+ --node_rank="${NODE_RANK}" \
134
+ --master_addr="${MASTER_ADDR}" \
135
+ --master_port="${MASTER_PORT}" \
136
+ train.py \
137
+ "${RESUME_ARGS[@]}" \
138
+ --data_path "${DATA_PATH}" \
139
+ --tokenized_hf \
140
+ --tokenized_pad_token pad \
141
+ --tokenizer_path "${TOKENIZER_PATH}" \
142
+ --save_dir "${SAVE_DIR}" \
143
+ --max_len 128 \
144
+ --batch_size "${PER_GPU_BATCH_SIZE}" \
145
+ --global_batch_size "${GLOBAL_BATCH_SIZE}" \
146
+ --num_workers "${NUM_WORKERS}" \
147
+ --dataloader_prefetch_factor "${DATALOADER_PREFETCH_FACTOR}" \
148
+ --epochs 0 \
149
+ --total_steps "${TOTAL_STEPS}" \
150
+ --warmup_steps "${WARMUP_STEPS}" \
151
+ --log_every "${LOG_EVERY}" \
152
+ --eval_every "${EVAL_EVERY}" \
153
+ --save_every "${SAVE_EVERY}" \
154
+ --latest_every "${LATEST_EVERY}" \
155
+ --optimizer adamw \
156
+ --lr "${LR}" \
157
+ --lr_schedule cosine \
158
+ --min_lr "${MIN_LR}" \
159
+ --weight_decay "${WEIGHT_DECAY}" \
160
+ --output_weight_decay "${OUTPUT_WEIGHT_DECAY}" \
161
+ --adamw_param_groups nanogpt \
162
+ --adam_beta1 "${ADAM_BETA1}" \
163
+ --adam_beta2 "${ADAM_BETA2}" \
164
+ --adam_eps "${ADAM_EPS}" \
165
+ --ema_decay "${EMA_DECAY}" \
166
+ --ema_start_step "${EMA_START_STEP}" \
167
+ --grad_clip "${GRAD_CLIP}" \
168
+ --seed 123 \
169
+ --d_model 768 \
170
+ --cond_dim 128 \
171
+ --n_layers 12 \
172
+ --n_heads 12 \
173
+ --dim_ff 3072 \
174
+ --dropout 0.0 \
175
+ --no-output_bias \
176
+ --norm_type rmsnorm \
177
+ --model_type ddit \
178
+ --state_format prob \
179
+ --bridge dirichlet \
180
+ --target_loss hard_ce \
181
+ --loss_t_weight_mode "${LOSS_T_WEIGHT_MODE}" \
182
+ --loss_t_min_weight "${LOSS_T_MIN_WEIGHT}" \
183
+ --loss_t_drop_below "${LOSS_T_DROP_BELOW}" \
184
+ --target_prob 1.0 \
185
+ --min_t 0.0 \
186
+ --max_t 1.0 \
187
+ --t_sampling_mode "${T_SAMPLING_MODE}" \
188
+ --t_sampling_power "${T_SAMPLING_POWER}" \
189
+ --t_sampling_logit_mean "${T_SAMPLING_LOGIT_MEAN}" \
190
+ --t_sampling_logit_std "${T_SAMPLING_LOGIT_STD}" \
191
+ --t_sampling_eps "${T_SAMPLING_EPS}" \
192
+ --dual_t \
193
+ --corrupt_t_mode same \
194
+ --corrupt_min_t 0.0 \
195
+ --corrupt_max_t 1.0 \
196
+ --min_mask_ratio "${MIN_MASK_RATIO}" \
197
+ --max_mask_ratio "${MAX_MASK_RATIO}" \
198
+ --wrong_token_replace_prob 1.0 \
199
+ --wrong_token_schedule linear_t \
200
+ --wrong_token_exp_k 1.0 \
201
+ --dirichlet_concentration_min 1.0 \
202
+ --dirichlet_concentration_max 1024 \
203
+ --dirichlet_endpoint_mode categorical_dual_t \
204
+ --dirichlet_semantic_t_mode same \
205
+ --dirichlet_semantic_t_value 0.0 \
206
+ --categorical_wrong_from_full_vocab \
207
+ --simplex_bridge_sampler dirichlet \
208
+ --eps 1e-8 \
209
+ --infer_steps 128 \
210
+ --decode_damping 1.0 \
211
+ --max_gamma 1.0 \
212
+ --decode_solver flowmap \
213
+ --noise_init logistic_normal \
214
+ --bridge_noise_init logistic_normal \
215
+ --noise_sigma -1 \
216
+ "${TF32_FLAG}" \
217
+ --ddp_gradient_as_bucket_view \
218
+ 2>&1 | tee -a "${LOG_FILE}"
219
+
LTA_openwebtext_dualt/scripts/launch_lta_openwebtext_dualt_8gpu_aligned.sh ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
6
+ export TOKENIZERS_PARALLELISM=false
7
+ export PYTHONUNBUFFERED=1
8
+ export NCCL_DEBUG="${NCCL_DEBUG:-WARN}"
9
+ export TORCH_DISTRIBUTED_TIMEOUT="${TORCH_DISTRIBUTED_TIMEOUT:-3600}"
10
+
11
+ # FLM-repo-aligned engineering defaults:
12
+ # - GPT-2 OpenWebText split, wrapped fixed length 1024
13
+ # - DDiT small: 12 layers, d=768, 12 heads, FF=3072, adaLN-zero
14
+ # - global batch 512, per-GPU local batch 32 on 8 GPUs
15
+ # - bf16, flash-attn when available, torch.compile max-autotune
16
+ # - AdamW lr 3e-4, no weight decay, 2500 warmup, constant schedule
17
+ #
18
+ # Algorithm remains ours:
19
+ # - probability-state LTA
20
+ # - Dirichlet bridge
21
+ # - hard CE target and one-hot clean anchors/endpoints
22
+ # - wrong-token corruption is scheduled by corruption time: p_wrong = 1 - t_corrupt
23
+ # - dual-t: model/flow time is separate from corruption/support time
24
+
25
+ RUN_NAME="${RUN_NAME:-lta_owt_dirichlet_dualt_onehot_hardce_ddit_small_len1024_gbs512_8gpu}"
26
+ DATA_PATH="${DATA_PATH:-/e2e-data/evad-tech-vla/wanghan58/data/small_benchmarks/langflow_2604_11748/openwebtext}"
27
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/models/flowtext_scorers/gpt2-standard/tokenizer.json}"
28
+ SAVE_DIR="${SAVE_DIR:-runs/${RUN_NAME}}"
29
+ LOG_FILE="${LOG_FILE:-logs/${RUN_NAME}.log}"
30
+
31
+ NNODES="${NNODES:-1}"
32
+ NPROC_PER_NODE="${NPROC_PER_NODE:-8}"
33
+ NODE_RANK="${NODE_RANK:-0}"
34
+ MASTER_ADDR="${MASTER_ADDR:-127.0.0.1}"
35
+ MASTER_PORT="${MASTER_PORT:-29621}"
36
+
37
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
38
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-32}"
39
+ TOTAL_STEPS="${TOTAL_STEPS:-1500000}"
40
+ WARMUP_STEPS="${WARMUP_STEPS:-2500}"
41
+ MAX_LEN="${MAX_LEN:-1024}"
42
+ NUM_WORKERS="${NUM_WORKERS:-4}"
43
+ LOG_EVERY="${LOG_EVERY:-100}"
44
+ SAVE_EVERY="${SAVE_EVERY:-20000}"
45
+ EVAL_EVERY="${EVAL_EVERY:-0}"
46
+
47
+ mkdir -p logs runs "${SAVE_DIR}"
48
+
49
+ python -m torch.distributed.run \
50
+ --nnodes="${NNODES}" \
51
+ --nproc_per_node="${NPROC_PER_NODE}" \
52
+ --node_rank="${NODE_RANK}" \
53
+ --master_addr="${MASTER_ADDR}" \
54
+ --master_port="${MASTER_PORT}" \
55
+ train.py \
56
+ --data_path "${DATA_PATH}" \
57
+ --text_column text \
58
+ --openwebtext_split train_minus_100k \
59
+ --tokenizer_path "${TOKENIZER_PATH}" \
60
+ --save_dir "${SAVE_DIR}" \
61
+ --wrap \
62
+ --max_len "${MAX_LEN}" \
63
+ --batch_size "${PER_GPU_BATCH_SIZE}" \
64
+ --num_workers "${NUM_WORKERS}" \
65
+ --global_batch_size "${GLOBAL_BATCH_SIZE}" \
66
+ --total_steps "${TOTAL_STEPS}" \
67
+ --log_every "${LOG_EVERY}" \
68
+ --eval_every "${EVAL_EVERY}" \
69
+ --save_every "${SAVE_EVERY}" \
70
+ --lr 3e-4 \
71
+ --weight_decay 0 \
72
+ --adam_beta1 0.9 \
73
+ --adam_beta2 0.999 \
74
+ --adam_eps 1e-8 \
75
+ --warmup_steps "${WARMUP_STEPS}" \
76
+ --lr_schedule constant_warmup \
77
+ --grad_clip 1.0 \
78
+ --seed 123 \
79
+ --d_model 768 \
80
+ --cond_dim 128 \
81
+ --n_layers 12 \
82
+ --n_heads 12 \
83
+ --dim_ff 3072 \
84
+ --dropout 0.1 \
85
+ --model_type ddit \
86
+ --state_format prob \
87
+ --bridge dirichlet \
88
+ --target_loss hard_ce \
89
+ --target_prob 1.0 \
90
+ --min_t 0.0 \
91
+ --max_t 1.0 \
92
+ --dual_t \
93
+ --corrupt_t_mode independent \
94
+ --corrupt_min_t 0.0 \
95
+ --corrupt_max_t 1.0 \
96
+ --min_mask_ratio 0.1 \
97
+ --max_mask_ratio 1.0 \
98
+ --wrong_token_replace_prob 1.0 \
99
+ --wrong_token_schedule linear_t \
100
+ --wrong_token_exp_k 1.0 \
101
+ --dirichlet_concentration_min 1.0 \
102
+ --dirichlet_concentration_max 1024.0 \
103
+ --eps 1e-8 \
104
+ --infer_steps 1024 \
105
+ --decode_damping 1.0 \
106
+ --max_gamma 1.0 \
107
+ --decode_solver flowmap \
108
+ --noise_init logistic_normal \
109
+ --bridge_noise_init logistic_normal \
110
+ --noise_sigma -1 \
111
+ --torch_compile \
112
+ --compile_mode max-autotune \
113
+ --bf16 2>&1 | tee -a "${LOG_FILE}"
LTA_openwebtext_dualt/scripts/launch_lta_owt_compact_gpt2bpe_v2048_elfaligned_logitnormal_tokenized_8gpu.sh ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ export VOCAB_SIZE=2048
7
+ export DATA_PATH="${DATA_PATH:-/e2e-data/evad-tech-vla/wanghan58/data/embedded-language-flows/openwebtext-compact-gpt2bpe-v2048-stream1024-train-minus-100k}"
8
+ export TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/models/lta_tokenizers/owt_compact_gpt2bpe_v2048/tokenizer.json}"
9
+
10
+ export CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7}"
11
+ export NPROC_PER_NODE="${NPROC_PER_NODE:-8}"
12
+ export MASTER_PORT="${MASTER_PORT:-32241}"
13
+
14
+ export GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
15
+ export PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-32}"
16
+ export EPOCHS="${EPOCHS:-5}"
17
+ export NUM_WORKERS="${NUM_WORKERS:-8}"
18
+ export LOG_EVERY="${LOG_EVERY:-100}"
19
+ export LATEST_EVERY="${LATEST_EVERY:-1000}"
20
+ export EVAL_EVERY="${EVAL_EVERY:-0}"
21
+
22
+ # Same recipe as the current OWT ELF-aligned runs: fp32 params/activations,
23
+ # TF32 matmul allowed, RMSNorm, no output bias, Muon+Adam fallback wd=0.1.
24
+ export ALLOW_TF32="${ALLOW_TF32:-1}"
25
+ export TARGET_LOSS="${TARGET_LOSS:-hard_ce}"
26
+ export T_LOGIT_MEAN="${T_LOGIT_MEAN:--1.5}"
27
+ export T_LOGIT_STD="${T_LOGIT_STD:-0.8}"
28
+ export WEIGHT_DECAY="${WEIGHT_DECAY:-0.1}"
29
+ export OUTPUT_INIT_STD="${OUTPUT_INIT_STD:-0.0}"
30
+
31
+ export LOG_DIR="${LOG_DIR:-logs/compact_gpt2bpe_v2048_stream1024_8gpu}"
32
+ export RUN_NAME="${RUN_NAME:-lta_owt_compact_gpt2bpe_v2048_stream1024_elfaligned_dditelf_muon_logitnormal_m1p5_s0p8_hardce_wd0p1_gbs512_8gpu_5epoch_$(date +%Y%m%d_%H%M%S)}"
33
+
34
+ exec bash scripts/launch_lta_owt_compact_gpt2bpe_elfaligned_logitnormal_tokenized_8gpu.sh "$@"
LTA_openwebtext_dualt/scripts/launch_lta_owt_fullycoupled_logitnormal_mid_mask1_wd0p1_fp32_8gpu.sh ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ export CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7}"
7
+ export OMP_NUM_THREADS="${OMP_NUM_THREADS:-1}"
8
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
9
+ export TOKENIZERS_PARALLELISM=false
10
+ export PYTHONUNBUFFERED=1
11
+ export NCCL_DEBUG="${NCCL_DEBUG:-WARN}"
12
+ export TORCH_DISTRIBUTED_TIMEOUT="${TORCH_DISTRIBUTED_TIMEOUT:-3600}"
13
+
14
+ # Fully-coupled OWT baseline with FP32 params/activations and nanoGPT-style AdamW decay:
15
+ # decay: matrix / embedding params (p.dim() >= 2)
16
+ # no decay: bias / norm / 1D params
17
+ # This intentionally does NOT pass --bf16. TF32 is enabled by default so H200 uses
18
+ # Tensor Cores; set ALLOW_TF32=0 for strict FP32 debugging.
19
+
20
+ T_SAMPLING_MODE="${T_SAMPLING_MODE:-logit_normal}"
21
+ T_SAMPLING_POWER="${T_SAMPLING_POWER:-1.0}"
22
+ T_SAMPLING_EPS="${T_SAMPLING_EPS:-1e-4}"
23
+ T_SAMPLING_LOGIT_MEAN="${T_SAMPLING_LOGIT_MEAN:--0.22}"
24
+ T_SAMPLING_LOGIT_STD="${T_SAMPLING_LOGIT_STD:-0.5}"
25
+ MIN_MASK_RATIO="${MIN_MASK_RATIO:-1.0}"
26
+ MAX_MASK_RATIO="${MAX_MASK_RATIO:-1.0}"
27
+ DDIT_MLP_TYPE="${DDIT_MLP_TYPE:-swiglu}"
28
+
29
+ sanitize_label() {
30
+ printf "%s" "$1" | sed -e 's/-/m/g' -e 's/\./p/g'
31
+ }
32
+
33
+ T_LOGIT_MEAN_LABEL="$(sanitize_label "${T_SAMPLING_LOGIT_MEAN}")"
34
+ T_LOGIT_STD_LABEL="$(sanitize_label "${T_SAMPLING_LOGIT_STD}")"
35
+ MIN_MASK_RATIO_LABEL="$(sanitize_label "${MIN_MASK_RATIO}")"
36
+ MAX_MASK_RATIO_LABEL="$(sanitize_label "${MAX_MASK_RATIO}")"
37
+
38
+ RUN_NAME="${RUN_NAME:-lta_owt_gpt2cached_len1024_fullycoupled_rmsnorm_nobias_${DDIT_MLP_TYPE}_adamw_wd0p1_logitnormal_mid_${T_LOGIT_MEAN_LABEL}_s${T_LOGIT_STD_LABEL}_hardce_mask${MIN_MASK_RATIO_LABEL}-${MAX_MASK_RATIO_LABEL}_nanogpt_fp32_ddit768x12_gbs512_8gpu_1m_$(date +%Y%m%d_%H%M%S)}"
39
+ SAVE_DIR="${SAVE_DIR:-runs/${RUN_NAME}}"
40
+ LOG_DIR="${LOG_DIR:-logs/fullycoupled_logitnormal_mid_mask1_wd0p1_fp32_8gpu}"
41
+ LOG_FILE="${LOG_FILE:-${LOG_DIR}/${RUN_NAME}.log}"
42
+
43
+ DATA_PATH="${DATA_PATH:-/e2e-data/evad-tech-vla/wanghan58/data/small_benchmarks/langflow_2604_11748/openwebtext}"
44
+ OWT_CACHE="${OWT_CACHE:-/e2e-data/evad-tech-vla/wanghan58/data/small_benchmarks/langflow_2604_11748/openwebtext_lta_cached_chunks/gpt2_len1024_train_minus_100k}"
45
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/models/flowtext_scorers/gpt2-standard/tokenizer.json}"
46
+
47
+ NNODES="${NNODES:-1}"
48
+ NPROC_PER_NODE="${NPROC_PER_NODE:-8}"
49
+ NODE_RANK="${NODE_RANK:-0}"
50
+ MASTER_ADDR="${MASTER_ADDR:-127.0.0.1}"
51
+ MASTER_PORT="${MASTER_PORT:-31997}"
52
+
53
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-32}"
54
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
55
+ TOTAL_STEPS="${TOTAL_STEPS:-1000000}"
56
+ WARMUP_STEPS="${WARMUP_STEPS:-2000}"
57
+ NUM_WORKERS="${NUM_WORKERS:-8}"
58
+ DATALOADER_PREFETCH_FACTOR="${DATALOADER_PREFETCH_FACTOR:-4}"
59
+ LOG_EVERY="${LOG_EVERY:-50}"
60
+ SAVE_EVERY="${SAVE_EVERY:-50000}"
61
+ LATEST_EVERY="${LATEST_EVERY:-1000}"
62
+ EVAL_EVERY="${EVAL_EVERY:-0}"
63
+ ALLOW_EXISTING_SAVE_DIR="${ALLOW_EXISTING_SAVE_DIR:-0}"
64
+ ALLOW_TF32="${ALLOW_TF32:-1}"
65
+ DRY_RUN="${DRY_RUN:-0}"
66
+
67
+ LR="${LR:-6e-4}"
68
+ MIN_LR="${MIN_LR:-6e-5}"
69
+ WEIGHT_DECAY="${WEIGHT_DECAY:-0.1}"
70
+ OUTPUT_WEIGHT_DECAY="${OUTPUT_WEIGHT_DECAY:--1}"
71
+ ADAM_BETA1="${ADAM_BETA1:-0.9}"
72
+ ADAM_BETA2="${ADAM_BETA2:-0.95}"
73
+ ADAM_EPS="${ADAM_EPS:-1e-8}"
74
+ GRAD_CLIP="${GRAD_CLIP:-1.0}"
75
+ EMA_DECAY="${EMA_DECAY:-0.0}"
76
+ EMA_START_STEP="${EMA_START_STEP:-0}"
77
+ LOSS_T_WEIGHT_MODE="${LOSS_T_WEIGHT_MODE:-none}"
78
+ LOSS_T_MIN_WEIGHT="${LOSS_T_MIN_WEIGHT:-0.0}"
79
+ LOSS_T_DROP_BELOW="${LOSS_T_DROP_BELOW:-0.2}"
80
+
81
+ if [[ -f "${SAVE_DIR}/args.json" && "${ALLOW_EXISTING_SAVE_DIR}" != "1" ]]; then
82
+ echo "Refusing to start because SAVE_DIR already contains args.json: ${SAVE_DIR}" >&2
83
+ echo "Use a new RUN_NAME/SAVE_DIR or set ALLOW_EXISTING_SAVE_DIR=1 intentionally." >&2
84
+ exit 2
85
+ fi
86
+
87
+ mkdir -p "${LOG_DIR}" "${SAVE_DIR}"
88
+
89
+ TF32_FLAG="--allow_tf32"
90
+ TF32_LABEL="true"
91
+ if [[ "${ALLOW_TF32}" == "0" || "${ALLOW_TF32}" == "false" || "${ALLOW_TF32}" == "False" ]]; then
92
+ TF32_FLAG="--no-allow_tf32"
93
+ TF32_LABEL="false"
94
+ fi
95
+
96
+ echo "[launch] method=owt_fullycoupled_adamw_wd0p1_nanogpt_fp32 host=$(hostname) time=$(date -Iseconds)"
97
+ echo "[launch] run_name=${RUN_NAME}"
98
+ echo "[launch] save_dir=${SAVE_DIR}"
99
+ echo "[launch] log_file=${LOG_FILE}"
100
+ echo "[launch] data_path=${DATA_PATH}"
101
+ echo "[launch] owt_cache=${OWT_CACHE}"
102
+ echo "[launch] optimizer=adamw lr=${LR} min_lr=${MIN_LR} wd=${WEIGHT_DECAY} output_wd=${OUTPUT_WEIGHT_DECAY} param_groups=nanogpt ema=${EMA_DECAY}"
103
+ echo "[launch] fp32=true bf16=false tf32=${TF32_LABEL} norm_type=rmsnorm output_bias=false ddit_mlp_type=${DDIT_MLP_TYPE} batch=${GLOBAL_BATCH_SIZE} per_gpu=${PER_GPU_BATCH_SIZE}"
104
+ echo "[launch] loss_t_weight_mode=${LOSS_T_WEIGHT_MODE} loss_t_min_weight=${LOSS_T_MIN_WEIGHT} loss_t_drop_below=${LOSS_T_DROP_BELOW}"
105
+ echo "[launch] target_loss=hard_ce t_sampling_mode=${T_SAMPLING_MODE} t_sampling_logit_mean=${T_SAMPLING_LOGIT_MEAN} t_sampling_logit_std=${T_SAMPLING_LOGIT_STD} t_sampling_power=${T_SAMPLING_POWER} t_sampling_eps=${T_SAMPLING_EPS} mask_ratio=${MIN_MASK_RATIO}->${MAX_MASK_RATIO}"
106
+
107
+ if [[ "${DRY_RUN}" == "1" || "${DRY_RUN}" == "true" || "${DRY_RUN}" == "True" ]]; then
108
+ echo "[launch] DRY_RUN=1, validated launch parameters; skipping torchrun."
109
+ exit 0
110
+ fi
111
+
112
+ python -m torch.distributed.run \
113
+ --nnodes="${NNODES}" \
114
+ --nproc_per_node="${NPROC_PER_NODE}" \
115
+ --node_rank="${NODE_RANK}" \
116
+ --master_addr="${MASTER_ADDR}" \
117
+ --master_port="${MASTER_PORT}" \
118
+ train.py \
119
+ --data_path "${DATA_PATH}" \
120
+ --openwebtext_split train_minus_100k \
121
+ --text_column text \
122
+ --detokenizer auto \
123
+ --tokenizer_path "${TOKENIZER_PATH}" \
124
+ --save_dir "${SAVE_DIR}" \
125
+ --wrap \
126
+ --wrap_mode stream \
127
+ --owt_cached_chunks \
128
+ --owt_chunk_cache_dir "${OWT_CACHE}" \
129
+ --max_len 1024 \
130
+ --batch_size "${PER_GPU_BATCH_SIZE}" \
131
+ --global_batch_size "${GLOBAL_BATCH_SIZE}" \
132
+ --num_workers "${NUM_WORKERS}" \
133
+ --dataloader_prefetch_factor "${DATALOADER_PREFETCH_FACTOR}" \
134
+ --total_steps "${TOTAL_STEPS}" \
135
+ --warmup_steps "${WARMUP_STEPS}" \
136
+ --log_every "${LOG_EVERY}" \
137
+ --eval_every "${EVAL_EVERY}" \
138
+ --save_every "${SAVE_EVERY}" \
139
+ --latest_every "${LATEST_EVERY}" \
140
+ --optimizer adamw \
141
+ --lr "${LR}" \
142
+ --lr_schedule cosine \
143
+ --min_lr "${MIN_LR}" \
144
+ --weight_decay "${WEIGHT_DECAY}" \
145
+ --output_weight_decay "${OUTPUT_WEIGHT_DECAY}" \
146
+ --adamw_param_groups nanogpt \
147
+ --adam_beta1 "${ADAM_BETA1}" \
148
+ --adam_beta2 "${ADAM_BETA2}" \
149
+ --adam_eps "${ADAM_EPS}" \
150
+ --ema_decay "${EMA_DECAY}" \
151
+ --ema_start_step "${EMA_START_STEP}" \
152
+ --grad_clip "${GRAD_CLIP}" \
153
+ --seed 123 \
154
+ --d_model 768 \
155
+ --cond_dim 128 \
156
+ --n_layers 12 \
157
+ --n_heads 12 \
158
+ --dim_ff 3072 \
159
+ --dropout 0.0 \
160
+ --no-output_bias \
161
+ --norm_type rmsnorm \
162
+ --model_type ddit \
163
+ --ddit_mlp_type "${DDIT_MLP_TYPE}" \
164
+ --state_format prob \
165
+ --bridge dirichlet \
166
+ --target_loss hard_ce \
167
+ --loss_t_weight_mode "${LOSS_T_WEIGHT_MODE}" \
168
+ --loss_t_min_weight "${LOSS_T_MIN_WEIGHT}" \
169
+ --loss_t_drop_below "${LOSS_T_DROP_BELOW}" \
170
+ --target_prob 1.0 \
171
+ --min_t 0.0 \
172
+ --max_t 1.0 \
173
+ --t_sampling_mode "${T_SAMPLING_MODE}" \
174
+ --t_sampling_power "${T_SAMPLING_POWER}" \
175
+ --t_sampling_logit_mean "${T_SAMPLING_LOGIT_MEAN}" \
176
+ --t_sampling_logit_std "${T_SAMPLING_LOGIT_STD}" \
177
+ --t_sampling_eps "${T_SAMPLING_EPS}" \
178
+ --dual_t \
179
+ --corrupt_t_mode same \
180
+ --corrupt_min_t 0.0 \
181
+ --corrupt_max_t 1.0 \
182
+ --min_mask_ratio "${MIN_MASK_RATIO}" \
183
+ --max_mask_ratio "${MAX_MASK_RATIO}" \
184
+ --wrong_token_replace_prob 1.0 \
185
+ --wrong_token_schedule linear_t \
186
+ --wrong_token_exp_k 1.0 \
187
+ --dirichlet_concentration_min 1.0 \
188
+ --dirichlet_concentration_max 1024 \
189
+ --dirichlet_endpoint_mode categorical_dual_t \
190
+ --dirichlet_semantic_t_mode same \
191
+ --dirichlet_semantic_t_value 0.0 \
192
+ --categorical_wrong_from_full_vocab \
193
+ --simplex_bridge_sampler dirichlet \
194
+ --eps 1e-8 \
195
+ --infer_steps 1024 \
196
+ --decode_damping 1.0 \
197
+ --max_gamma 1.0 \
198
+ --decode_solver flowmap \
199
+ --noise_init logistic_normal \
200
+ --bridge_noise_init logistic_normal \
201
+ --noise_sigma -1 \
202
+ "${TF32_FLAG}" \
203
+ --ddp_gradient_as_bucket_view \
204
+ 2>&1 | tee -a "${LOG_FILE}"
LTA_openwebtext_dualt/scripts/launch_lta_owt_t5_adaln_adamw_wd0p1_rollin_grad_k1_rho025_8gpu.sh ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+ set -x
4
+ set -o pipefail
5
+
6
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
7
+
8
+ # Use the repo's normal Python/torchrun by default. Set ACTIVATE_ENV only if
9
+ # that environment is known to include torch, datasets, and tokenizers.
10
+ if [[ -n "${ACTIVATE_ENV:-}" ]]; then
11
+ source "${ACTIVATE_ENV}"
12
+ fi
13
+
14
+ free_port() {
15
+ python3 - <<'PY'
16
+ import socket
17
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
18
+ s.bind(("127.0.0.1", 0))
19
+ print(s.getsockname()[1])
20
+ PY
21
+ }
22
+
23
+ export CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7}"
24
+ export NPROC_PER_NODE="${NPROC_PER_NODE:-8}"
25
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
26
+ export TOKENIZERS_PARALLELISM=false
27
+ export PYTHONUNBUFFERED=1
28
+ export NCCL_DEBUG="${NCCL_DEBUG:-WARN}"
29
+ export TORCH_NCCL_AVOID_RECORD_STREAMS=1
30
+ export TORCH_DISTRIBUTED_TIMEOUT="${TORCH_DISTRIBUTED_TIMEOUT:-3600}"
31
+
32
+ DATA_PATH="${DATA_PATH:-/e2e-data/evad-tech-vla/wanghan58/data/embedded-language-flows/openwebtext-t5}"
33
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/models/hf/t5-small/tokenizer.json}"
34
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
35
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-32}"
36
+ TOTAL_STEPS="${TOTAL_STEPS:-1000000}"
37
+ MASTER_PORT="${MASTER_PORT:-$(free_port)}"
38
+ LOG_DIR="${LOG_DIR:-logs/elfaligned_t5tokenized_8gpu}"
39
+
40
+ RUN_NAME="${RUN_NAME:-lta_owt_t5_adaln_adamw_wd0p1_rollin_grad_p50_k1_rho0_0p25_uniformt_temp1_synct_gbs${GLOBAL_BATCH_SIZE}_8gpu_1m_$(date +%Y%m%d_%H%M%S)}"
41
+ LOG_FILE="${LOG_FILE:-${LOG_DIR}/${RUN_NAME}.log}"
42
+
43
+ mkdir -p "${LOG_DIR}" "runs/${RUN_NAME}"
44
+
45
+ python - <<'PY'
46
+ import sys
47
+ import torch
48
+ import tokenizers
49
+
50
+ print(f"[launch] python={sys.executable}")
51
+ print(f"[launch] torch={torch.__version__} tokenizers={tokenizers.__version__}")
52
+ PY
53
+
54
+ echo "[launch] run_name=${RUN_NAME}" | tee -a "${LOG_FILE}"
55
+ echo "[launch] cuda=${CUDA_VISIBLE_DEVICES} nproc_per_node=${NPROC_PER_NODE} master_port=${MASTER_PORT}" | tee -a "${LOG_FILE}"
56
+ echo "[launch] global_batch_size=${GLOBAL_BATCH_SIZE} per_gpu_batch_size=${PER_GPU_BATCH_SIZE} total_steps=${TOTAL_STEPS}" | tee -a "${LOG_FILE}"
57
+ echo "[launch] rollout=keep_grad,p50,K1,rhoU0_0p25,sync_t" | tee -a "${LOG_FILE}"
58
+ echo "[launch] data_path=${DATA_PATH}" | tee -a "${LOG_FILE}"
59
+ echo "[launch] tokenizer=${TOKENIZER_PATH}" | tee -a "${LOG_FILE}"
60
+ echo "[launch] log_file=${LOG_FILE}" | tee -a "${LOG_FILE}"
61
+
62
+ torchrun \
63
+ --nproc_per_node="${NPROC_PER_NODE}" \
64
+ --master_port="${MASTER_PORT}" \
65
+ train.py \
66
+ --data_path "${DATA_PATH}" \
67
+ --tokenized_hf \
68
+ --tokenized_pad_token pad \
69
+ --tokenizer_path "${TOKENIZER_PATH}" \
70
+ --save_dir "runs/${RUN_NAME}" \
71
+ --max_len 1024 \
72
+ --batch_size "${PER_GPU_BATCH_SIZE}" \
73
+ --global_batch_size "${GLOBAL_BATCH_SIZE}" \
74
+ --num_workers 8 \
75
+ --dataloader_prefetch_factor 4 \
76
+ --epochs 0 \
77
+ --total_steps "${TOTAL_STEPS}" \
78
+ --warmup_steps 1000 \
79
+ --log_every 100 \
80
+ --eval_every 0 \
81
+ --save_every 10000 \
82
+ --latest_every 1000 \
83
+ --optimizer adamw \
84
+ --lr 6e-4 \
85
+ --lr_schedule cosine \
86
+ --min_lr 6e-5 \
87
+ --weight_decay 0.1 \
88
+ --output_weight_decay -1 \
89
+ --adamw_param_groups nanogpt \
90
+ --adam_beta1 0.9 \
91
+ --adam_beta2 0.999 \
92
+ --adam_eps 1e-8 \
93
+ --ema_decay 0.9999 \
94
+ --ema_start_step 0 \
95
+ --grad_clip 1.0 \
96
+ --seed 42 \
97
+ --d_model 768 \
98
+ --cond_dim 128 \
99
+ --n_layers 12 \
100
+ --n_heads 12 \
101
+ --dim_ff 3072 \
102
+ --dropout 0.0 \
103
+ --no-output_bias \
104
+ --norm_type rmsnorm \
105
+ --model_type ddit \
106
+ --ddit_mlp_type swiglu \
107
+ --state_format prob \
108
+ --bridge dirichlet \
109
+ --target_loss hard_ce \
110
+ --loss_t_weight_mode none \
111
+ --loss_t_min_weight 0.0 \
112
+ --rollout_train_prob 0.50 \
113
+ --rollout_train_time_mode sampled_path \
114
+ --rollout_train_steps 1 \
115
+ --rollout_train_steps_min 1 \
116
+ --rollout_train_infer_steps 1 \
117
+ --rollout_train_s_dist uniform \
118
+ --rollout_train_s_min_frac 0.0 \
119
+ --rollout_train_s_max_frac 0.25 \
120
+ --rollout_train_temp 1.0 \
121
+ --rollout_train_max_gamma 1.0 \
122
+ --rollout_train_corrupt_only \
123
+ --rollout_train_samplewise \
124
+ --rollout_train_selected_only \
125
+ --no-rollout_train_compute_always \
126
+ --rollout_train_keep_grad \
127
+ --rollout_train_sync_t \
128
+ --target_prob 1.0 \
129
+ --min_t 0.0 \
130
+ --max_t 1.0 \
131
+ --t_sampling_mode uniform \
132
+ --t_sampling_logit_mean -1.5 \
133
+ --t_sampling_logit_std 0.8 \
134
+ --t_sampling_eps 1e-4 \
135
+ --dual_t \
136
+ --corrupt_t_mode same \
137
+ --corrupt_min_t 0.0 \
138
+ --corrupt_max_t 1.0 \
139
+ --min_mask_ratio 1.0 \
140
+ --max_mask_ratio 1.0 \
141
+ --mask_mixture_original_prob 0.0 \
142
+ --mask_mixture_lowk_prob 0.0 \
143
+ --mask_mixture_lowcorrupt_prob 0.0 \
144
+ --mask_mixture_block_prob 0.0 \
145
+ --mask_mixture_all_prob 1.0 \
146
+ --wrong_token_replace_prob 1.0 \
147
+ --wrong_token_schedule linear_t \
148
+ --wrong_token_exp_k 1.0 \
149
+ --dirichlet_concentration_min 1.0 \
150
+ --dirichlet_concentration_max 1024 \
151
+ --dirichlet_endpoint_mode categorical_dual_t \
152
+ --dirichlet_semantic_t_mode same \
153
+ --dirichlet_semantic_t_value 0.0 \
154
+ --categorical_wrong_from_full_vocab \
155
+ --simplex_bridge_sampler dirichlet \
156
+ --eps 1e-8 \
157
+ --infer_steps 1024 \
158
+ --decode_damping 1.0 \
159
+ --max_gamma 1.0 \
160
+ --decode_solver flowmap \
161
+ --noise_init logistic_normal \
162
+ --bridge_noise_init logistic_normal \
163
+ --noise_sigma -1 \
164
+ --allow_tf32 \
165
+ --activation_checkpointing \
166
+ --activation_checkpoint_scope mlp \
167
+ --ddp_gradient_as_bucket_view \
168
+ 2>&1 | tee -a "${LOG_FILE}"
LTA_openwebtext_dualt/scripts/make_duo_integral_cache.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import pickle
6
+ import time
7
+ from pathlib import Path
8
+
9
+ import numpy as np
10
+ from scipy.integrate import quad
11
+ from scipy.stats import norm
12
+
13
+
14
+ def _discrete_prob_map(gamma_t: float, vocab_size: int):
15
+ snr_sqrt = np.exp(-gamma_t / 2)
16
+
17
+ def value(x):
18
+ cdf = norm.cdf(x, scale=1) ** (vocab_size - 1)
19
+ pdf = norm.pdf(x, loc=snr_sqrt, scale=1)
20
+ return pdf * cdf
21
+
22
+ return value
23
+
24
+
25
+ def _discrete_prob_grad(gamma_t: float, vocab_size: int):
26
+ snr_sqrt = np.exp(-gamma_t / 2)
27
+
28
+ def value(x):
29
+ coef = -0.5 * snr_sqrt * (x - snr_sqrt)
30
+ cdf = norm.cdf(x, scale=1) ** (vocab_size - 1)
31
+ pdf = norm.pdf(x, loc=snr_sqrt, scale=1)
32
+ return coef * pdf * cdf
33
+
34
+ return value
35
+
36
+
37
+ def main() -> None:
38
+ p = argparse.ArgumentParser()
39
+ p.add_argument("--vocab_size", type=int, required=True)
40
+ p.add_argument("--log10_num_points", type=int, default=5)
41
+ p.add_argument("--output", required=True)
42
+ p.add_argument("--gamma_min", type=float, default=-5.0)
43
+ p.add_argument("--gamma_max", type=float, default=-1.0)
44
+ args = p.parse_args()
45
+
46
+ output = Path(args.output)
47
+ output.parent.mkdir(parents=True, exist_ok=True)
48
+ num_points = 10 ** int(args.log10_num_points)
49
+ gammas = np.linspace(args.gamma_min, args.gamma_max, num_points)
50
+ pt = []
51
+ grad_pt = []
52
+ start = time.time()
53
+ for i, gamma in enumerate(gammas, start=1):
54
+ val, _ = quad(_discrete_prob_map(float(gamma), args.vocab_size), -np.inf, np.inf)
55
+ grad, _ = quad(_discrete_prob_grad(float(gamma), args.vocab_size), -np.inf, np.inf)
56
+ pt.append(val)
57
+ grad_pt.append(grad)
58
+ if i % 100 == 0 or i == num_points:
59
+ print(f"{100 * i / num_points:.1f}% completed elapsed={(time.time() - start) / 60:.2f}m", flush=True)
60
+
61
+ payload = {
62
+ "vocab_size": args.vocab_size,
63
+ "gamma_min": args.gamma_min,
64
+ "gamma_max": args.gamma_max,
65
+ "num_points": num_points,
66
+ "pt": np.asarray(pt),
67
+ "grad_pt": np.asarray(grad_pt),
68
+ }
69
+ tmp = output.with_suffix(output.suffix + ".tmp")
70
+ with tmp.open("wb") as f:
71
+ pickle.dump(payload, f)
72
+ tmp.replace(output)
73
+ print(f"wrote {output}", flush=True)
74
+
75
+
76
+ if __name__ == "__main__":
77
+ main()
LTA_openwebtext_dualt/scripts/prepare_elf_wmt14_deen_t5.sh ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
6
+
7
+ DATA_ROOT="${DATA_ROOT:-/e2e-data/evad-tech-vla/wanghan58/data/small_benchmarks/elf}"
8
+ CACHE_DIR="${CACHE_DIR:-/e2e-data/evad-tech-vla/wanghan58/data/hf_cache}"
9
+ mkdir -p "${DATA_ROOT}" "${CACHE_DIR}"
10
+
11
+ python - <<'PY'
12
+ from pathlib import Path
13
+ from datasets import load_from_disk
14
+ from huggingface_hub import snapshot_download
15
+
16
+ data_root = Path(__import__("os").environ["DATA_ROOT"])
17
+ cache_dir = __import__("os").environ["CACHE_DIR"]
18
+ repos = {
19
+ "embedded-language-flows/wmt14_de-en_train_t5": data_root / "wmt14_de-en_train_t5",
20
+ "embedded-language-flows/wmt14_de-en_validation_t5": data_root / "wmt14_de-en_validation_t5",
21
+ }
22
+ for repo, out_dir in repos.items():
23
+ if out_dir.exists():
24
+ print(f"[skip] {out_dir} already exists")
25
+ continue
26
+ print(f"[download] {repo}")
27
+ snap = snapshot_download(repo_id=repo, repo_type="dataset", cache_dir=cache_dir)
28
+ ds = load_from_disk(snap)
29
+ print(f"[save] {repo}: rows={len(ds)} -> {out_dir}")
30
+ ds.save_to_disk(str(out_dir))
31
+ print("[done]")
32
+ PY
LTA_openwebtext_dualt/scripts/run_lta_lm1b_bert_absrope_time4_dirichlet_len128_C1_to_1024_4gpu_1m_mask1_sameT_save1k.sh ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ # Apple-to-apple control for:
7
+ # run_lta_owt_bert_absrope_time4_dirichlet_len128_C1_to_1024_4gpu_1m_mask1_sameT_save1k.sh
8
+ #
9
+ # Only swap the training data to LM1B. Keep:
10
+ # BERT tokenizer, [CLS]/[SEP] wrapping, max_len=128, 4 GPUs,
11
+ # ddit_elf + 4 time tokens + RoPE + learned abs position embeddings,
12
+ # C=1->1024, mask_ratio=1.0, corrupt/model t shared,
13
+ # every-1k checkpoint + dual-line watcher inference.
14
+
15
+ export DATA_PATH="${DATA_PATH:-data/lm1b_train_parquet}"
16
+ export TEXT_COLUMN="${TEXT_COLUMN:-text}"
17
+ export OPENWEBTEXT_SPLIT="${OPENWEBTEXT_SPLIT:-all}"
18
+ export TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/workspace/imagenet_handoff_20260327/nlp_dts_light/assets/distilbert-base-uncased/tokenizer.json}"
19
+ export TOKENIZED_HF=0
20
+ export WRAP_MODE="${WRAP_MODE:-stream}"
21
+
22
+ export DATE_TAG="${DATE_TAG:-$(date +%Y%m%d)}"
23
+ export RUN_NAME="${RUN_NAME:-lta_lm1b_bert_absrope_time4_dirichlet_len128_C1_to_1024_mask1_sameT_gbs512_b32_4gpu_1m_save1k_${DATE_TAG}}"
24
+
25
+ export MASTER_PORT="${MASTER_PORT:-32761}"
26
+ export WATCH_LOG_DIR="${WATCH_LOG_DIR:-logs/lm1b_bert_absrope_time4_len128_C1_to_1024_mask1_sameT_every1k_dualline_watch}"
27
+ export WATCH_OUT_BASE="${WATCH_OUT_BASE:-docs/lta_samples/metrics_${DATE_TAG}/lm1b_bert_absrope_time4_len128_C1_to_1024_mask1_sameT_every1k_dualline_dirres_c1_1024_n128/${RUN_NAME}}"
28
+
29
+ bash scripts/run_lta_owt_bert_absrope_time4_dirichlet_len128_C1_to_1024_4gpu_1m_mask1_sameT_save1k.sh
LTA_openwebtext_dualt/scripts/run_lta_owt_dirichlet_len1024_Cv_to_2v_4gpu_abspos_specialloss_watch.sh ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ export CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0,1,2,3}"
7
+ export NPROC_PER_NODE="${NPROC_PER_NODE:-4}"
8
+ export MASTER_PORT="${MASTER_PORT:-32674}"
9
+
10
+ export GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
11
+ export PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-4}"
12
+ export TOTAL_STEPS="${TOTAL_STEPS:-20000}"
13
+ export WARMUP_STEPS="${WARMUP_STEPS:-2500}"
14
+ export SAVE_EVERY="${SAVE_EVERY:-1000}"
15
+ export LATEST_EVERY="${LATEST_EVERY:-1000}"
16
+ export LOG_EVERY="${LOG_EVERY:-100}"
17
+
18
+ export MAX_LEN="${MAX_LEN:-1024}"
19
+ export VOCAB_SIZE="${VOCAB_SIZE:-30522}"
20
+ export CMIN="${CMIN:-${VOCAB_SIZE}}"
21
+ export CMAX="${CMAX:-61044}"
22
+
23
+ export ABS_POS_EMBED="${ABS_POS_EMBED:-1}"
24
+ export FORCE_SPECIAL_CORRUPT_TOKEN_IDS="${FORCE_SPECIAL_CORRUPT_TOKEN_IDS:-101,102}"
25
+ export SPECIAL_LOSS_TOKEN_IDS="${SPECIAL_LOSS_TOKEN_IDS:-101,102}"
26
+ export SPECIAL_LOSS_WEIGHT="${SPECIAL_LOSS_WEIGHT:-16.0}"
27
+ # Keep Bernoulli wrong input endpoints for specials in the first causal test.
28
+ export SPECIAL_ENDPOINT_GOLD_TOKEN_IDS="${SPECIAL_ENDPOINT_GOLD_TOKEN_IDS:-}"
29
+
30
+ export MIN_MASK_RATIO="${MIN_MASK_RATIO:-0.1}"
31
+ export MAX_MASK_RATIO="${MAX_MASK_RATIO:-1.0}"
32
+ export CATEGORICAL_WRONG_PROB_FLOOR="${CATEGORICAL_WRONG_PROB_FLOOR:-0.0}"
33
+
34
+ export WATCH_ENABLED="${WATCH_ENABLED:-1}"
35
+ export WATCH_CUDA_VISIBLE_DEVICES="${WATCH_CUDA_VISIBLE_DEVICES:-3}"
36
+ export WATCH_STEP_INTERVAL="${WATCH_STEP_INTERVAL:-1000}"
37
+ export WATCH_N_SAMPLES="${WATCH_N_SAMPLES:-128}"
38
+
39
+ DATE_TAG="${DATE_TAG:-$(date +%Y%m%d)}"
40
+ export RUN_NAME="${RUN_NAME:-lta_owt_dirichlet_len1024_Cv_to_2v_gbs512_4gpu_abspos_specialloss16_save1k_gumbelwatch_${DATE_TAG}}"
41
+
42
+ bash scripts/run_lta_owt_dirichlet_len1024_Cv_to_2v_8gpu_save1k_with_gumbel_watch.sh
LTA_openwebtext_dualt/scripts/run_lta_owt_dirichlet_len1024_Cv_to_2v_8gpu_save1k_with_gumbel_watch.sh ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
7
+ export TOKENIZERS_PARALLELISM=false
8
+ export PYTHONUNBUFFERED=1
9
+ export NCCL_DEBUG="${NCCL_DEBUG:-WARN}"
10
+ export TORCH_DISTRIBUTED_TIMEOUT="${TORCH_DISTRIBUTED_TIMEOUT:-3600}"
11
+
12
+ DATE_TAG="${DATE_TAG:-$(date +%Y%m%d)}"
13
+ MAX_LEN="${MAX_LEN:-1024}"
14
+ VOCAB_SIZE="${VOCAB_SIZE:-30522}"
15
+ CMIN="${CMIN:-${VOCAB_SIZE}}"
16
+ CMAX="${CMAX:-61044}"
17
+
18
+ RUN_NAME="${RUN_NAME:-lta_owt_dirichlet_len${MAX_LEN}_Cv_to_2v_gbs512_8gpu_20k_save1k_gumbelwatch_${DATE_TAG}}"
19
+ SAVE_DIR="${SAVE_DIR:-runs/${RUN_NAME}}"
20
+ LOG_FILE="${LOG_FILE:-logs/${RUN_NAME}.log}"
21
+
22
+ DATA_PATH="${DATA_PATH:-/e2e-data/evad-tech-vla/wanghan58/data/small_benchmarks/langflow_2604_11748/openwebtext}"
23
+ TEXT_COLUMN="${TEXT_COLUMN:-text}"
24
+ OPENWEBTEXT_SPLIT="${OPENWEBTEXT_SPLIT:-train_minus_100k}"
25
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/workspace/imagenet_handoff_20260327/nlp_dts_light/assets/distilbert-base-uncased/tokenizer.json}"
26
+ SCORER="${SCORER:-/e2e-data/evad-tech-vla/wanghan58/models/flowtext_scorers/gpt2-large-standard}"
27
+ TOKENIZED_HF="${TOKENIZED_HF:-0}"
28
+ TOKENIZED_PAD_TOKEN="${TOKENIZED_PAD_TOKEN:-pad}"
29
+ TOKENIZED_PREPEND_BOS="${TOKENIZED_PREPEND_BOS:-0}"
30
+ TOKENIZED_APPEND_EOS="${TOKENIZED_APPEND_EOS:-0}"
31
+ TOKENIZED_STRIP_EDGE_SPECIALS="${TOKENIZED_STRIP_EDGE_SPECIALS:-0}"
32
+
33
+ CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7}"
34
+ NNODES="${NNODES:-1}"
35
+ NPROC_PER_NODE="${NPROC_PER_NODE:-8}"
36
+ NODE_RANK="${NODE_RANK:-0}"
37
+ MASTER_ADDR="${MASTER_ADDR:-127.0.0.1}"
38
+ MASTER_PORT="${MASTER_PORT:-32681}"
39
+
40
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
41
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-32}"
42
+ TOTAL_STEPS="${TOTAL_STEPS:-20000}"
43
+ WARMUP_STEPS="${WARMUP_STEPS:-2500}"
44
+ LOG_EVERY="${LOG_EVERY:-100}"
45
+ SAVE_EVERY="${SAVE_EVERY:-1000}"
46
+ LATEST_EVERY="${LATEST_EVERY:-1000}"
47
+ EVAL_EVERY="${EVAL_EVERY:-0}"
48
+ NUM_WORKERS="${NUM_WORKERS:-0}"
49
+ WRAP_MODE="${WRAP_MODE:-stream}"
50
+ WRAP_RECORD_BUFFER_SIZE="${WRAP_RECORD_BUFFER_SIZE:-200}"
51
+ ALLOW_EXISTING_SAVE_DIR="${ALLOW_EXISTING_SAVE_DIR:-0}"
52
+ RESUME_PATH="${RESUME_PATH:-}"
53
+
54
+ MIN_MASK_RATIO="${MIN_MASK_RATIO:-0.1}"
55
+ MAX_MASK_RATIO="${MAX_MASK_RATIO:-1.0}"
56
+ CATEGORICAL_WRONG_PROB_FLOOR="${CATEGORICAL_WRONG_PROB_FLOOR:-0.0}"
57
+ CORRUPT_T_MODE="${CORRUPT_T_MODE:-independent}"
58
+ ABS_POS_EMBED="${ABS_POS_EMBED:-0}"
59
+ MODEL_TYPE="${MODEL_TYPE:-ddit}"
60
+ ELF_NUM_TIME_TOKENS="${ELF_NUM_TIME_TOKENS:-4}"
61
+ ELF_NUM_MODEL_MODE_TOKENS="${ELF_NUM_MODEL_MODE_TOKENS:-0}"
62
+ QK_NORM="${QK_NORM:-1}"
63
+ FORCE_SPECIAL_CORRUPT_TOKEN_IDS="${FORCE_SPECIAL_CORRUPT_TOKEN_IDS:-}"
64
+ SPECIAL_ENDPOINT_GOLD_TOKEN_IDS="${SPECIAL_ENDPOINT_GOLD_TOKEN_IDS:-}"
65
+ SPECIAL_LOSS_TOKEN_IDS="${SPECIAL_LOSS_TOKEN_IDS:-}"
66
+ SPECIAL_LOSS_WEIGHT="${SPECIAL_LOSS_WEIGHT:-1.0}"
67
+
68
+ WATCH_ENABLED="${WATCH_ENABLED:-0}"
69
+ WATCH_CUDA_VISIBLE_DEVICES="${WATCH_CUDA_VISIBLE_DEVICES:-7}"
70
+ WATCH_STEP_INTERVAL="${WATCH_STEP_INTERVAL:-1000}"
71
+ WATCH_SLEEP_SECONDS="${WATCH_SLEEP_SECONDS:-30}"
72
+ WATCH_N_SAMPLES="${WATCH_N_SAMPLES:-128}"
73
+ WATCH_STEPS="${WATCH_STEPS:-128}"
74
+ WATCH_ENDPOINT_TEMP="${WATCH_ENDPOINT_TEMP:-1.45}"
75
+ WATCH_ENDPOINT_TOP_P="${WATCH_ENDPOINT_TOP_P:-0.95}"
76
+ WATCH_GUMBEL_TAU_START="${WATCH_GUMBEL_TAU_START:-1.0}"
77
+ WATCH_GUMBEL_TAU_END="${WATCH_GUMBEL_TAU_END:-0.2}"
78
+ WATCH_DECODE_BATCH="${WATCH_DECODE_BATCH:-2}"
79
+ WATCH_SCORE_BATCH="${WATCH_SCORE_BATCH:-1}"
80
+ WATCH_SCORE_MAX_LENGTH="${WATCH_SCORE_MAX_LENGTH:-1024}"
81
+ WATCH_DECODE_MODE="${WATCH_DECODE_MODE:-sde_gumbel}"
82
+ WATCH_DUAL_SEMANTIC_POWER="${WATCH_DUAL_SEMANTIC_POWER:-1.5}"
83
+ WATCH_DUAL_EARLY_TEMP="${WATCH_DUAL_EARLY_TEMP:-2.8}"
84
+ WATCH_DUAL_LATE_TEMP="${WATCH_DUAL_LATE_TEMP:-1.45}"
85
+ WATCH_DUAL_TEMP_END="${WATCH_DUAL_TEMP_END:-0.55}"
86
+ WATCH_DUAL_TEMP_POWER="${WATCH_DUAL_TEMP_POWER:-1.5}"
87
+ WATCH_OUT_BASE="${WATCH_OUT_BASE:-docs/lta_samples/metrics_${DATE_TAG}/owt_dirichlet_len${MAX_LEN}_Cv_to_2v_every1k_sde_gumbel_topp${WATCH_ENDPOINT_TOP_P//./p}_tau${WATCH_GUMBEL_TAU_START//./p}_to_${WATCH_GUMBEL_TAU_END//./p}_blend_c${CMIN}_${CMAX}_n${WATCH_N_SAMPLES}/${RUN_NAME}}"
88
+ WATCH_LOG_DIR="${WATCH_LOG_DIR:-logs/owt_dirichlet_len${MAX_LEN}_Cv_to_2v_gumbel_sde_watch}"
89
+ WATCH_SCRIPT="${WATCH_SCRIPT:-logs/${RUN_NAME}_watcher.sh}"
90
+ WATCH_LOG="${WATCH_LOG:-logs/${RUN_NAME}_watcher.log}"
91
+ WATCH_PID_FILE="${WATCH_PID_FILE:-logs/${RUN_NAME}_watcher.pid}"
92
+
93
+ if [[ -f "${SAVE_DIR}/args.json" && -z "${RESUME_PATH}" && "${ALLOW_EXISTING_SAVE_DIR}" != "1" ]]; then
94
+ echo "Refusing to start because SAVE_DIR already contains args.json: ${SAVE_DIR}" >&2
95
+ echo "Set RESUME_PATH, use a new RUN_NAME/SAVE_DIR, or ALLOW_EXISTING_SAVE_DIR=1." >&2
96
+ exit 2
97
+ fi
98
+
99
+ mkdir -p logs runs "${SAVE_DIR}" "${WATCH_LOG_DIR}" "${WATCH_OUT_BASE}"
100
+
101
+ RESUME_ARGS=()
102
+ if [[ -n "${RESUME_PATH}" ]]; then
103
+ RESUME_ARGS+=(--resume_path "${RESUME_PATH}")
104
+ fi
105
+
106
+ TEXT_COLUMN_ARGS=()
107
+ if [[ -n "${TEXT_COLUMN}" ]]; then
108
+ TEXT_COLUMN_ARGS+=(--text_column "${TEXT_COLUMN}")
109
+ fi
110
+
111
+ OPENWEBTEXT_ARGS=(--openwebtext_split "${OPENWEBTEXT_SPLIT}")
112
+ WRAP_ARGS=(--wrap --wrap_mode "${WRAP_MODE}" --wrap_record_buffer_size "${WRAP_RECORD_BUFFER_SIZE}")
113
+ TOKENIZED_ARGS=()
114
+ DATA_MODE_LABEL="raw_wrap_${WRAP_MODE}"
115
+ if [[ "${TOKENIZED_HF}" == "1" || "${TOKENIZED_HF}" == "true" || "${TOKENIZED_HF}" == "True" ]]; then
116
+ TEXT_COLUMN_ARGS=()
117
+ OPENWEBTEXT_ARGS=()
118
+ WRAP_ARGS=()
119
+ TOKENIZED_ARGS=(--tokenized_hf --tokenized_pad_token "${TOKENIZED_PAD_TOKEN}")
120
+ if [[ "${TOKENIZED_PREPEND_BOS}" == "1" || "${TOKENIZED_PREPEND_BOS}" == "true" || "${TOKENIZED_PREPEND_BOS}" == "True" ]]; then
121
+ TOKENIZED_ARGS+=(--tokenized_prepend_bos)
122
+ fi
123
+ if [[ "${TOKENIZED_APPEND_EOS}" == "1" || "${TOKENIZED_APPEND_EOS}" == "true" || "${TOKENIZED_APPEND_EOS}" == "True" ]]; then
124
+ TOKENIZED_ARGS+=(--tokenized_append_eos)
125
+ fi
126
+ if [[ "${TOKENIZED_STRIP_EDGE_SPECIALS}" == "1" || "${TOKENIZED_STRIP_EDGE_SPECIALS}" == "true" || "${TOKENIZED_STRIP_EDGE_SPECIALS}" == "True" ]]; then
127
+ TOKENIZED_ARGS+=(--tokenized_strip_edge_specials)
128
+ fi
129
+ DATA_MODE_LABEL="tokenized_hf_pad_${TOKENIZED_PAD_TOKEN}"
130
+ fi
131
+
132
+ ABS_POS_ARGS=()
133
+ if [[ "${ABS_POS_EMBED}" == "1" || "${ABS_POS_EMBED}" == "true" || "${ABS_POS_EMBED}" == "True" ]]; then
134
+ ABS_POS_ARGS+=(--abs_pos_embed)
135
+ fi
136
+
137
+ QK_NORM_ARGS=(--qk_norm)
138
+ if [[ "${QK_NORM}" == "0" || "${QK_NORM}" == "false" || "${QK_NORM}" == "False" ]]; then
139
+ QK_NORM_ARGS=(--no-qk_norm)
140
+ fi
141
+
142
+ SPECIAL_ARGS=()
143
+ if [[ -n "${FORCE_SPECIAL_CORRUPT_TOKEN_IDS}" ]]; then
144
+ SPECIAL_ARGS+=(--force_special_corrupt_token_ids "${FORCE_SPECIAL_CORRUPT_TOKEN_IDS}")
145
+ fi
146
+ if [[ -n "${SPECIAL_ENDPOINT_GOLD_TOKEN_IDS}" ]]; then
147
+ SPECIAL_ARGS+=(--special_endpoint_gold_token_ids "${SPECIAL_ENDPOINT_GOLD_TOKEN_IDS}")
148
+ fi
149
+ if [[ -n "${SPECIAL_LOSS_TOKEN_IDS}" ]]; then
150
+ SPECIAL_ARGS+=(--special_loss_token_ids "${SPECIAL_LOSS_TOKEN_IDS}" --special_loss_weight "${SPECIAL_LOSS_WEIGHT}")
151
+ fi
152
+
153
+ write_watcher() {
154
+ cat > "${WATCH_SCRIPT}" <<'WATCH_EOF'
155
+ #!/usr/bin/env bash
156
+ set -euo pipefail
157
+
158
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
159
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
160
+ export TOKENIZERS_PARALLELISM=false
161
+ export PYTHONUNBUFFERED=1
162
+
163
+ : "${RUN_DIR:?RUN_DIR is required}"
164
+ : "${OUT_BASE:?OUT_BASE is required}"
165
+ : "${LOG_DIR:?LOG_DIR is required}"
166
+ : "${TOKENIZER_PATH:?TOKENIZER_PATH is required}"
167
+ : "${SCORER:?SCORER is required}"
168
+
169
+ RUN_STEM="$(basename "${RUN_DIR}")"
170
+ TEMP_TAG="${ENDPOINT_TEMP//./p}"
171
+ PROCESSED_FILE="${LOG_DIR}/processed_${RUN_STEM}_steps${STEPS}_c${CMIN}_${CMAX}_gumbel_t${TEMP_TAG}_n${N_SAMPLES}.txt"
172
+
173
+ mkdir -p "${OUT_BASE}" "${LOG_DIR}"
174
+ touch "${PROCESSED_FILE}"
175
+
176
+ echo "[watch-gumbel] run_dir=${RUN_DIR}"
177
+ echo "[watch-gumbel] out_base=${OUT_BASE}"
178
+ echo "[watch-gumbel] interval=${STEP_INTERVAL} max_len=${MAX_LEN} steps=${STEPS} c=${CMIN}->${CMAX} decode_mode=${DECODE_MODE:-sde_gumbel} temp=${ENDPOINT_TEMP} top_p=${ENDPOINT_TOP_P} tau=${GUMBEL_TAU_START}->${GUMBEL_TAU_END} n=${N_SAMPLES}"
179
+
180
+ while true; do
181
+ shopt -s nullglob
182
+ ckpts=("${RUN_DIR}"/step_*.pt)
183
+ shopt -u nullglob
184
+
185
+ if (( ${#ckpts[@]} == 0 )); then
186
+ echo "[watch-gumbel] $(date +%F_%T) no ckpt yet"
187
+ sleep "${SLEEP_SECONDS}"
188
+ continue
189
+ fi
190
+
191
+ printf "%s\n" "${ckpts[@]}" | sort | while read -r ckpt; do
192
+ base="$(basename "${ckpt}")"
193
+ step="${base#step_}"
194
+ step="${step%.pt}"
195
+ step_num=$((10#${step}))
196
+ if (( step_num % STEP_INTERVAL != 0 )); then
197
+ continue
198
+ fi
199
+ if grep -Fxq "${ckpt}" "${PROCESSED_FILE}"; then
200
+ continue
201
+ fi
202
+
203
+ out_dir="${OUT_BASE}/step_${step}"
204
+ log_file="${LOG_DIR}/infer_${RUN_STEM}_step_${step}.log"
205
+ mkdir -p "${out_dir}"
206
+
207
+ echo "[watch-gumbel] $(date +%F_%T) infer ${ckpt} -> ${out_dir}" | tee -a "${log_file}"
208
+ if [[ "${DECODE_MODE:-sde_gumbel}" == "dual_line_probe" ]]; then
209
+ CUDA_VISIBLE_DEVICES="${WATCH_CUDA_VISIBLE_DEVICES}" python scripts/infer_softkl_decode_probe.py \
210
+ --checkpoint "${ckpt}" \
211
+ --tokenizer_path "${TOKENIZER_PATH}" \
212
+ --scorer "${SCORER}" \
213
+ --score \
214
+ --out_dir "${out_dir}" \
215
+ --max_lens "${MAX_LEN}" \
216
+ --n_samples "${N_SAMPLES}" \
217
+ --batch_size "${DECODE_BATCH}" \
218
+ --steps "${STEPS}" \
219
+ --decode_rule dual_line_resample \
220
+ --c_min "${CMIN}" \
221
+ --c_max "${CMAX}" \
222
+ --input_noise_dirichlet_concentration "${CMIN}" \
223
+ --anchor_mode state \
224
+ --model_t_mode flow \
225
+ --time_schedule uniform \
226
+ --support_power 1.0 \
227
+ --semantic_power "${DUAL_SEMANTIC_POWER}" \
228
+ --early_temp "${DUAL_EARLY_TEMP}" \
229
+ --late_temp "${DUAL_LATE_TEMP}" \
230
+ --temp_end "${DUAL_TEMP_END}" \
231
+ --temp_power "${DUAL_TEMP_POWER}" \
232
+ --final_from blend \
233
+ --final_decode argmax \
234
+ --seed 20260524 \
235
+ 2>&1 | tee -a "${log_file}"
236
+ else
237
+ CUDA_VISIBLE_DEVICES="${WATCH_CUDA_VISIBLE_DEVICES}" python scripts/eval_lm1b_c1024_fullycoupled_sde_genppl.py \
238
+ --checkpoint "${ckpt}" \
239
+ --tokenizer_path "${TOKENIZER_PATH}" \
240
+ --scorer "${SCORER}" \
241
+ --out_dir "${out_dir}" \
242
+ --n_samples "${N_SAMPLES}" \
243
+ --max_len "${MAX_LEN}" \
244
+ --steps "${STEPS}" \
245
+ --batch_size "${DECODE_BATCH}" \
246
+ --score_batch "${SCORE_BATCH}" \
247
+ --score_max_length "${SCORE_MAX_LENGTH}" \
248
+ --concentration_min "${CMIN}" \
249
+ --concentration_max "${CMAX}" \
250
+ --endpoint_temp "${ENDPOINT_TEMP}" \
251
+ --endpoint_projection gumbel_softmax \
252
+ --endpoint_top_p "${ENDPOINT_TOP_P}" \
253
+ --gumbel_tau_start "${GUMBEL_TAU_START}" \
254
+ --gumbel_tau_end "${GUMBEL_TAU_END}" \
255
+ --model_t_mode support_t \
256
+ --mean_mode endpoint_only \
257
+ --semantic_power 1.0 \
258
+ --noise_init dirichlet \
259
+ --noise_dirichlet_concentration "${CMIN}" \
260
+ --sde_resample dirichlet \
261
+ --final_from blend_0.5 \
262
+ --seed 20260524 \
263
+ 2>&1 | tee -a "${log_file}"
264
+ fi
265
+
266
+ echo "${ckpt}" >> "${PROCESSED_FILE}"
267
+ echo "[watch-gumbel] $(date +%F_%T) done step_${step}" | tee -a "${log_file}"
268
+ done
269
+
270
+ sleep "${SLEEP_SECONDS}"
271
+ done
272
+ WATCH_EOF
273
+ chmod +x "${WATCH_SCRIPT}"
274
+ }
275
+
276
+ start_watcher() {
277
+ if [[ "${WATCH_ENABLED}" != "1" ]]; then
278
+ echo "[launch] watcher disabled"
279
+ return
280
+ fi
281
+ if [[ -f "${WATCH_PID_FILE}" ]]; then
282
+ old_pid="$(cat "${WATCH_PID_FILE}" || true)"
283
+ if [[ -n "${old_pid}" ]] && kill -0 "${old_pid}" 2>/dev/null; then
284
+ echo "[launch] watcher already running pid=${old_pid}"
285
+ return
286
+ fi
287
+ fi
288
+ write_watcher
289
+ nohup env \
290
+ RUN_DIR="${SAVE_DIR}" \
291
+ OUT_BASE="${WATCH_OUT_BASE}" \
292
+ LOG_DIR="${WATCH_LOG_DIR}" \
293
+ TOKENIZER_PATH="${TOKENIZER_PATH}" \
294
+ SCORER="${SCORER}" \
295
+ WATCH_CUDA_VISIBLE_DEVICES="${WATCH_CUDA_VISIBLE_DEVICES}" \
296
+ N_SAMPLES="${WATCH_N_SAMPLES}" \
297
+ MAX_LEN="${MAX_LEN}" \
298
+ STEPS="${WATCH_STEPS}" \
299
+ DECODE_BATCH="${WATCH_DECODE_BATCH}" \
300
+ SCORE_BATCH="${WATCH_SCORE_BATCH}" \
301
+ SCORE_MAX_LENGTH="${WATCH_SCORE_MAX_LENGTH}" \
302
+ DECODE_MODE="${WATCH_DECODE_MODE}" \
303
+ DUAL_SEMANTIC_POWER="${WATCH_DUAL_SEMANTIC_POWER}" \
304
+ DUAL_EARLY_TEMP="${WATCH_DUAL_EARLY_TEMP}" \
305
+ DUAL_LATE_TEMP="${WATCH_DUAL_LATE_TEMP}" \
306
+ DUAL_TEMP_END="${WATCH_DUAL_TEMP_END}" \
307
+ DUAL_TEMP_POWER="${WATCH_DUAL_TEMP_POWER}" \
308
+ CMIN="${CMIN}" \
309
+ CMAX="${CMAX}" \
310
+ ENDPOINT_TEMP="${WATCH_ENDPOINT_TEMP}" \
311
+ ENDPOINT_TOP_P="${WATCH_ENDPOINT_TOP_P}" \
312
+ GUMBEL_TAU_START="${WATCH_GUMBEL_TAU_START}" \
313
+ GUMBEL_TAU_END="${WATCH_GUMBEL_TAU_END}" \
314
+ STEP_INTERVAL="${WATCH_STEP_INTERVAL}" \
315
+ SLEEP_SECONDS="${WATCH_SLEEP_SECONDS}" \
316
+ bash "${WATCH_SCRIPT}" > "${WATCH_LOG}" 2>&1 &
317
+ echo "$!" > "${WATCH_PID_FILE}"
318
+ echo "[launch] watcher pid=$(cat "${WATCH_PID_FILE}") log=${WATCH_LOG}"
319
+ }
320
+
321
+ echo "[launch] run=${RUN_NAME}"
322
+ echo "[launch] data_path=${DATA_PATH} mode=${DATA_MODE_LABEL} split=${OPENWEBTEXT_SPLIT} text_column=${TEXT_COLUMN}"
323
+ echo "[launch] max_len=${MAX_LEN} gbs=${GLOBAL_BATCH_SIZE} per_gpu=${PER_GPU_BATCH_SIZE} total_steps=${TOTAL_STEPS}"
324
+ echo "[launch] dirichlet C=${CMIN}->${CMAX} wrong_floor=${CATEGORICAL_WRONG_PROB_FLOOR} corrupt_t_mode=${CORRUPT_T_MODE}"
325
+ echo "[launch] model_type=${MODEL_TYPE} abs_pos=${ABS_POS_EMBED} elf_time_tokens=${ELF_NUM_TIME_TOKENS} qk_norm=${QK_NORM} force_special_corrupt=${FORCE_SPECIAL_CORRUPT_TOKEN_IDS:-none} special_endpoint_gold=${SPECIAL_ENDPOINT_GOLD_TOKEN_IDS:-none} special_loss=${SPECIAL_LOSS_TOKEN_IDS:-none}x${SPECIAL_LOSS_WEIGHT}"
326
+ start_watcher
327
+
328
+ CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES}" python -m torch.distributed.run \
329
+ --nnodes="${NNODES}" \
330
+ --nproc_per_node="${NPROC_PER_NODE}" \
331
+ --node_rank="${NODE_RANK}" \
332
+ --master_addr="${MASTER_ADDR}" \
333
+ --master_port="${MASTER_PORT}" \
334
+ train.py \
335
+ --data_path "${DATA_PATH}" \
336
+ "${TEXT_COLUMN_ARGS[@]}" \
337
+ "${OPENWEBTEXT_ARGS[@]}" \
338
+ "${TOKENIZED_ARGS[@]}" \
339
+ --detokenizer auto \
340
+ --tokenizer_path "${TOKENIZER_PATH}" \
341
+ --save_dir "${SAVE_DIR}" \
342
+ "${WRAP_ARGS[@]}" \
343
+ --max_len "${MAX_LEN}" \
344
+ --batch_size "${PER_GPU_BATCH_SIZE}" \
345
+ --num_workers "${NUM_WORKERS}" \
346
+ --global_batch_size "${GLOBAL_BATCH_SIZE}" \
347
+ --total_steps "${TOTAL_STEPS}" \
348
+ --log_every "${LOG_EVERY}" \
349
+ --eval_every "${EVAL_EVERY}" \
350
+ --save_every "${SAVE_EVERY}" \
351
+ --latest_every "${LATEST_EVERY}" \
352
+ --lr 3e-4 \
353
+ --weight_decay 0 \
354
+ --adam_beta1 0.9 \
355
+ --adam_beta2 0.999 \
356
+ --adam_eps 1e-8 \
357
+ --warmup_steps "${WARMUP_STEPS}" \
358
+ --lr_schedule constant_warmup \
359
+ --grad_clip 1.0 \
360
+ --seed 123 \
361
+ --d_model 768 \
362
+ --cond_dim 128 \
363
+ --n_layers 12 \
364
+ --n_heads 12 \
365
+ --dim_ff 3072 \
366
+ --dropout 0.1 \
367
+ "${ABS_POS_ARGS[@]}" \
368
+ --model_type "${MODEL_TYPE}" \
369
+ --elf_num_time_tokens "${ELF_NUM_TIME_TOKENS}" \
370
+ --elf_num_model_mode_tokens "${ELF_NUM_MODEL_MODE_TOKENS}" \
371
+ "${QK_NORM_ARGS[@]}" \
372
+ --state_format prob \
373
+ --bridge dirichlet \
374
+ --target_loss hard_ce \
375
+ --target_prob 1.0 \
376
+ --min_t 0.0 \
377
+ --max_t 1.0 \
378
+ --dual_t \
379
+ --corrupt_t_mode "${CORRUPT_T_MODE}" \
380
+ --corrupt_min_t 0.0 \
381
+ --corrupt_max_t 1.0 \
382
+ --min_mask_ratio "${MIN_MASK_RATIO}" \
383
+ --max_mask_ratio "${MAX_MASK_RATIO}" \
384
+ --wrong_token_replace_prob 1.0 \
385
+ --wrong_token_schedule linear_t \
386
+ --wrong_token_exp_k 1.0 \
387
+ --categorical_wrong_prob_floor "${CATEGORICAL_WRONG_PROB_FLOOR}" \
388
+ --dirichlet_concentration_min "${CMIN}" \
389
+ --dirichlet_concentration_max "${CMAX}" \
390
+ --dirichlet_endpoint_mode categorical_dual_t \
391
+ --dirichlet_semantic_t_mode same \
392
+ --dirichlet_semantic_t_value 0.0 \
393
+ --categorical_wrong_from_full_vocab \
394
+ --eps 1e-8 \
395
+ --infer_steps 128 \
396
+ --decode_damping 1.0 \
397
+ --max_gamma 1.0 \
398
+ --decode_solver flowmap \
399
+ --noise_init logistic_normal \
400
+ --bridge_noise_init logistic_normal \
401
+ --noise_sigma -1 \
402
+ "${SPECIAL_ARGS[@]}" \
403
+ "${RESUME_ARGS[@]}" \
404
+ --bf16 2>&1 | tee -a "${LOG_FILE}"
LTA_openwebtext_dualt/scripts/run_lta_owt_t5_len128_uniform10k_then_lognsr_4gpu.sh ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ export CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-4,5,6,7}"
7
+ export NPROC_PER_NODE="${NPROC_PER_NODE:-4}"
8
+ export MASTER_PORT="${MASTER_PORT:-39331}"
9
+ export OMP_NUM_THREADS="${OMP_NUM_THREADS:-1}"
10
+ export PYTHONUNBUFFERED=1
11
+ export TOKENIZERS_PARALLELISM=false
12
+
13
+ BASE_RUN_NAME="${BASE_RUN_NAME:-lta_owt_t5_len128_uniform10k_then_lognsr_sde_rollin_4gpu_$(date +%Y%m%d_%H%M%S)}"
14
+ WARMUP_RUN_NAME="${BASE_RUN_NAME}_warmup_uniform_norollin"
15
+ MAIN_RUN_NAME="${BASE_RUN_NAME}_resume_lognsr_sde_rollin"
16
+
17
+ COMMON_ENV=(
18
+ MAX_LEN=128
19
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
20
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-32}"
21
+ SAVE_EVERY="${SAVE_EVERY:-1000}"
22
+ LATEST_EVERY="${LATEST_EVERY:-1000}"
23
+ LOG_EVERY="${LOG_EVERY:-100}"
24
+ TARGET_LOSS="${TARGET_LOSS:-hard_ce}"
25
+ MIN_MASK_RATIO=1.0
26
+ MAX_MASK_RATIO=1.0
27
+ MASK_MIXTURE_ALL_PROB=1.0
28
+ )
29
+
30
+ echo "[two-phase] base_run_name=${BASE_RUN_NAME}"
31
+ echo "[two-phase] phase1=${WARMUP_RUN_NAME}: uniform t, no roll-in, 10k steps"
32
+ env "${COMMON_ENV[@]}" \
33
+ RUN_NAME="${WARMUP_RUN_NAME}" \
34
+ TOTAL_STEPS=10000 \
35
+ T_SAMPLING_MODE=uniform \
36
+ ROLLOUT_TRAIN_PROB=0.0 \
37
+ bash scripts/launch_lta_owt_t5_len128_sde_rollin_lognsr_4gpu.sh
38
+
39
+ WARMUP_CKPT="runs/${WARMUP_RUN_NAME}/step_0010000.pt"
40
+ if [[ ! -f "${WARMUP_CKPT}" ]]; then
41
+ echo "[two-phase] missing warmup checkpoint: ${WARMUP_CKPT}" >&2
42
+ exit 1
43
+ fi
44
+
45
+ echo "[two-phase] phase2=${MAIN_RUN_NAME}: resume ${WARMUP_CKPT}, lognsr_gumbel + sde roll-in"
46
+ env "${COMMON_ENV[@]}" \
47
+ RUN_NAME="${MAIN_RUN_NAME}" \
48
+ RESUME_PATH="${WARMUP_CKPT}" \
49
+ TOTAL_STEPS="${TOTAL_STEPS:-1000000}" \
50
+ T_SAMPLING_MODE=lognsr_gumbel \
51
+ T_GUMBEL_LOC="${T_GUMBEL_LOC:-2.2}" \
52
+ T_GUMBEL_SCALE="${T_GUMBEL_SCALE:-0.8}" \
53
+ ROLLOUT_TRAIN_PROB="${ROLLOUT_TRAIN_PROB:-0.50}" \
54
+ ROLLOUT_TRAIN_RULE=dirichlet_resample \
55
+ ROLLOUT_TRAIN_TIME_MODE=sampled_path \
56
+ ROLLOUT_TRAIN_STEPS="${ROLLOUT_TRAIN_STEPS:-3}" \
57
+ ROLLOUT_TRAIN_STEPS_MIN="${ROLLOUT_TRAIN_STEPS_MIN:-0}" \
58
+ ROLLOUT_TRAIN_INFER_STEPS="${ROLLOUT_TRAIN_INFER_STEPS:-1}" \
59
+ ROLLOUT_TRAIN_TEMP="${ROLLOUT_TRAIN_TEMP:-1.0}" \
60
+ bash scripts/launch_lta_owt_t5_len128_sde_rollin_lognsr_4gpu.sh
LTA_openwebtext_dualt/scripts/run_train8_ctx1024_sampleds_sweep_4gpu.sh ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
7
+ export TOKENIZERS_PARALLELISM=false
8
+ export PYTHONUNBUFFERED=1
9
+
10
+ BASE_CACHE="${BASE_CACHE:-/e2e-data/evad-tech-vla/wanghan58/data/small_benchmarks/langflow_2604_11748/openwebtext_lta_cached_chunks}"
11
+ CACHE_PREFIX="${CACHE_PREFIX:-gpt2}"
12
+ CACHE_DIR="${CACHE_DIR:-}"
13
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/models/flowtext_scorers/gpt2-standard/tokenizer.json}"
14
+ MAX_LEN="${MAX_LEN:-1024}"
15
+ N_SAMPLES="${N_SAMPLES:-64}"
16
+ INFER_STEPS="${INFER_STEPS:-128}"
17
+ STEP_CHUNK="${STEP_CHUNK:-1000}"
18
+ MAX_TOTAL_STEPS="${MAX_TOTAL_STEPS:-12000}"
19
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE:-128}"
20
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE:-512}"
21
+ LEARNING_RATE="${LEARNING_RATE:-0.002}"
22
+ WEIGHT_DECAY="${WEIGHT_DECAY:-0.1}"
23
+ GROUP_STAMP="${GROUP_STAMP:-$(date +%Y%m%d_%H%M%S)}"
24
+ WAIT_FOR_RUN="${WAIT_FOR_RUN:-}"
25
+ OUT_ROOT="${OUT_ROOT:-docs/lta_samples/metrics_20260517/ctx1024_sampleds_sweep_bs512_ode128_${GROUP_STAMP}}"
26
+ DRIVER_LOG="${DRIVER_LOG:-logs/ctx1024_sampleds_sweep_4gpu/${GROUP_STAMP}.log}"
27
+ CURVE_CSV="${CURVE_CSV:-${OUT_ROOT}/hit_ratio_curve.csv}"
28
+ EVAL_DECODE_RULES="${EVAL_DECODE_RULES:-flowmap}"
29
+ EVAL_C_MAX="${EVAL_C_MAX:-512}"
30
+ EVAL_EARLY_TEMP="${EVAL_EARLY_TEMP:-1.0}"
31
+ EVAL_LATE_TEMP="${EVAL_LATE_TEMP:-1.0}"
32
+ mkdir -p "$(dirname "${DRIVER_LOG}")" "${OUT_ROOT}"
33
+
34
+ if [[ -n "${CACHE_DIR}" ]]; then
35
+ cache="${CACHE_DIR}"
36
+ else
37
+ cache="${BASE_CACHE}/${CACHE_PREFIX}_len${MAX_LEN}_train8_compact_overfit"
38
+ fi
39
+ vocab_size="$(
40
+ python - "$cache" <<'PY'
41
+ import json
42
+ import sys
43
+ from pathlib import Path
44
+ meta = json.loads((Path(sys.argv[1]) / "meta.json").read_text())
45
+ print(int(meta.get("compact_vocab_size", meta.get("vocab_size"))))
46
+ PY
47
+ )"
48
+
49
+ if [[ ! -f "${CURVE_CSV}" ]]; then
50
+ echo "config,decode_rule,run_name,ckpt_step,train_views_seen,train_tokens_seen,token_acc_mean,exact_count,exact_ref_count,exact_ref_hits" > "${CURVE_CSV}"
51
+ fi
52
+
53
+ latest_step() {
54
+ local run_name="$1"
55
+ python - "$run_name" <<'PY'
56
+ import re
57
+ import sys
58
+ from pathlib import Path
59
+ run = Path("runs") / sys.argv[1]
60
+ steps = []
61
+ for path in run.glob("step_*.pt"):
62
+ m = re.search(r"step_(\d+)\.pt$", path.name)
63
+ if m:
64
+ steps.append(int(m.group(1)))
65
+ print(max(steps) if steps else 0)
66
+ PY
67
+ }
68
+
69
+ free_port() {
70
+ python - <<'PY'
71
+ import socket
72
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
73
+ s.bind(("127.0.0.1", 0))
74
+ print(s.getsockname()[1])
75
+ PY
76
+ }
77
+
78
+ eval_latest() {
79
+ local config="$1"
80
+ local run_name="$2"
81
+ local target_step="$3"
82
+ IFS=',' read -r -a decode_rules <<<"${EVAL_DECODE_RULES}"
83
+ for decode_rule in "${decode_rules[@]}"; do
84
+ decode_rule="$(echo "${decode_rule}" | xargs)"
85
+ [[ -n "${decode_rule}" ]] || continue
86
+ local out_dir="${OUT_ROOT}/${config}/step_${target_step}/${decode_rule}_c${EVAL_C_MAX}"
87
+ mkdir -p "${out_dir}"
88
+ CUDA_VISIBLE_DEVICES="${EVAL_CUDA_VISIBLE_DEVICES:-0}" python scripts/eval_train8_decode_acc.py \
89
+ --runs_glob "runs/${run_name}" \
90
+ --data_dir "${cache}" \
91
+ --tokenizer_path "${TOKENIZER_PATH}" \
92
+ --out_dir "${out_dir}" \
93
+ --max_len "${MAX_LEN}" \
94
+ --n_samples "${N_SAMPLES}" \
95
+ --batch_size "${N_SAMPLES}" \
96
+ --latest_only \
97
+ --endpoint_softenings none \
98
+ --steps "${INFER_STEPS}" \
99
+ --decode_rule "${decode_rule}" \
100
+ --time_schedule logit_normal \
101
+ --time_logit_mean -1.5 \
102
+ --time_logit_std 0.8 \
103
+ --model_t_mode post \
104
+ --c_min 1 \
105
+ --c_max "${EVAL_C_MAX}" \
106
+ --early_temp "${EVAL_EARLY_TEMP}" \
107
+ --late_temp "${EVAL_LATE_TEMP}" \
108
+ --final_from state \
109
+ --final_decode argmax
110
+ python - "$out_dir" "$N_SAMPLES" "$GLOBAL_BATCH_SIZE" "$MAX_LEN" "$CURVE_CSV" "$config" "$run_name" "$decode_rule" <<'PY'
111
+ import json
112
+ import sys
113
+ from pathlib import Path
114
+ out = Path(sys.argv[1])
115
+ n = int(sys.argv[2])
116
+ global_batch = int(sys.argv[3])
117
+ max_len = int(sys.argv[4])
118
+ curve = Path(sys.argv[5])
119
+ config = sys.argv[6]
120
+ run_name = sys.argv[7]
121
+ decode_rule = sys.argv[8]
122
+ row = json.loads((out / "decode_token_acc.jsonl").read_text().splitlines()[-1])
123
+ views = int(row["ckpt_step"]) * global_batch
124
+ tokens = views * max_len
125
+ print(
126
+ "RESULT "
127
+ f"config={config} decode={decode_rule} run={run_name} ckpt_step={row['ckpt_step']} "
128
+ f"views={views} token_acc={row['token_acc_mean']:.4f} "
129
+ f"exact={row['exact_count']}/{n} exact_refs={row['exact_ref_count']} "
130
+ f"hits={row['exact_ref_hits']}",
131
+ flush=True,
132
+ )
133
+ with curve.open("a", encoding="utf-8") as f:
134
+ f.write(
135
+ f"{config},{decode_rule},{run_name},{row['ckpt_step']},{views},{tokens},{row['token_acc_mean']},"
136
+ f"{row['exact_count']},{row['exact_ref_count']},\"{row['exact_ref_hits']}\"\n"
137
+ )
138
+ PY
139
+ done
140
+ }
141
+
142
+ run_config() {
143
+ local config="$1"
144
+ local rollout_prob="$2"
145
+ local time_mode="$3"
146
+ local rollout_steps="$4"
147
+ local s_dist="$5"
148
+ local s_min_frac="$6"
149
+ local s_max_frac="$7"
150
+ local s_beta_alpha="$8"
151
+ local s_beta_beta="$9"
152
+ local output_wd="${10}"
153
+ local sync_t="${11}"
154
+ local rollout_steps_min="${12:-${ROLLOUT_TRAIN_STEPS_MIN:--1}}"
155
+ local run_name="${RUN_PREFIX:-train8_ctx1024}_${config}_${GROUP_STAMP}"
156
+ echo "[ctx1024-sampleds] config=${config} run=${run_name} p=${rollout_prob} mode=${time_mode} steps=${rollout_steps} steps_min=${rollout_steps_min} s_dist=${s_dist} s_frac=${s_min_frac}->${s_max_frac} beta=${s_beta_alpha},${s_beta_beta} outwd=${output_wd} sync_t=${sync_t}" | tee -a "${DRIVER_LOG}"
157
+ while :; do
158
+ local step_now
159
+ step_now="$(latest_step "${run_name}")"
160
+ if [[ "${step_now}" -ge "${MAX_TOTAL_STEPS}" ]]; then
161
+ echo "[ctx1024-sampleds] capped config=${config} step=${step_now}" | tee -a "${DRIVER_LOG}"
162
+ break
163
+ fi
164
+ local target_step=$((step_now + STEP_CHUNK))
165
+ if [[ "${target_step}" -gt "${MAX_TOTAL_STEPS}" ]]; then
166
+ target_step="${MAX_TOTAL_STEPS}"
167
+ fi
168
+ local resume_path=""
169
+ if [[ -f "runs/${run_name}/latest.pt" ]]; then
170
+ resume_path="runs/${run_name}/latest.pt"
171
+ fi
172
+ echo "[ctx1024-sampleds] train config=${config} from=${step_now} to=${target_step}" | tee -a "${DRIVER_LOG}"
173
+ CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0,1,2,3}" \
174
+ NPROC_PER_NODE="${NPROC_PER_NODE:-4}" \
175
+ MASTER_PORT="$(free_port)" \
176
+ OWT_CHUNK_CACHE_DIR="${cache}" \
177
+ OWT_EXACT_REPEAT_PER_CHUNK="${OWT_EXACT_REPEAT_PER_CHUNK:-64}" \
178
+ MAX_LEN="${MAX_LEN}" \
179
+ VOCAB_SIZE_OVERRIDE="${vocab_size}" \
180
+ D_MODEL="${D_MODEL:-192}" \
181
+ COND_DIM="${COND_DIM:-64}" \
182
+ N_LAYERS="${N_LAYERS:-3}" \
183
+ N_HEADS="${N_HEADS:-3}" \
184
+ DIM_FF="${DIM_FF:-768}" \
185
+ TOTAL_STEPS="${target_step}" \
186
+ PER_GPU_BATCH_SIZE="${PER_GPU_BATCH_SIZE}" \
187
+ GLOBAL_BATCH_SIZE="${GLOBAL_BATCH_SIZE}" \
188
+ NUM_WORKERS="${NUM_WORKERS:-0}" \
189
+ LOG_EVERY="${LOG_EVERY:-100}" \
190
+ SAVE_EVERY="${STEP_CHUNK}" \
191
+ LATEST_EVERY="${STEP_CHUNK}" \
192
+ WARMUP_STEPS="${WARMUP_STEPS:-10}" \
193
+ LEARNING_RATE="${LEARNING_RATE}" \
194
+ WEIGHT_DECAY="${WEIGHT_DECAY}" \
195
+ OUTPUT_WEIGHT_DECAY="${output_wd}" \
196
+ MUON_IMPL="${MUON_IMPL:-legacy}" \
197
+ MIN_MASK_RATIO=1.0 \
198
+ MAX_MASK_RATIO=1.0 \
199
+ MASK_MIXTURE_LOWK_PROB=0.0 \
200
+ MASK_MIXTURE_ALL_PROB=1.0 \
201
+ LOWK_CLEAN_TOKENS=0 \
202
+ CLEAN_STATE_MODE=onehot \
203
+ TARGET_LOSS=hard_ce \
204
+ DIRICHLET_CONCENTRATION_MIN=1.0 \
205
+ DIRICHLET_CONCENTRATION_MAX=1024 \
206
+ SIMPLEX_BRIDGE_SAMPLER=dirichlet \
207
+ CATEGORICAL_WRONG_PROB_FLOOR=0.0 \
208
+ ROLLOUT_TRAIN_PROB="${rollout_prob}" \
209
+ ROLLOUT_TRAIN_STEPS="${rollout_steps}" \
210
+ ROLLOUT_TRAIN_STEPS_MIN="${rollout_steps_min}" \
211
+ ROLLOUT_TRAIN_INFER_STEPS=1 \
212
+ ROLLOUT_TRAIN_TIME_MODE="${time_mode}" \
213
+ ROLLOUT_TRAIN_S_DIST="${s_dist}" \
214
+ ROLLOUT_TRAIN_S_MIN_FRAC="${s_min_frac}" \
215
+ ROLLOUT_TRAIN_S_MAX_FRAC="${s_max_frac}" \
216
+ ROLLOUT_TRAIN_S_BETA_ALPHA="${s_beta_alpha}" \
217
+ ROLLOUT_TRAIN_S_BETA_BETA="${s_beta_beta}" \
218
+ ROLLOUT_TRAIN_TEMP=1.0 \
219
+ ROLLOUT_TRAIN_MAX_GAMMA=1.0 \
220
+ ROLLOUT_TRAIN_CORRUPT_ONLY=1 \
221
+ ROLLOUT_TRAIN_SAMPLEWISE=1 \
222
+ ROLLOUT_TRAIN_SELECTED_ONLY=1 \
223
+ ROLLOUT_TRAIN_COMPUTE_ALWAYS=0 \
224
+ ROLLOUT_TRAIN_SYNC_T="${sync_t}" \
225
+ T_SAMPLING_MODE="${T_SAMPLING_MODE:-uniform}" \
226
+ RUN_NAME="${run_name}" \
227
+ RESUME_PATH="${resume_path}" \
228
+ bash scripts/launch_lta_owt_gpt2_softendpoint_mn_pilot_4gpu.sh
229
+ echo "[ctx1024-sampleds] eval config=${config} step=${target_step}" | tee -a "${DRIVER_LOG}"
230
+ eval_latest "${config}" "${run_name}" "${target_step}" | tee -a "${DRIVER_LOG}"
231
+ local eval_rule_count
232
+ eval_rule_count="$(python - "$EVAL_DECODE_RULES" <<'PY'
233
+ import sys
234
+ print(len([x for x in sys.argv[1].split(",") if x.strip()]) or 1)
235
+ PY
236
+ )"
237
+ if python - "$CURVE_CSV" "$N_SAMPLES" "$eval_rule_count" <<'PY'
238
+ import csv
239
+ import sys
240
+ from pathlib import Path
241
+ path = Path(sys.argv[1])
242
+ target = min(60, int(sys.argv[2]))
243
+ rule_count = max(1, int(sys.argv[3]))
244
+ rows = list(csv.DictReader(path.open()))
245
+ recent = rows[-rule_count:]
246
+ raise SystemExit(0 if any(int(float(r["exact_count"])) >= target for r in recent) else 1)
247
+ PY
248
+ then
249
+ echo "[ctx1024-sampleds] early-hit config=${config}" | tee -a "${DRIVER_LOG}"
250
+ break
251
+ fi
252
+ done
253
+ }
254
+
255
+ if [[ -n "${WAIT_FOR_RUN}" ]]; then
256
+ echo "[ctx1024-sampleds] waiting for run=${WAIT_FOR_RUN}" | tee -a "${DRIVER_LOG}"
257
+ while pgrep -f "${WAIT_FOR_RUN}" >/dev/null; do
258
+ sleep 60
259
+ done
260
+ fi
261
+
262
+ echo "[ctx1024-sampleds] start stamp=${GROUP_STAMP} len=${MAX_LEN} vocab=${vocab_size} out=${OUT_ROOT}" | tee -a "${DRIVER_LOG}"
263
+
264
+ CONFIGS=(
265
+ "p50_unif0_0p125_outwdm1|0.50|sampled_s|1|uniform|0.0|0.125|2.0|6.0|-1|1"
266
+ "p25_unif0_0p125_outwdm1|0.25|sampled_s|1|uniform|0.0|0.125|2.0|6.0|-1|1"
267
+ "p50_unif0_0p25_outwdm1|0.50|sampled_s|1|uniform|0.0|0.25|2.0|6.0|-1|1"
268
+ "p50_beta2_6_0_0p5_outwdm1|0.50|sampled_s|1|beta|0.0|0.5|2.0|6.0|-1|1"
269
+ "p50_beta2_2_0_0p5_outwdm1|0.50|sampled_s|1|beta|0.0|0.5|2.0|2.0|-1|1"
270
+ "p50_unif0_0p125_outwd0p3|0.50|sampled_s|1|uniform|0.0|0.125|2.0|6.0|0.3|1"
271
+ )
272
+
273
+ if [[ -n "${SWEEP_CONFIGS:-}" ]]; then
274
+ IFS=$'\n' read -r -d '' -a CONFIGS < <(printf '%s\0' "${SWEEP_CONFIGS}") || true
275
+ fi
276
+
277
+ for entry in "${CONFIGS[@]}"; do
278
+ IFS='|' read -r config rollout_prob time_mode rollout_steps s_dist s_min_frac s_max_frac s_beta_alpha s_beta_beta output_wd sync_t rollout_steps_min <<<"${entry}"
279
+ run_config "${config}" "${rollout_prob}" "${time_mode}" "${rollout_steps}" "${s_dist}" "${s_min_frac}" "${s_max_frac}" "${s_beta_alpha}" "${s_beta_beta}" "${output_wd}" "${sync_t}" "${rollout_steps_min:-}"
280
+ done
281
+
282
+ echo "[ctx1024-sampleds] done" | tee -a "${DRIVER_LOG}"
LTA_openwebtext_dualt/scripts/run_train8_decode_algo_sweep_len256_latest.sh ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd /e2e-data/evad-tech-vla/wanghan58/workspace/LTA_openwebtext_dualt
5
+
6
+ export PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
7
+ export TOKENIZERS_PARALLELISM=false
8
+ export PYTHONUNBUFFERED=1
9
+
10
+ DATA_DIR="${DATA_DIR:-/e2e-data/evad-tech-vla/wanghan58/data/small_benchmarks/langflow_2604_11748/openwebtext_lta_cached_chunks/gpt2_len256_train8_compact_overfit}"
11
+ TOKENIZER_PATH="${TOKENIZER_PATH:-/e2e-data/evad-tech-vla/wanghan58/models/flowtext_scorers/gpt2-standard/tokenizer.json}"
12
+ MAX_LEN="${MAX_LEN:-256}"
13
+ N_SAMPLES="${N_SAMPLES:-64}"
14
+ INFER_STEPS="${INFER_STEPS:-128}"
15
+ OUT_ROOT="${OUT_ROOT:-docs/lta_samples/metrics_20260517/train8_decode_algo_sweep_len256_latest}"
16
+ LOG_FILE="${LOG_FILE:-logs/train8_decode_algo_sweep_len256_latest/sweep.log}"
17
+ mkdir -p "$(dirname "${LOG_FILE}")" "${OUT_ROOT}"
18
+
19
+ modes=("${MODES:-onehot allcorrupt}")
20
+ variants=(
21
+ "flowmap|state|logit_normal|post|none|ode_trainlogit_post_state"
22
+ "flowmap|endpoint|logit_normal|post|none|ode_trainlogit_post_endpoint"
23
+ "flowmap|blend|logit_normal|post|none|ode_trainlogit_post_blend"
24
+ "flowmap|state|logit_normal|pre|none|ode_trainlogit_pre_state"
25
+ "flowmap|state|uniform|post|none|ode_uniform_post_state"
26
+ "flowmap|state|power_high|post|none|ode_powerhigh_post_state"
27
+ "log_geodesic|state|uniform|post|none|loggeo_uniform_post_state"
28
+ "log_geodesic|state|logit_normal|post|none|loggeo_trainlogit_post_state"
29
+ "flowmap|state|logit_normal|post|uniform|ode_trainlogit_post_state_softuniform"
30
+ )
31
+
32
+ for mode in ${modes[*]}; do
33
+ run_name="${RUN_PREFIX:-train8_n256_compactv969_3l_bs512_hard_ce_}${mode}"
34
+ if [[ ! -d "runs/${run_name}" ]]; then
35
+ echo "[decode-sweep] skip missing run=${run_name}" | tee -a "${LOG_FILE}"
36
+ continue
37
+ fi
38
+ for variant in "${variants[@]}"; do
39
+ IFS='|' read -r decode_rule final_from time_schedule model_t endpoint_softening tag <<<"${variant}"
40
+ out_dir="${OUT_ROOT}/${mode}/${tag}"
41
+ echo "[decode-sweep] $(date) mode=${mode} run=${run_name} tag=${tag}" | tee -a "${LOG_FILE}"
42
+ CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0}" python scripts/eval_train8_decode_acc.py \
43
+ --runs_glob "runs/${run_name}" \
44
+ --data_dir "${DATA_DIR}" \
45
+ --tokenizer_path "${TOKENIZER_PATH}" \
46
+ --out_dir "${out_dir}" \
47
+ --max_len "${MAX_LEN}" \
48
+ --n_samples "${N_SAMPLES}" \
49
+ --batch_size "${N_SAMPLES}" \
50
+ --latest_only \
51
+ --endpoint_softenings "${endpoint_softening}" \
52
+ --steps "${INFER_STEPS}" \
53
+ --decode_rule "${decode_rule}" \
54
+ --time_schedule "${time_schedule}" \
55
+ --time_logit_mean -1.5 \
56
+ --time_logit_std 0.8 \
57
+ --model_t_mode "${model_t}" \
58
+ --c_min 1 \
59
+ --c_max 512 \
60
+ --late_temp 1.0 \
61
+ --final_from "${final_from}" \
62
+ --final_decode argmax \
63
+ 2>&1 | tee -a "${LOG_FILE}"
64
+ done
65
+ done
66
+
67
+ python - "$OUT_ROOT" <<'PY' | tee -a "$LOG_FILE"
68
+ import json
69
+ import sys
70
+ from pathlib import Path
71
+
72
+ root = Path(sys.argv[1])
73
+ rows = []
74
+ for path in root.glob("*/*/decode_token_acc.jsonl"):
75
+ for line in path.read_text().splitlines():
76
+ if not line.strip():
77
+ continue
78
+ row = json.loads(line)
79
+ row["mode"] = path.parents[1].name
80
+ row["variant"] = path.parent.name
81
+ rows.append(row)
82
+ rows.sort(key=lambda r: (r["mode"], -float(r.get("token_acc_mean", 0.0)), r["variant"]))
83
+ out = root / "decode_algo_summary.tsv"
84
+ with out.open("w", encoding="utf-8") as f:
85
+ f.write("mode\tvariant\tckpt_step\ttoken_acc_mean\texact_count\texact_ref_count\tdecode_rule\tfinal_from\ttime_schedule\tmodel_t_mode\tendpoint_softening\n")
86
+ for r in rows:
87
+ f.write(
88
+ "\t".join(
89
+ [
90
+ str(r.get("mode")),
91
+ str(r.get("variant")),
92
+ str(r.get("ckpt_step")),
93
+ f"{float(r.get('token_acc_mean', 0.0)):.6f}",
94
+ str(r.get("exact_count")),
95
+ str(r.get("exact_ref_count")),
96
+ str(r.get("decode_rule")),
97
+ str(r.get("final_from")),
98
+ str(r.get("time_schedule")),
99
+ str(r.get("model_t_mode")),
100
+ str(r.get("endpoint_softening")),
101
+ ]
102
+ )
103
+ + "\n"
104
+ )
105
+ print(out)
106
+ for r in rows[:10]:
107
+ print(
108
+ "SWEEP_RESULT "
109
+ f"mode={r.get('mode')} variant={r.get('variant')} step={r.get('ckpt_step')} "
110
+ f"token_acc={float(r.get('token_acc_mean', 0.0)):.4f} "
111
+ f"exact={r.get('exact_count')}/{r.get('n_gen')} refs={r.get('exact_ref_count')}"
112
+ )
113
+ PY
LTA_openwebtext_dualt/scripts/sweep_categorical_c1024_late_refresh_20260506.py ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import importlib.util
6
+ import json
7
+ import math
8
+ import sys
9
+ from dataclasses import asdict, dataclass
10
+ from pathlib import Path
11
+
12
+ import torch
13
+ import torch.nn.functional as F
14
+ from transformers import AutoModelForCausalLM, AutoTokenizer
15
+
16
+
17
+ BASE_PATH = Path(__file__).with_name("eval_lm1b_200k_methods_genppl_20260506.py")
18
+ spec = importlib.util.spec_from_file_location("eval_lm1b_200k_methods_genppl_20260506", BASE_PATH)
19
+ if spec is None or spec.loader is None:
20
+ raise RuntimeError(f"Could not load {BASE_PATH}")
21
+ base = importlib.util.module_from_spec(spec)
22
+ sys.modules[spec.name] = base
23
+ spec.loader.exec_module(base)
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class RefreshCfg:
28
+ label: str
29
+ refresh_frac: float
30
+ sample_temp: float = 0.8
31
+ top_k: int = 16
32
+ select: str = "low_conf"
33
+
34
+
35
+ def default_configs() -> list[RefreshCfg]:
36
+ return [
37
+ RefreshCfg("base_argmax", 0.0, top_k=1),
38
+ RefreshCfg("lowconf05_t0p8_top16", 0.05, 0.8, 16),
39
+ RefreshCfg("lowconf10_t0p8_top16", 0.10, 0.8, 16),
40
+ RefreshCfg("lowconf15_t0p8_top16", 0.15, 0.8, 16),
41
+ RefreshCfg("lowconf20_t0p8_top16", 0.20, 0.8, 16),
42
+ RefreshCfg("lowconf10_t1p0_top32", 0.10, 1.0, 32),
43
+ RefreshCfg("lowconf15_t1p0_top32", 0.15, 1.0, 32),
44
+ RefreshCfg("lowconf20_t1p0_top64", 0.20, 1.0, 64),
45
+ RefreshCfg("random10_t0p8_top16", 0.10, 0.8, 16, select="random"),
46
+ RefreshCfg("random15_t0p8_top16", 0.15, 0.8, 16, select="random"),
47
+ ]
48
+
49
+
50
+ def load_endpoint_model(checkpoint: str, tokenizer, device: torch.device):
51
+ ckpt = torch.load(checkpoint, map_location="cpu", weights_only=False)
52
+ model = base.build_endpoint_model(ckpt, tokenizer, "categorical_fullvocab", device)
53
+ return ckpt, model
54
+
55
+
56
+ def sample_from_probs(probs: torch.Tensor, *, temp: float, top_k: int) -> torch.Tensor:
57
+ if top_k <= 1:
58
+ return probs.argmax(dim=-1)
59
+ k = min(int(top_k), probs.size(-1))
60
+ vals, inds = torch.topk(probs, k=k, dim=-1)
61
+ vals = vals.clamp_min(1e-20)
62
+ if temp != 1.0:
63
+ vals = vals.pow(1.0 / float(temp))
64
+ vals = vals / vals.sum(dim=-1, keepdim=True).clamp_min(1e-20)
65
+ picked = torch.multinomial(vals.reshape(-1, k), num_samples=1).view(*probs.shape[:-1])
66
+ return inds.gather(-1, picked.unsqueeze(-1)).squeeze(-1)
67
+
68
+
69
+ def apply_refresh(final_probs: torch.Tensor, cfg: RefreshCfg) -> torch.Tensor:
70
+ ids = final_probs.argmax(dim=-1)
71
+ if cfg.refresh_frac <= 0:
72
+ return ids
73
+ bs, length, _ = final_probs.shape
74
+ n_refresh = max(1, int(math.ceil(float(cfg.refresh_frac) * length)))
75
+ conf = final_probs.max(dim=-1).values
76
+ if cfg.select == "low_conf":
77
+ order_score = -conf
78
+ elif cfg.select == "random":
79
+ order_score = torch.rand_like(conf)
80
+ else:
81
+ raise ValueError(f"unknown select={cfg.select!r}")
82
+ chosen = torch.topk(order_score, k=min(n_refresh, length), dim=-1).indices
83
+ sampled = sample_from_probs(final_probs, temp=cfg.sample_temp, top_k=cfg.top_k)
84
+ return ids.scatter(1, chosen, sampled.gather(1, chosen))
85
+
86
+
87
+ @torch.inference_mode()
88
+ def generate_variants(
89
+ model,
90
+ tokenizer,
91
+ configs: list[RefreshCfg],
92
+ *,
93
+ n_samples: int,
94
+ batch_size: int,
95
+ max_len: int,
96
+ steps: int,
97
+ seed: int,
98
+ device: torch.device,
99
+ ) -> tuple[dict[str, list[list[int]]], dict[str, list[str]], dict]:
100
+ torch.manual_seed(seed)
101
+ eps = 1e-8
102
+ concentration_min = 1.0
103
+ concentration_max = 1024.0
104
+ all_ids = {cfg.label: [] for cfg in configs}
105
+ all_texts = {cfg.label: [] for cfg in configs}
106
+ remaining = n_samples
107
+ while remaining > 0:
108
+ bs = min(batch_size, remaining)
109
+ probs = base.sample_noise_simplex(
110
+ (bs, max_len),
111
+ tokenizer.vocab_size,
112
+ device,
113
+ eps,
114
+ noise_mode="dirichlet",
115
+ target_prob=1.0,
116
+ noise_sigma=-1.0,
117
+ dirichlet_concentration=1.0,
118
+ )
119
+ attn = torch.ones((bs, max_len), dtype=torch.bool, device=device)
120
+ last_endpoint = probs
121
+ for step in range(steps):
122
+ model_t = torch.full((bs,), 0.5, dtype=torch.float32, device=device)
123
+ logits = model(base.state_for_model(model, probs, eps), model_t, attn).float() / 1.3
124
+ endpoint = F.softmax(logits, dim=-1)
125
+ last_endpoint = endpoint
126
+
127
+ support_t = (step + 1) / max(steps, 1)
128
+ semantic_t = support_t**1.5
129
+ anchor = probs.clamp_min(eps)
130
+ anchor = anchor / anchor.sum(dim=-1, keepdim=True).clamp_min(eps)
131
+ guided = (1.0 - semantic_t) * anchor + semantic_t * endpoint
132
+ guided = guided.clamp_min(eps)
133
+ guided = guided / guided.sum(dim=-1, keepdim=True).clamp_min(eps)
134
+
135
+ mean = (1.0 - support_t) / float(tokenizer.vocab_size) + support_t * guided
136
+ mean = mean.clamp_min(eps)
137
+ mean = mean / mean.sum(dim=-1, keepdim=True).clamp_min(eps)
138
+ conc = math.exp(
139
+ math.log(concentration_min)
140
+ + support_t * (math.log(concentration_max) - math.log(concentration_min))
141
+ )
142
+ alpha = (mean * conc).clamp_min(eps)
143
+ probs = torch._standard_gamma(alpha).clamp_min(eps)
144
+ probs = probs / probs.sum(dim=-1, keepdim=True).clamp_min(eps)
145
+
146
+ final_probs = 0.5 * probs + 0.5 * last_endpoint
147
+ final_probs = final_probs.clamp_min(eps)
148
+ final_probs = final_probs / final_probs.sum(dim=-1, keepdim=True).clamp_min(eps)
149
+ for cfg in configs:
150
+ ids = apply_refresh(final_probs, cfg).detach().cpu().tolist()
151
+ all_ids[cfg.label].extend(ids)
152
+ all_texts[cfg.label].extend(tokenizer.decode(row, stop_at_eos=False, skip_special_tokens=False) for row in ids)
153
+ remaining -= bs
154
+ print(f"[decode] generated base states {n_samples - remaining}/{n_samples}", flush=True)
155
+
156
+ base_decode = {
157
+ "kind": "categorical_fullvocab",
158
+ "steps": steps,
159
+ "model_t_mode": "const05",
160
+ "base_decode_rule": "dual_line_resample_rolling",
161
+ "support_power": 1.0,
162
+ "semantic_power": 1.5,
163
+ "endpoint_temp": 1.3,
164
+ "final_from": "blend_then_refresh",
165
+ "n_samples": n_samples,
166
+ "seed": seed,
167
+ }
168
+ return all_ids, all_texts, base_decode
169
+
170
+
171
+ def main() -> None:
172
+ p = argparse.ArgumentParser()
173
+ p.add_argument(
174
+ "--checkpoint",
175
+ default="runs/lta_lm1b_dirichlet_categorical_fullvocab_dualt_flmpack_onehot_hardce_ddit_small_len128_gbs512_8gpu_1m_nw0/latest.pt",
176
+ )
177
+ p.add_argument("--tokenizer_path", required=True)
178
+ p.add_argument("--scorer", required=True)
179
+ p.add_argument("--out_dir", required=True)
180
+ p.add_argument("--n_samples", type=int, default=128)
181
+ p.add_argument("--max_len", type=int, default=128)
182
+ p.add_argument("--steps", type=int, default=1024)
183
+ p.add_argument("--decode_batch", type=int, default=16)
184
+ p.add_argument("--score_batch", type=int, default=8)
185
+ p.add_argument("--score_max_length", type=int, default=256)
186
+ p.add_argument("--seed", type=int, default=20260506)
187
+ p.add_argument("--only", default="", help="Optional comma-separated config labels.")
188
+ args = p.parse_args()
189
+
190
+ selected = {x.strip() for x in args.only.split(",") if x.strip()}
191
+ configs = [c for c in default_configs() if not selected or c.label in selected]
192
+ if not configs:
193
+ raise SystemExit(f"No configs selected by --only={args.only!r}")
194
+
195
+ out_dir = Path(args.out_dir)
196
+ out_dir.mkdir(parents=True, exist_ok=True)
197
+ summary_path = out_dir / "summary.jsonl"
198
+ summary_path.write_text("", encoding="utf-8")
199
+
200
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
201
+ tokenizer = base.BpeTextTokenizer.from_file(args.tokenizer_path)
202
+ ckpt, model = load_endpoint_model(args.checkpoint, tokenizer, device)
203
+ step = ckpt.get("step")
204
+ print(f"[load] checkpoint={args.checkpoint} step={step}", flush=True)
205
+
206
+ scorer_tok = AutoTokenizer.from_pretrained(args.scorer)
207
+ if scorer_tok.pad_token_id is None:
208
+ scorer_tok.pad_token = scorer_tok.eos_token
209
+ scorer_tok.pad_token_id = scorer_tok.eos_token_id
210
+ scorer = AutoModelForCausalLM.from_pretrained(args.scorer).to(device).eval()
211
+ if getattr(scorer.config, "pad_token_id", None) is None:
212
+ scorer.config.pad_token_id = scorer_tok.pad_token_id
213
+
214
+ ids_by_label, texts_by_label, base_decode = generate_variants(
215
+ model,
216
+ tokenizer,
217
+ configs,
218
+ n_samples=args.n_samples,
219
+ batch_size=args.decode_batch,
220
+ max_len=args.max_len,
221
+ steps=args.steps,
222
+ seed=args.seed,
223
+ device=device,
224
+ )
225
+
226
+ summaries = []
227
+ with summary_path.open("a", encoding="utf-8") as sf:
228
+ for cfg in configs:
229
+ decode = dict(base_decode)
230
+ decode.update({"decode_rule": "late_low_conf_refresh", "refresh": asdict(cfg)})
231
+ target = base.EvalTarget(f"categorical_c1024_late_refresh_{cfg.label}", "categorical_fullvocab", args.checkpoint)
232
+ summary = base.score_and_write(
233
+ target=target,
234
+ checkpoint=args.checkpoint,
235
+ step=step,
236
+ decode=decode,
237
+ ids=ids_by_label[cfg.label],
238
+ raw_texts=texts_by_label[cfg.label],
239
+ scorer=scorer,
240
+ scorer_tok=scorer_tok,
241
+ score_batch=args.score_batch,
242
+ score_max_length=args.score_max_length,
243
+ device=device,
244
+ out_dir=out_dir,
245
+ )
246
+ summary["config"] = asdict(cfg)
247
+ sf.write(json.dumps(summary, ensure_ascii=False) + "\n")
248
+ sf.flush()
249
+ summaries.append(summary)
250
+ div = summary["diversity"]
251
+ print(
252
+ f"[summary] {cfg.label} raw={summary['raw_genppl']['ppl']:.3f} "
253
+ f"strip={summary['stripped_genppl']['ppl']:.3f} "
254
+ f"ent={div['sample_entropy']:.3f} d2={div['distinct_2']:.3f} "
255
+ f"top={div['top_token_mass']:.3f}",
256
+ flush=True,
257
+ )
258
+
259
+ table_path = out_dir / "summary.tsv"
260
+ with table_path.open("w", encoding="utf-8") as f:
261
+ f.write(
262
+ "label\traw_genppl\tstripped_genppl\tsample_entropy\tdistinct_2\ttop_token_mass\t"
263
+ "refresh_frac\tsample_temp\ttop_k\tselect\tmeets_target\n"
264
+ )
265
+ for summary in summaries:
266
+ div = summary["diversity"]
267
+ raw = summary["raw_genppl"]["ppl"]
268
+ ent = div["sample_entropy"]
269
+ cfg = summary["config"]
270
+ meets = raw <= 30.0 and ent >= 4.1
271
+ f.write(
272
+ f"{cfg['label']}\t{raw:.6f}\t{summary['stripped_genppl']['ppl']:.6f}\t"
273
+ f"{ent:.6f}\t{div['distinct_2']:.6f}\t{div['top_token_mass']:.6f}\t"
274
+ f"{cfg['refresh_frac']:.3f}\t{cfg['sample_temp']:.3f}\t{cfg['top_k']}\t"
275
+ f"{cfg['select']}\t{int(meets)}\n"
276
+ )
277
+ print(f"[done] {out_dir}", flush=True)
278
+
279
+
280
+ if __name__ == "__main__":
281
+ main()