Spaces:
Sleeping
Sleeping
File size: 26,422 Bytes
00cabba | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | // Forge β mock graph + resolve engine
// Matches the FastAPI shapes in the handoff doc, so swap to fetch() later.
window.FORGE_NODES = [
// optimizers
{ canonical: "adamw", name: "AdamW", type: "optimizer", description: "Workhorse decoupled-weight-decay optimizer. Safe default.", tier: 1 },
{ canonical: "adamw_8bit", name: "AdamW 8-bit", type: "optimizer", description: "bitsandbytes 8-bit AdamW. Saves VRAM. Default param groups can fight per-layer LR tricks.", tier: 1 },
{ canonical: "paged_adamw", name: "Paged AdamW", type: "optimizer", description: "CPU-paged optimizer states. For when you really can't fit.", tier: 2 },
{ canonical: "lion", name: "Lion", type: "optimizer", description: "Sign-momentum optimizer. Lower memory than AdamW; needs lower LR.", tier: 2 },
{ canonical: "muon", name: "Muon", type: "optimizer", description: "NewtonβSchulz orthogonalized momentum. Faster convergence on hidden weights.", tier: 2 },
{ canonical: "sophia", name: "Sophia-G", type: "optimizer", description: "Hessian-informed second-order. Promising for LLMs.", tier: 3 },
{ canonical: "adafactor", name: "Adafactor", type: "optimizer", description: "Memory-light. Tricky LR schedule.", tier: 2 },
// schedulers
{ canonical: "cosine", name: "Cosine", type: "scheduler", description: "Cosine decay with warmup. Boring; works.", tier: 1 },
{ canonical: "onecycle", name: "OneCycle", type: "scheduler", description: "Aggressive warm-then-anneal. Faster but can overshoot on long runs.", tier: 2 },
{ canonical: "dlrs", name: "DLRS", type: "scheduler", description: "Rick's dynamic LR scheduler. #1 on val_loss in the bench.", tier: 1 },
{ canonical: "linear", name: "Linear", type: "scheduler", description: "Linear warmup β linear decay.", tier: 1 },
{ canonical: "wsd", name: "WSD", type: "scheduler", description: "WarmupβStableβDecay. Continual-pretrain friendly.", tier: 2 },
{ canonical: "constant", name: "Constant", type: "scheduler", description: "Flat. Combine with manual restarts.", tier: 1 },
// techniques
{ canonical: "qlora", name: "QLoRA", type: "technique", description: "4-bit base + LoRA adapters. Lets a 70B fit on one card.", tier: 1 },
{ canonical: "lora", name: "LoRA", type: "technique", description: "Low-rank adapters. Cheap, composable, the default PEFT.", tier: 1 },
{ canonical: "fft", name: "Full Fine-Tune", type: "technique", description: "Update every parameter. Hungry. Mutually exclusive with adapter methods.", tier: 1 },
{ canonical: "grad_ckpt", name: "Grad Checkpoint", type: "technique", description: "Trade FLOPs for VRAM. Must be off for vLLM gen during training.", tier: 1 },
{ canonical: "per_layer_lr_rotation", name: "Per-Layer LR Rotation", type: "technique", description: "Rick's trick: rotate LR across layer bands per step. Needs custom param groups.", tier: 1 },
{ canonical: "chaos_inject", name: "Chaos Injectors", type: "technique", description: "Activation perturbation at hidden layers. NaN-prone without staged melt-in.", tier: 1 },
{ canonical: "jacobian_reg", name: "Jacobian Reg", type: "technique", description: "Smoothness penalty via Jacobian. Forward pass corrupts the injector cache.", tier: 1 },
{ canonical: "fsdp", name: "FSDP", type: "technique", description: "Fully-Sharded Data Parallel. Sharding for big models.", tier: 1 },
{ canonical: "ddp", name: "DDP", type: "technique", description: "Vanilla data-parallel. Cheap when the model fits.", tier: 1 },
{ canonical: "deepspeed_z3", name: "DeepSpeed ZeRO-3", type: "technique", description: "ZeRO stage 3 partitioning. Battle-tested.", tier: 1 },
{ canonical: "unsloth", name: "Unsloth", type: "technique", description: "Fused kernels for LoRA/QLoRA. PyTorch-only; tight coupling to bnb.", tier: 2 },
// quantization
{ canonical: "bnb_4bit", name: "bnb 4-bit", type: "quantization", description: "bitsandbytes NF4. The QLoRA base.", tier: 1 },
{ canonical: "bnb_8bit", name: "bnb 8-bit", type: "quantization", description: "LLM.int8(). Inference-leaning; training works.", tier: 1 },
{ canonical: "gptq", name: "GPTQ", type: "quantization", description: "Post-training quant. Inference-only for our purposes.", tier: 2 },
{ canonical: "awq", name: "AWQ", type: "quantization", description: "Activation-aware weight quant. Inference-time.", tier: 2 },
// architectures
{ canonical: "llama3", name: "Llama-3", type: "architecture", description: "Llama-3 8B / 70B family.", tier: 1 },
{ canonical: "mistral", name: "Mistral", type: "architecture", description: "Mistral / Mixtral.", tier: 1 },
{ canonical: "qwen2", name: "Qwen-2.5", type: "architecture", description: "Strong open multilingual base.", tier: 1 },
{ canonical: "distilbert", name: "DistilBERT", type: "architecture", description: "The bench model. SST-2 sandbox.", tier: 1 },
// inference
{ canonical: "vllm", name: "vLLM", type: "inference", description: "PagedAttention server. Needs grad-ckpt off during in-train generation.", tier: 1 },
{ canonical: "sglang", name: "SGLang", type: "inference", description: "Structured-gen server.", tier: 2 },
];
// edges. relations: REQUIRES, CONDITIONAL, COMPATIBLE, DEGRADES, BREAKS
// Direction: from β to. For REQUIRES: "from needs to to work".
// For BREAKS: symmetric in display but stored once.
window.FORGE_EDGES = [
// --- T1 verified seed (from the backend doc) -----------------------------
{ from: "per_layer_lr_rotation", to: "adamw_8bit", relation: "BREAKS", tier: 1, confidence: 1.0,
fix: "Pass custom optimizer_grouped_parameters β adamw_8bit's default decay/no-decay split overrides your per-layer LR bands.",
evidence: [{ url: "mempalace://chaos-injection-trainer-notes", quote: "adamw_8bit produces decay/no-decay param groups by default; per-layer LR rotation silently no-ops unless you pass optimizer_grouped_parameters yourself.", source_type: "practitioner_run", tier: 1 }] },
{ from: "jacobian_reg", to: "chaos_inject", relation: "BREAKS", tier: 1, confidence: 1.0,
fix: "Jacobian-reg's extra forward pass corrupts the injector activation cache β ortho_loss is poisoned. Disable one.",
evidence: [{ url: "mempalace://chaos-injection-trainer-notes", quote: "the jacobian reg forward overwrites the activation cache that chaos_inject samples from; ortho_loss explodes.", source_type: "practitioner_run", tier: 1 }] },
{ from: "chaos_inject", to: "staged_meltin", relation: "REQUIRES", tier: 1, confidence: 1.0,
fix: "Stage injectors in over ~100 steps; NaN at layer ~6 if injected from step 0.",
evidence: [{ url: "mempalace://chaos-injection-trainer-notes", quote: "NaN at injector layer ~6 if run from step 0; staged melt-in over 100 steps fixed it.", source_type: "practitioner_run", tier: 1 }] },
{ from: "grad_ckpt", to: "vllm", relation: "BREAKS", tier: 1, confidence: 1.0,
fix: "Disable gradient_checkpointing for the in-train vLLM gen pass. TRL-documented.",
evidence: [{ url: "https://huggingface.co/docs/trl", quote: "gradient_checkpointing must be disabled when generating with vLLM during training.", source_type: "official_docs", tier: 1 }] },
// --- core technique mutex / requires -------------------------------------
{ from: "qlora", to: "fft", relation: "BREAKS", tier: 1, confidence: 1.0,
fix: "QLoRA freezes the base model; Full Fine-Tune updates it. Pick one.",
evidence: [{ url: "https://arxiv.org/abs/2305.14314", quote: "QLoRA backprops gradients through a frozen 4-bit quantized model into low-rank adapters.", source_type: "paper", tier: 1 }] },
{ from: "qlora", to: "bnb_4bit", relation: "REQUIRES", tier: 1, confidence: 1.0,
fix: "QLoRA is defined as 4-bit NF4 base + LoRA adapters β load the base in bnb 4-bit.",
evidence: [{ url: "https://huggingface.co/docs/peft", quote: "QLoRA fine-tunes a 4-bit quantized base model loaded via bitsandbytes NF4.", source_type: "official_docs", tier: 1 }] },
{ from: "qlora", to: "lora", relation: "REQUIRES", tier: 1, confidence: 1.0,
fix: "QLoRA = 4-bit base + LoRA adapters. The adapter rank is your hyperparameter.",
evidence: [{ url: "https://arxiv.org/abs/2305.14314", quote: "QLoRA augments the frozen quantized model with Low-Rank Adapters.", source_type: "paper", tier: 1 }] },
{ from: "lora", to: "fft", relation: "BREAKS", tier: 2, confidence: 0.85,
fix: "Adapter-method and full fine-tune are mutually exclusive within one run.",
evidence: [{ url: "https://huggingface.co/docs/peft", quote: "PEFT methods freeze the base; choose either full fine-tuning or a PEFT method per run.", source_type: "official_docs", tier: 2 }] },
// --- optimizer β quantization --------------------------------------------
{ from: "muon", to: "adamw_8bit", relation: "BREAKS", tier: 2, confidence: 0.8,
fix: "Muon owns the optimizer step for hidden weights; 8-bit AdamW state is incompatible with the NewtonβSchulz update.",
evidence: [{ url: "https://kellerjordan.github.io/posts/muon/", quote: "Muon replaces the optimizer update for 2D weights; use AdamW for the rest, not its 8-bit variant.", source_type: "blog", tier: 2 }] },
{ from: "muon", to: "adamw", relation: "REQUIRES", tier: 2, confidence: 0.9,
fix: "Muon only updates 2D hidden weights β embeddings + biases still need AdamW.",
evidence: [{ url: "https://kellerjordan.github.io/posts/muon/", quote: "non-hidden parameters (embeddings, scalars) are handled by a standard AdamW.", source_type: "blog", tier: 2 }] },
{ from: "lion", to: "bnb_8bit", relation: "DEGRADES", tier: 3, confidence: 0.5,
fix: "Lion sign-update interacts poorly with 8-bit state quant β drop to 16-bit moments.",
evidence: [{ url: "https://github.com/bitsandbytes-foundation/bitsandbytes/issues", quote: "single user report: Lion+8-bit moments diverged at step 4k on a 7B base.", source_type: "issue", tier: 3 }] },
// --- unsloth / quant family ----------------------------------------------
{ from: "unsloth", to: "bnb_4bit", relation: "REQUIRES", tier: 1, confidence: 1.0,
fix: "Unsloth's fused kernels assume a bnb 4-bit base.",
evidence: [{ url: "https://github.com/unslothai/unsloth", quote: "Unsloth supports 4-bit quantized models via bitsandbytes for QLoRA fine-tuning.", source_type: "official_docs", tier: 1 }] },
{ from: "unsloth", to: "lora", relation: "REQUIRES", tier: 1, confidence: 1.0,
fix: "Unsloth's fast path is the LoRA / QLoRA path.",
evidence: [{ url: "https://github.com/unslothai/unsloth", quote: "Unsloth accelerates LoRA and QLoRA fine-tuning with custom Triton kernels.", source_type: "official_docs", tier: 1 }] },
{ from: "unsloth", to: "fsdp", relation: "BREAKS", tier: 2, confidence: 0.8,
fix: "Unsloth's custom kernels don't compose with FSDP sharding hooks today.",
evidence: [{ url: "https://github.com/unslothai/unsloth/issues", quote: "FSDP is not currently supported alongside Unsloth's fused kernels.", source_type: "issue", tier: 2 }] },
// --- inference quants (category errors) ----------------------------------
{ from: "awq", to: "fft", relation: "BREAKS", tier: 2, confidence: 0.85,
fix: "AWQ is an inference-time weight quant. You can't fine-tune through it.",
evidence: [{ url: "https://github.com/casper-hansen/AutoAWQ", quote: "AWQ is intended for post-training quantization for inference.", source_type: "official_docs", tier: 2 }] },
{ from: "gptq", to: "fft", relation: "BREAKS", tier: 2, confidence: 0.85,
fix: "GPTQ is post-training quant β frozen base only.",
evidence: [{ url: "https://arxiv.org/abs/2210.17323", quote: "GPTQ is a one-shot post-training quantization method.", source_type: "paper", tier: 2 }] },
// --- distributed -----------------------------------------------------------
{ from: "fsdp", to: "bnb_4bit", relation: "CONDITIONAL", tier: 2, confidence: 0.8, conditions: { plugin: "bnb-fsdp" },
fix: "Works only with the bnb-FSDP plugin; vanilla FSDP shards over uninitialized 4-bit weights.",
evidence: [{ url: "https://huggingface.co/docs/accelerate", quote: "FSDP + bitsandbytes 4-bit requires the bnb-fsdp wrap policy.", source_type: "official_docs", tier: 2 }] },
{ from: "deepspeed_z3", to: "bnb_8bit", relation: "DEGRADES", tier: 3, confidence: 0.5,
fix: "Reports of slowdown / hangs on multi-node Z3 + 8-bit. Use bf16 weights, 8-bit optimizer states only.",
evidence: [{ url: "https://github.com/microsoft/DeepSpeed/issues", quote: "Z3 + 8-bit weights hang on the param-gather step in some configs.", source_type: "issue", tier: 3 }] },
// --- scheduler benchmark relations ---------------------------------------
{ from: "dlrs", to: "distilbert", relation: "COMPATIBLE", tier: 1, confidence: 1.0,
fix: "DLRS #1 on the SST-2 bench: val_loss 0.2653, val_acc 0.890, steps_to_target 266.7 (n=3 seeds).",
evidence: [{ url: "https://huggingface.co/spaces/juiceb0xc0de/lr-scheduler-benchmark", quote: "DLRS leads on val_loss across 3 seeds on distilbert/sst2.", source_type: "benchmark", tier: 1 }] },
{ from: "onecycle", to: "distilbert", relation: "DEGRADES", tier: 1, confidence: 1.0,
fix: "OneCycle underperforms on the SST-2 bench: val_loss 0.4284 vs cohort cutoff 0.4022.",
evidence: [{ url: "https://huggingface.co/spaces/juiceb0xc0de/lr-scheduler-benchmark", quote: "OneCycle val_loss 0.4284 is above the cohort cutoff 0.4022.", source_type: "benchmark", tier: 1 }] },
// --- compatible/positive edges (just so the graph isn't all conflict) ----
{ from: "lora", to: "bnb_8bit", relation: "COMPATIBLE", tier: 2, confidence: 0.8, fix: "", evidence: [] },
{ from: "lora", to: "bnb_4bit", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "grad_ckpt", to: "fsdp", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "grad_ckpt", to: "qlora",relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "cosine", to: "adamw", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "dlrs", to: "adamw", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "fsdp", to: "llama3", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "qlora", to: "llama3", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "qlora", to: "mistral", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "qlora", to: "qwen2", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "lora", to: "distilbert", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "vllm", to: "llama3", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "vllm", to: "mistral", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "deepspeed_z3", to: "fft", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "fsdp", to: "fft", relation: "COMPATIBLE", tier: 1, confidence: 1.0, fix: "", evidence: [] },
{ from: "muon", to: "llama3", relation: "COMPATIBLE", tier: 2, confidence: 0.8, fix: "", evidence: [] },
];
// add "staged melt-in" as a hidden technique reachable as a fix-target
window.FORGE_NODES.push({
canonical: "staged_meltin", name: "Staged Melt-In", type: "technique",
description: "Linear ramp-in of chaos injectors over N steps. Prevents NaN at layer ~6.",
tier: 1,
});
// ============================================================================
// RESOLVE ENGINE
// ============================================================================
// For each non-selected node N, look at edges between N and any selected S:
// BREAKS β blocked (red)
// REQUIRES(S β N) β S needs N; mark N "needed by S" (amber/conditional)
// REQUIRES(N β S) β N needs S, S is selected β that requirement is satisfied (ignore)
// CONDITIONAL β conditional (amber) with conditions
// DEGRADES β available + warning
// COMPATIBLE β available
// Plus: if N has any REQUIRES(N β X) where X is *not* selected and X is also not
// universally optional, N is conditional ("needs X").
window.forgeResolve = function (selectedCanons) {
const sel = new Set(selectedCanons);
const out = {};
const nodeByCanon = Object.fromEntries(window.FORGE_NODES.map(n => [n.canonical, n]));
const incoming = {};
const outgoing = {};
for (const e of window.FORGE_EDGES) {
(outgoing[e.from] = outgoing[e.from] || []).push(e);
(incoming[e.to] = incoming[e.to] || []).push(e);
}
for (const n of window.FORGE_NODES) {
if (sel.has(n.canonical)) {
out[n.canonical] = { status: "selected", reasons: [], warnings: [] };
continue;
}
const reasons = [];
const warnings = [];
// edges adjacent to n
const adj = [...(outgoing[n.canonical] || []), ...(incoming[n.canonical] || [])];
for (const e of adj) {
const otherCanon = e.from === n.canonical ? e.to : e.from;
const direction = e.from === n.canonical ? "out" : "in"; // n -> other or other -> n
const other = nodeByCanon[otherCanon];
if (!other) continue;
if (sel.has(otherCanon)) {
if (e.relation === "BREAKS") {
reasons.push({
kind: "blocked",
label: `breaks with ${other.name}`,
fix: e.fix,
evidence: e.evidence,
tier: e.tier,
confidence: e.confidence,
otherCanon,
});
} else if (e.relation === "CONDITIONAL") {
reasons.push({
kind: "conditional",
label: `conditional on ${other.name}`,
fix: e.fix,
conditions: e.conditions,
evidence: e.evidence,
tier: e.tier,
otherCanon,
});
} else if (e.relation === "REQUIRES" && direction === "in") {
// other -> n means "other requires n". other is selected, n is not.
// n is a missing ingredient.
reasons.push({
kind: "needed-by",
label: `needed by ${other.name}`,
fix: e.fix,
evidence: e.evidence,
tier: e.tier,
otherCanon,
});
} else if (e.relation === "DEGRADES") {
warnings.push({
label: `degrades with ${other.name}`,
fix: e.fix,
evidence: e.evidence,
tier: e.tier,
otherCanon,
});
}
}
}
let status = "available";
if (reasons.some(r => r.kind === "blocked")) status = "blocked";
else if (reasons.some(r => r.kind === "conditional" || r.kind === "needed-by")) status = "conditional";
out[n.canonical] = { status, reasons, warnings };
}
return out;
};
// recipe payload
window.forgeRecipe = function (selectedCanons) {
const sel = new Set(selectedCanons);
const nodeByCanon = Object.fromEntries(window.FORGE_NODES.map(n => [n.canonical, n]));
const conflicts = [];
const unmet = [];
const warnings = [];
for (const e of window.FORGE_EDGES) {
const a = sel.has(e.from), b = sel.has(e.to);
if (a && b) {
if (e.relation === "BREAKS") {
conflicts.push({ a: nodeByCanon[e.from].name, b: nodeByCanon[e.to].name, fix: e.fix, tier: e.tier, evidence: e.evidence });
}
if (e.relation === "DEGRADES") {
warnings.push({ a: nodeByCanon[e.from].name, b: nodeByCanon[e.to].name, fix: e.fix, tier: e.tier, evidence: e.evidence });
}
} else if (a && !b && e.relation === "REQUIRES") {
unmet.push({ from: nodeByCanon[e.from].name, missing: nodeByCanon[e.to].name, missingCanon: e.to, fix: e.fix, tier: e.tier, evidence: e.evidence });
} else if (!a && b && e.relation === "REQUIRES") {
// selected b but not a; the requires goes from aβb meaning a needs b. a not selected, so not unmet here.
}
}
// scheduler benchmark cohort (mock real bench data)
const scheduler_picks = [
{ component: "DLRS", val_loss: 0.26528, val_acc: 0.89029, steps_to_target: 266.7, n_seeds: 3, source: "https://huggingface.co/spaces/juiceb0xc0de/lr-scheduler-benchmark", canonical: "dlrs" },
{ component: "Cosine", val_loss: 0.31417, val_acc: 0.87959, steps_to_target: 312.0, n_seeds: 3, source: "https://huggingface.co/spaces/juiceb0xc0de/lr-scheduler-benchmark", canonical: "cosine" },
{ component: "WSD", val_loss: 0.34081, val_acc: 0.86790, steps_to_target: 348.3, n_seeds: 3, source: "https://huggingface.co/spaces/juiceb0xc0de/lr-scheduler-benchmark", canonical: "wsd" },
];
const scheduler_warnings = [
{ component: "OneCycle", val_loss: 0.42844, cutoff: 0.4022, canonical: "onecycle" },
];
const valid = conflicts.length === 0 && unmet.length === 0;
return { selected: selectedCanons, valid, conflicts, unmet, warnings, scheduler_picks, scheduler_warnings };
};
// ============================================================================
// LIVE DISCOVERIES FEED (mock SSE)
// ============================================================================
window.FORGE_DISCOVERIES = [
{ a: "Gradient Checkpointing", relation: "COMPATIBLE", b: "LoRA", tier: 2, source: "huggingface.co/docs/peft", ts_offset: -8 },
{ a: "Muon", relation: "REQUIRES", b: "AdamW", tier: 2, source: "kellerjordan.github.io", ts_offset: -22 },
{ a: "DeepSpeed ZeRO-3", relation: "DEGRADES", b: "bnb 8-bit", tier: 3, source: "github.com/microsoft/DeepSpeed", ts_offset: -41 },
{ a: "QLoRA", relation: "COMPATIBLE", b: "Qwen-2.5", tier: 2, source: "qwenlm.github.io", ts_offset: -67 },
{ a: "FSDP", relation: "CONDITIONAL",b: "bnb 4-bit", tier: 2, source: "huggingface.co/docs/accelerate", ts_offset: -94 },
{ a: "Sophia-G", relation: "DEGRADES", b: "bnb 8-bit", tier: 3, source: "github.com/Liuhong99/Sophia", ts_offset: -128 },
{ a: "WSD", relation: "COMPATIBLE", b: "Continual PT", tier: 2, source: "arxiv.org/abs/2404.06395", ts_offset: -171 },
{ a: "Unsloth", relation: "BREAKS", b: "FSDP", tier: 2, source: "github.com/unslothai/unsloth", ts_offset: -210 },
{ a: "AWQ", relation: "BREAKS", b: "Full Fine-Tune",tier: 2, source: "github.com/casper-hansen/AutoAWQ", ts_offset: -266 },
{ a: "OneCycle", relation: "DEGRADES", b: "distilbert/sst2", tier: 1, source: "hf.co/spaces/juiceb0xc0de/lr-scheduler-benchmark", ts_offset: -311 },
];
// new live discoveries that stream in over time (offsets in seconds from "now")
window.FORGE_FUTURE_DISCOVERIES = [
{ a: "Per-Layer LR Rotation", relation: "BREAKS", b: "AdamW 8-bit", tier: 1, source: "mempalace://rick-notes" },
{ a: "Jacobian Reg", relation: "BREAKS", b: "Chaos Injectors", tier: 1, source: "mempalace://rick-notes" },
{ a: "Lion", relation: "DEGRADES", b: "bnb 8-bit", tier: 3, source: "github.com/bitsandbytes-foundation/bitsandbytes" },
{ a: "Paged AdamW", relation: "COMPATIBLE", b: "QLoRA", tier: 2, source: "huggingface.co/docs/transformers" },
{ a: "DLRS", relation: "COMPATIBLE", b: "WSD", tier: 2, source: "hf.co/spaces/juiceb0xc0de/lr-scheduler-benchmark" },
{ a: "Cosine", relation: "COMPATIBLE", b: "AdamW", tier: 1, source: "pytorch.org/docs" },
{ a: "FlashAttention-3", relation: "COMPATIBLE", b: "Llama-3", tier: 2, source: "github.com/Dao-AILab/flash-attention" },
{ a: "Liger Kernel", relation: "COMPATIBLE", b: "Unsloth", tier: 3, source: "github.com/linkedin/Liger-Kernel" },
];
// ============================================================================
// LIVE API BOOTSTRAP β prefer the live Forge API; fall back to the bundled mock.
// Default base is same-origin (the API serves this frontend in prod).
// Split-port dev: ?api=http://localhost:8010
// ============================================================================
window.FORGE_API = (function () {
const m = location.search.match(/[?&]api=([^&]+)/);
return m ? decodeURIComponent(m[1]) : "";
})();
window.FORGE_LIVE = false;
window.forgeBootstrap = async function () {
const base = window.FORGE_API.replace(/\/$/, "");
try {
const g = await (await fetch(base + "/graph", { cache: "no-store" })).json();
if (g && Array.isArray(g.nodes) && g.nodes.length && Array.isArray(g.edges)) {
const tierByNode = {};
for (const e of g.edges) {
for (const c of [e.from_canon, e.to_canon]) {
tierByNode[c] = Math.min(tierByNode[c] == null ? 9 : tierByNode[c], e.tier || 2);
}
}
window.FORGE_NODES = g.nodes.map(n => ({
canonical: n.canonical, name: n.name, type: n.type,
description: n.description || "", tier: tierByNode[n.canonical] || 2,
}));
window.FORGE_EDGES = g.edges.map(e => ({
from: e.from_canon, to: e.to_canon, relation: e.relation, tier: e.tier,
confidence: e.confidence, fix: e.fix || "", conditions: e.conditions || {},
evidence: e.evidence || [],
}));
window.FORGE_LIVE = true;
}
const feed = await (await fetch(base + "/feed?n=12", { cache: "no-store" })).json();
if (Array.isArray(feed) && feed.length) {
window.FORGE_DISCOVERIES = feed.map(f => ({
a: f.a, relation: f.relation, b: f.b, tier: f.tier, source: "bright data", ts_offset: 0,
}));
}
} catch (err) {
console.warn("[forge] live API unavailable, using bundled mock:", err.message);
}
return window.FORGE_LIVE;
};
|