Molbap HF Staff commited on
Commit
347ff85
·
1 Parent(s): b5d63a3

big update

Browse files
content/article.md CHANGED
@@ -2,13 +2,24 @@
2
  ## Introduction
3
 
4
  The `transformers` library, built with `PyTorch`, supports all state-of-the-art LLMs, many VLMs, task-specific vision language models, video models, audio models, table models, classical encoders, to a global count of almost 400 models.
 
5
  The name of the library itself is mostly majority driven as many models are not even transformers architectures, like Mamba, Zamba, RWKV, and convolution-based models.
 
6
  Regardless, each of these is wrought by the research and engineering team that created them, then harmonized into a now famous interface, and callable with a simple `.from_pretrained` command.
 
7
  Inference works for all models, training is functional for most. The library is a foundation for many machine learning courses, cookbooks, and overall, several thousands other open-source libraries depend on it. All models are tested as part of a daily CI ensuring their preservation and reproducibility. Most importantly, it is _open-source_ and has been written by the community for a large part.
8
  This isn't really to brag but to set the stakes: what does it take to keep such a ship afloat, made of so many moving, unrelated parts?
 
9
  The ML wave has not stopped, there's more and more models being added, at a steadily growing rate. `Transformers` is widely used, and we read the feedback that users post online. Whether it's about a function that had 300+ keyword arguments, duplicated code and helpers, and mentions of `Copied from ... ` everywhere, along with optimisation concerns. Text-only models are relatively tamed, but multimodal models remain to be harmonized.
10
 
11
- Here we will dissect what is the new design philosophy of transformers, as a continuation from the existing older [philosophy](https://huggingface.co/docs/transformers/en/philosophy) page, and an accompanying [blog post from 2022](https://huggingface.co/blog/transformers-design-philosophy) . Some time ago I dare not say how long, we discussed with transformers maintainers about the state of things. A lot of recent developments were satisfactory, but if we were only talking about these, self-congratulation would be the only goalpost. Reflecting on this philosophy now, as models pile up, is essential and will drive new developments.
 
 
 
 
 
 
 
12
 
13
  ### What you will learn
14
 
@@ -325,14 +336,15 @@ curl -X POST http://localhost:8000/v1/chat/completions \
325
  ```
326
 
327
  This provides an OpenAI-compatible API with features like continuous batching for better GPU utilization.
 
328
  ## Community reusability
329
 
330
 
331
  Adding a model to transformers means:
332
  - having it immediately available to the community
333
- - usable in vLLM, SGLang, and so on without additional code.
334
 
335
- ## Inner cooking: CUDA Warmup
336
 
337
  Having a clean _external_ API allows us to work on the true inner workings of transformers. One of the few recent additions was the _CUDA warmup_ via `caching_allocator_warmup` which improved massively the loading footprint by pre-allocating GPU memory to avoid malloc bottlenecks during model loading.
338
 
 
2
  ## Introduction
3
 
4
  The `transformers` library, built with `PyTorch`, supports all state-of-the-art LLMs, many VLMs, task-specific vision language models, video models, audio models, table models, classical encoders, to a global count of almost 400 models.
5
+
6
  The name of the library itself is mostly majority driven as many models are not even transformers architectures, like Mamba, Zamba, RWKV, and convolution-based models.
7
+
8
  Regardless, each of these is wrought by the research and engineering team that created them, then harmonized into a now famous interface, and callable with a simple `.from_pretrained` command.
9
+
10
  Inference works for all models, training is functional for most. The library is a foundation for many machine learning courses, cookbooks, and overall, several thousands other open-source libraries depend on it. All models are tested as part of a daily CI ensuring their preservation and reproducibility. Most importantly, it is _open-source_ and has been written by the community for a large part.
11
  This isn't really to brag but to set the stakes: what does it take to keep such a ship afloat, made of so many moving, unrelated parts?
12
+
13
  The ML wave has not stopped, there's more and more models being added, at a steadily growing rate. `Transformers` is widely used, and we read the feedback that users post online. Whether it's about a function that had 300+ keyword arguments, duplicated code and helpers, and mentions of `Copied from ... ` everywhere, along with optimisation concerns. Text-only models are relatively tamed, but multimodal models remain to be harmonized.
14
 
15
+ Here we will dissect what is the new design philosophy of transformers, as a continuation from the existing older [philosophy](https://huggingface.co/docs/transformers/en/philosophy) page, and an accompanying [blog post from 2022](https://huggingface.co/blog/transformers-design-philosophy).
16
+
17
+ More recently, and I recommend the read if it's not done yet, a blog post about [recent upgrades to transformers](https://huggingface.co/blog/faster-transformers) was written, explaining in particular what makes the library faster today.
18
+
19
+ Some time ago I dare not say how long, we discussed with transformers maintainers about the state of features in transformers. A lot of recent developments were satisfactory, but if we were only talking about these, self-congratulation would be the only goalpost.
20
+
21
+ Reflecting on this philosophy now, as models pile up, is essential and will drive new developments.
22
+
23
 
24
  ### What you will learn
25
 
 
336
  ```
337
 
338
  This provides an OpenAI-compatible API with features like continuous batching for better GPU utilization.
339
+
340
  ## Community reusability
341
 
342
 
343
  Adding a model to transformers means:
344
  - having it immediately available to the community
345
+ - usable in vLLM, SGLang, and so on without additional code.
346
 
347
+ ## Cooking faster CUDA warmups
348
 
349
  Having a clean _external_ API allows us to work on the true inner workings of transformers. One of the few recent additions was the _CUDA warmup_ via `caching_allocator_warmup` which improved massively the loading footprint by pre-allocating GPU memory to avoid malloc bottlenecks during model loading.
350
 
dist/distill.bundle.js.map CHANGED
The diff for this file is too large to render. See raw diff
 
dist/fragments/attention-visualizer.html CHANGED
@@ -10,16 +10,16 @@
10
  <div style="display: grid; grid-template-columns: 1fr auto; gap: 1rem; align-items: start; margin-bottom: 1rem;">
11
  <div>
12
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem; color: #374151;">Model:</label>
13
- <select id=model-select style="width: 100%; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 6px; background: white;">
14
- <option value=openai-community/gpt2>openai-community/gpt2</option>
15
- <option value=google/gemma-2-2b>google/gemma-2-2b</option>
16
- <option value=microsoft/DialoGPT-small>microsoft/DialoGPT-small</option>
17
  </select>
18
  </div>
19
 
20
  <div>
21
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem; color: #374151;">Action:</label>
22
- <button id=visualize-btn style="padding: 0.5rem 1rem; background: #3b82f6; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: 500;">
23
  🚀 Visualize
24
  </button>
25
  </div>
@@ -27,10 +27,13 @@
27
 
28
  <div style="margin-bottom: 1rem;">
29
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem; color: #374151;">Prompt:</label>
30
- <textarea id=prompt-input style="width: 100%; padding: 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; resize: vertical; font-family: monospace; font-size: 0.9em;" rows=3 placeholder="You are an assistant. Make sure you print me."></textarea>
 
 
 
31
  </div>
32
 
33
- <div id=attention-output style="min-height: 200px; background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; padding: 1rem;">
34
  <div style="text-align: center; color: #6c757d; font-style: italic;">
35
  Click "Visualize" to generate attention visualization
36
  </div>
@@ -43,4 +46,57 @@
43
  </div>
44
  </div>
45
 
46
- <script>document.addEventListener("DOMContentLoaded",function(){let e=document.getElementById("model-select"),t=document.getElementById("prompt-input"),n=document.getElementById("visualize-btn"),i=document.getElementById("attention-output");t.value="You are an assistant. Make sure you print me.",n.addEventListener("click",function(){let o=e.value,r=t.value.trim();if(!r){i.innerHTML='<div style="color: #e53e3e;">Please enter a prompt</div>';return}n.disabled=!0,n.textContent="Processing...",i.innerHTML='<div style="text-align: center; color: #6c757d;"><em>Generating attention visualization...</em></div>',setTimeout(()=>{let e=r.split(" ").slice(0,8),t='<div style="margin-bottom: 1rem;"><strong>Model:</strong> '+o+"</div>";t+='<div style="margin-bottom: 1rem;"><strong>Tokens:</strong> '+e.join(" • ")+'</div><div><strong>Attention Matrix (Layer 0, Head 0):</strong></div><table style="margin-top: 0.5rem; border-collapse: collapse; font-family: monospace; font-size: 0.8em;">';for(let n=0;n<e.length;n++){t+="<tr>";for(let n=0;n<e.length;n++){let e=Math.random(),n=`rgba(59, 130, 246, ${e})`;t+=`<td style="border: 1px solid #ddd; padding: 4px; background: ${n}; text-align: center; min-width: 40px;">${e.toFixed(2)}</td>`}t+="</tr>"}i.innerHTML=t+='</table><div style="margin-top: 1rem; font-size: 0.9em; color: #6c757d;"><em>Darker blue = higher attention weight</em></div>',n.disabled=!1,n.textContent="\uD83D\uDE80 Visualize"},2e3)})})</script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  <div style="display: grid; grid-template-columns: 1fr auto; gap: 1rem; align-items: start; margin-bottom: 1rem;">
11
  <div>
12
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem; color: #374151;">Model:</label>
13
+ <select id="model-select" style="width: 100%; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 6px; background: white;">
14
+ <option value="openai-community/gpt2">openai-community/gpt2</option>
15
+ <option value="google/gemma-2-2b">google/gemma-2-2b</option>
16
+ <option value="microsoft/DialoGPT-small">microsoft/DialoGPT-small</option>
17
  </select>
18
  </div>
19
 
20
  <div>
21
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem; color: #374151;">Action:</label>
22
+ <button id="visualize-btn" style="padding: 0.5rem 1rem; background: #3b82f6; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: 500;">
23
  🚀 Visualize
24
  </button>
25
  </div>
 
27
 
28
  <div style="margin-bottom: 1rem;">
29
  <label style="display: block; font-weight: 600; margin-bottom: 0.5rem; color: #374151;">Prompt:</label>
30
+ <textarea id="prompt-input"
31
+ style="width: 100%; padding: 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; resize: vertical; font-family: monospace; font-size: 0.9em;"
32
+ rows="3"
33
+ placeholder="You are an assistant. Make sure you print me."></textarea>
34
  </div>
35
 
36
+ <div id="attention-output" style="min-height: 200px; background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; padding: 1rem;">
37
  <div style="text-align: center; color: #6c757d; font-style: italic;">
38
  Click "Visualize" to generate attention visualization
39
  </div>
 
46
  </div>
47
  </div>
48
 
49
+ <script>
50
+ document.addEventListener('DOMContentLoaded', function() {
51
+ const modelSelect = document.getElementById('model-select');
52
+ const promptInput = document.getElementById('prompt-input');
53
+ const visualizeBtn = document.getElementById('visualize-btn');
54
+ const output = document.getElementById('attention-output');
55
+
56
+ // Set default prompt
57
+ promptInput.value = "You are an assistant. Make sure you print me.";
58
+
59
+ visualizeBtn.addEventListener('click', function() {
60
+ const model = modelSelect.value;
61
+ const prompt = promptInput.value.trim();
62
+
63
+ if (!prompt) {
64
+ output.innerHTML = '<div style="color: #e53e3e;">Please enter a prompt</div>';
65
+ return;
66
+ }
67
+
68
+ // Show loading state
69
+ visualizeBtn.disabled = true;
70
+ visualizeBtn.textContent = 'Processing...';
71
+ output.innerHTML = '<div style="text-align: center; color: #6c757d;"><em>Generating attention visualization...</em></div>';
72
+
73
+ // Simulate processing time
74
+ setTimeout(() => {
75
+ // Generate mock attention visualization
76
+ const tokens = prompt.split(' ').slice(0, 8); // Limit tokens for demo
77
+ let html = '<div style="margin-bottom: 1rem;"><strong>Model:</strong> ' + model + '</div>';
78
+ html += '<div style="margin-bottom: 1rem;"><strong>Tokens:</strong> ' + tokens.join(' • ') + '</div>';
79
+ html += '<div><strong>Attention Matrix (Layer 0, Head 0):</strong></div>';
80
+ html += '<table style="margin-top: 0.5rem; border-collapse: collapse; font-family: monospace; font-size: 0.8em;">';
81
+
82
+ // Generate attention matrix visualization
83
+ for (let i = 0; i < tokens.length; i++) {
84
+ html += '<tr>';
85
+ for (let j = 0; j < tokens.length; j++) {
86
+ const attention = Math.random();
87
+ const opacity = attention;
88
+ const color = `rgba(59, 130, 246, ${opacity})`;
89
+ html += `<td style="border: 1px solid #ddd; padding: 4px; background: ${color}; text-align: center; min-width: 40px;">${attention.toFixed(2)}</td>`;
90
+ }
91
+ html += '</tr>';
92
+ }
93
+ html += '</table>';
94
+ html += '<div style="margin-top: 1rem; font-size: 0.9em; color: #6c757d;"><em>Darker blue = higher attention weight</em></div>';
95
+
96
+ output.innerHTML = html;
97
+ visualizeBtn.disabled = false;
98
+ visualizeBtn.textContent = '🚀 Visualize';
99
+ }, 2000);
100
+ });
101
+ });
102
+ </script>
dist/fragments/d3-graph.html CHANGED
@@ -1,11 +1,11 @@
1
- <div class=interactive-demo>
2
- <div class=demo-header>
3
  <h3>🔗 Model Dependency Graph</h3>
4
  </div>
5
- <div class=demo-content>
6
- <iframe src=static/d3_dependency_graph.html width=100% height=600px frameborder=0 style="border-radius: 8px; background: white;"></iframe>
7
  </div>
8
- <div class=demo-footer>
9
  Interactive dependency graph showing real relationships between Transformers models. 🟡 Base models (HuggingFace logo), 🔵 Derived modular models. Click and drag to explore!
10
  </div>
11
  </div>
 
1
+ <div class="interactive-demo">
2
+ <div class="demo-header">
3
  <h3>🔗 Model Dependency Graph</h3>
4
  </div>
5
+ <div class="demo-content">
6
+ <iframe src="static/d3_dependency_graph.html" width="100%" height="600px" frameborder="0" style="border-radius: 8px; background: white;"></iframe>
7
  </div>
8
+ <div class="demo-footer">
9
  Interactive dependency graph showing real relationships between Transformers models. 🟡 Base models (HuggingFace logo), 🔵 Derived modular models. Click and drag to explore!
10
  </div>
11
  </div>
dist/fragments/glm-compare.html CHANGED
@@ -1,9 +1,9 @@
1
- <div class=code-compare style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1.5rem 0;">
2
- <div class=code-column style="border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden;">
3
- <div class=code-header style="background: #f8f9fa; padding: 0.75rem 1rem; font-weight: 600; color: #495057; border-bottom: 1px solid #e2e8f0;">
4
  modular_glm.py
5
  </div>
6
- <pre style="margin: 0; padding: 1rem; background: #ffffff; overflow-x: auto; font-size: 0.9em;"><code class=language-python>class GlmMLP(Phi3MLP):
7
  pass
8
 
9
  class GlmAttention(LlamaAttention):
@@ -19,11 +19,11 @@ class GlmForCausalLM(LlamaForCausalLM):
19
  pass</code></pre>
20
  </div>
21
 
22
- <div class=code-column style="border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden;">
23
- <div class=code-header style="background: #f8f9fa; padding: 0.75rem 1rem; font-weight: 600; color: #495057; border-bottom: 1px solid #e2e8f0;">
24
  modeling_glm.py (auto-expanded)
25
  </div>
26
- <pre style="margin: 0; padding: 1rem; background: #ffffff; overflow-x: auto; font-size: 0.9em; max-height: 400px;"><code class=language-python>class GlmMLP(nn.Module):
27
  def __init__(self, config):
28
  super().__init__()
29
  self.config = config
 
1
+ <div class="code-compare" style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1.5rem 0;">
2
+ <div class="code-column" style="border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden;">
3
+ <div class="code-header" style="background: #f8f9fa; padding: 0.75rem 1rem; font-weight: 600; color: #495057; border-bottom: 1px solid #e2e8f0;">
4
  modular_glm.py
5
  </div>
6
+ <pre style="margin: 0; padding: 1rem; background: #ffffff; overflow-x: auto; font-size: 0.9em;"><code class="language-python">class GlmMLP(Phi3MLP):
7
  pass
8
 
9
  class GlmAttention(LlamaAttention):
 
19
  pass</code></pre>
20
  </div>
21
 
22
+ <div class="code-column" style="border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden;">
23
+ <div class="code-header" style="background: #f8f9fa; padding: 0.75rem 1rem; font-weight: 600; color: #495057; border-bottom: 1px solid #e2e8f0;">
24
  modeling_glm.py (auto-expanded)
25
  </div>
26
+ <pre style="margin: 0; padding: 1rem; background: #ffffff; overflow-x: auto; font-size: 0.9em; max-height: 400px;"><code class="language-python">class GlmMLP(nn.Module):
27
  def __init__(self, config):
28
  super().__init__()
29
  self.config = config
dist/fragments/modular-growth.html ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <section id="modular-growth-space" class="l-body">
2
+ <h2>Modular growth (interactive)</h2>
3
+ <p class="l-page">Explore live graphs and metrics from the accompanying Space.</p>
4
+ <div style="position:relative;padding-top:62.5%;border:1px solid rgba(255,255,255,.08);border-radius:12px;overflow:hidden">
5
+ <iframe
6
+ src="https://molbap-transformers-modular-refactor.hf.space"
7
+ title="Transformers Modular Refactor Space"
8
+ style="position:absolute;inset:0;border:0;width:100%;height:100%;"
9
+ loading="lazy"
10
+ referrerpolicy="no-referrer-when-downgrade"
11
+ allow="clipboard-read; clipboard-write; fullscreen; autoplay"
12
+ ></iframe>
13
+ </div>
14
+ <p class="l-page" style="margin-top:.6rem">
15
+ Open in a new tab: <a href="https://huggingface.co/spaces/Molbap/transformers-modular-refactor" target="_blank" rel="noopener">Space README & details</a>.
16
+ </p>
17
+ </section>
18
+
dist/fragments/terminal.html CHANGED
@@ -2,21 +2,42 @@
2
  <h4 style="margin-top: 0; color: #495057;">Interactive Terminal</h4>
3
  <div style="background: #2d3748; color: #e2e8f0; padding: 1rem; border-radius: 6px; font-family: 'Consolas', 'Monaco', monospace;">
4
  <div style="margin-bottom: 1rem;">
5
- <input type=text id=terminal-input placeholder="python -c 'import torch; print(torch.__version__)'" style="width: calc(100% - 80px); padding: 0.5rem; background: #1a202c; border: 1px solid #4a5568; color: #e2e8f0; border-radius: 4px;">
6
- <button id=terminal-run style="width: 70px; padding: 0.5rem; margin-left: 8px; background: #3182ce; color: white; border: none; border-radius: 4px; cursor: pointer;">Run</button>
 
 
 
 
7
  </div>
8
- <pre id=terminal-output style="background: #1a202c; padding: 1rem; border-radius: 4px; min-height: 100px; margin: 0; overflow-x: auto;">$ Ready to run commands...</pre>
9
  </div>
10
  <p style="font-size: 0.9em; color: #6c757d; margin-top: 0.5rem;">
11
  <em>Note: This is a simulated terminal. In the original Gradio app, this would execute real Python commands with proper security restrictions.</em>
12
  </p>
13
  </div>
14
 
15
- <script>document.addEventListener("DOMContentLoaded",function(){let e=document.getElementById("terminal-input"),t=document.getElementById("terminal-run"),n=document.getElementById("terminal-output");function o(){let t=e.value.trim();t&&(n.textContent=`$ ${t}
16
- Simulated output for: ${t}
17
-
18
- This would execute the command in the original app.
19
- Example outputs:
20
- - torch version: 2.0.1+cu117
21
- - import checks: Success
22
- - memory info: Available`)}t.addEventListener("click",o),e.addEventListener("keypress",function(e){"Enter"===e.key&&o()})})</script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  <h4 style="margin-top: 0; color: #495057;">Interactive Terminal</h4>
3
  <div style="background: #2d3748; color: #e2e8f0; padding: 1rem; border-radius: 6px; font-family: 'Consolas', 'Monaco', monospace;">
4
  <div style="margin-bottom: 1rem;">
5
+ <input type="text"
6
+ id="terminal-input"
7
+ placeholder="python -c 'import torch; print(torch.__version__)'"
8
+ style="width: calc(100% - 80px); padding: 0.5rem; background: #1a202c; border: 1px solid #4a5568; color: #e2e8f0; border-radius: 4px;">
9
+ <button id="terminal-run"
10
+ style="width: 70px; padding: 0.5rem; margin-left: 8px; background: #3182ce; color: white; border: none; border-radius: 4px; cursor: pointer;">Run</button>
11
  </div>
12
+ <pre id="terminal-output" style="background: #1a202c; padding: 1rem; border-radius: 4px; min-height: 100px; margin: 0; overflow-x: auto;">$ Ready to run commands...</pre>
13
  </div>
14
  <p style="font-size: 0.9em; color: #6c757d; margin-top: 0.5rem;">
15
  <em>Note: This is a simulated terminal. In the original Gradio app, this would execute real Python commands with proper security restrictions.</em>
16
  </p>
17
  </div>
18
 
19
+ <script>
20
+ document.addEventListener('DOMContentLoaded', function() {
21
+ const input = document.getElementById('terminal-input');
22
+ const button = document.getElementById('terminal-run');
23
+ const output = document.getElementById('terminal-output');
24
+
25
+ function runCommand() {
26
+ const command = input.value.trim();
27
+ if (!command) return;
28
+
29
+ // Simulate command execution
30
+ output.textContent = `$ ${command}\nSimulated output for: ${command}\n\n` +
31
+ `This would execute the command in the original app.\n` +
32
+ `Example outputs:\n` +
33
+ `- torch version: 2.0.1+cu117\n` +
34
+ `- import checks: Success\n` +
35
+ `- memory info: Available`;
36
+ }
37
+
38
+ button.addEventListener('click', runCommand);
39
+ input.addEventListener('keypress', function(e) {
40
+ if (e.key === 'Enter') runCommand();
41
+ });
42
+ });
43
+ </script>
dist/fragments/tp-plan.html ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <pre><code class="language-python"># In the model's config (example: ERNIE 4.5-style decoder blocks)
2
+ base_model_tp_plan = {
3
+ "layers.*.self_attn.q_proj": "colwise",
4
+ "layers.*.self_attn.k_proj": "colwise",
5
+ "layers.*.self_attn.v_proj": "colwise",
6
+ "layers.*.self_attn.o_proj": "rowwise",
7
+ "layers.*.mlp.gate_proj": "colwise",
8
+ "layers.*.mlp.up_proj": "colwise",
9
+ "layers.*.mlp.down_proj": "rowwise",
10
+ }
11
+
12
+ # Runtime
13
+ import torch
14
+ from transformers import AutoModelForCausalLM, AutoTokenizer
15
+
16
+ model_id = "your/model-or-local-checkpoint"
17
+ model = AutoModelForCausalLM.from_pretrained(
18
+ model_id,
19
+ dtype=torch.bfloat16,
20
+ tp_plan=base_model_tp_plan, # <-- plan defined above
21
+ )
22
+ tok = AutoTokenizer.from_pretrained(model_id)
23
+ inputs = tok("Hello", return_tensors="pt").to(model.device)
24
+ out = model(**inputs)</code></pre>
dist/fragments/warmup_demo.html ADDED
@@ -0,0 +1,398 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <style>
2
+ .warmup-demo body {
3
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
4
+ margin: 0;
5
+ padding: 20px;
6
+ background-color: #f5f5f5;
7
+ }
8
+
9
+ .warmup-demo .container {
10
+ max-width: 1200px;
11
+ margin: 0 auto;
12
+ background: white;
13
+ border-radius: 12px;
14
+ padding: 30px;
15
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
16
+ }
17
+
18
+ .warmup-demo h1 {
19
+ text-align: center;
20
+ color: #333;
21
+ margin-bottom: 10px;
22
+ }
23
+
24
+ .warmup-demo .subtitle {
25
+ text-align: center;
26
+ color: #666;
27
+ margin-bottom: 30px;
28
+ font-size: 16px;
29
+ }
30
+
31
+ .warmup-demo .demo-container {
32
+ display: flex;
33
+ gap: 40px;
34
+ margin-bottom: 30px;
35
+ }
36
+
37
+ .warmup-demo .side {
38
+ flex: 1;
39
+ border: 2px solid #ddd;
40
+ border-radius: 8px;
41
+ padding: 20px;
42
+ background: #fafafa;
43
+ }
44
+
45
+ .warmup-demo .side h2 {
46
+ text-align: center;
47
+ margin-top: 0;
48
+ color: #333;
49
+ }
50
+
51
+ .warmup-demo .no-warmup h2 {
52
+ color: #d63384;
53
+ }
54
+
55
+ .warmup-demo .with-warmup h2 {
56
+ color: #198754;
57
+ }
58
+
59
+ .warmup-demo .memory-area {
60
+ height: 400px;
61
+ border: 2px dashed #ccc;
62
+ border-radius: 6px;
63
+ padding: 10px;
64
+ margin: 20px 0;
65
+ background: #fff;
66
+ position: relative;
67
+ overflow: hidden;
68
+ }
69
+
70
+ .warmup-demo .layer-box {
71
+ width: 80px;
72
+ height: 30px;
73
+ border: 2px solid #666;
74
+ border-radius: 4px;
75
+ margin: 3px;
76
+ display: inline-block;
77
+ position: relative;
78
+ background: #fff;
79
+ transition: all 0.3s ease;
80
+ }
81
+
82
+ .warmup-demo .layer-box.allocating {
83
+ background: #e9ecef;
84
+ border-color: #adb5bd;
85
+ }
86
+
87
+ .warmup-demo .layer-box.allocating::after {
88
+ content: "malloc";
89
+ position: absolute;
90
+ top: 50%;
91
+ left: 50%;
92
+ transform: translate(-50%, -50%);
93
+ font-size: 10px;
94
+ color: #666;
95
+ font-weight: bold;
96
+ }
97
+
98
+ .warmup-demo .layer-box.loaded {
99
+ background: #d1e7dd;
100
+ border-color: #198754;
101
+ }
102
+
103
+ .warmup-demo .layer-box.loaded::after {
104
+ content: "data";
105
+ position: absolute;
106
+ top: 50%;
107
+ left: 50%;
108
+ transform: translate(-50%, -50%);
109
+ font-size: 10px;
110
+ color: #198754;
111
+ font-weight: bold;
112
+ }
113
+
114
+ .warmup-demo .warmup-container {
115
+ width: 100%;
116
+ height: 60px;
117
+ border: 3px solid #666;
118
+ border-radius: 6px;
119
+ margin-bottom: 20px;
120
+ background: #fff;
121
+ position: relative;
122
+ overflow: hidden;
123
+ }
124
+
125
+ .warmup-demo .warmup-container.allocated {
126
+ border-color: #0d6efd;
127
+ background: #e7f1ff;
128
+ }
129
+
130
+ .warmup-demo .warmup-container::before {
131
+ content: "Pre-allocated Memory Pool";
132
+ position: absolute;
133
+ top: 50%;
134
+ left: 50%;
135
+ transform: translate(-50%, -50%);
136
+ font-size: 14px;
137
+ color: #666;
138
+ font-weight: bold;
139
+ z-index: 1;
140
+ }
141
+
142
+ .warmup-demo .warmup-container.allocated::before {
143
+ color: #0d6efd;
144
+ }
145
+
146
+ .warmup-demo .warmup-fill {
147
+ height: 100%;
148
+ background: linear-gradient(90deg, #198754, #20c997);
149
+ width: 0%;
150
+ transition: width 0.5s ease;
151
+ border-radius: 3px;
152
+ position: relative;
153
+ z-index: 2;
154
+ }
155
+
156
+ .warmup-demo .warmup-fill::after {
157
+ content: "Layer Data Loading";
158
+ position: absolute;
159
+ top: 50%;
160
+ left: 50%;
161
+ transform: translate(-50%, -50%);
162
+ font-size: 12px;
163
+ color: white;
164
+ font-weight: bold;
165
+ white-space: nowrap;
166
+ }
167
+
168
+ .warmup-demo .timing {
169
+ text-align: center;
170
+ font-size: 24px;
171
+ font-weight: bold;
172
+ margin: 15px 0;
173
+ min-height: 30px;
174
+ }
175
+
176
+ .warmup-demo .no-warmup .timing {
177
+ color: #d63384;
178
+ }
179
+
180
+ .warmup-demo .with-warmup .timing {
181
+ color: #198754;
182
+ }
183
+
184
+ .warmup-demo .controls {
185
+ text-align: center;
186
+ margin: 30px 0;
187
+ }
188
+
189
+ .warmup-demo .btn {
190
+ background: #0d6efd;
191
+ color: white;
192
+ border: none;
193
+ padding: 12px 24px;
194
+ border-radius: 6px;
195
+ font-size: 16px;
196
+ cursor: pointer;
197
+ margin: 0 10px;
198
+ transition: background 0.3s ease;
199
+ }
200
+
201
+ .warmup-demo .btn:hover {
202
+ background: #0b5ed7;
203
+ }
204
+
205
+ .warmup-demo .btn:disabled {
206
+ background: #6c757d;
207
+ cursor: not-allowed;
208
+ }
209
+
210
+ .warmup-demo .description {
211
+ background: #f8f9fa;
212
+ padding: 15px;
213
+ border-radius: 6px;
214
+ margin-top: 15px;
215
+ font-size: 14px;
216
+ line-height: 1.5;
217
+ }
218
+
219
+ .warmup-demo .phase-indicator {
220
+ font-size: 14px;
221
+ color: #666;
222
+ text-align: center;
223
+ margin-top: 10px;
224
+ min-height: 20px;
225
+ }
226
+
227
+ .warmup-demo .layer-counter {
228
+ text-align: center;
229
+ font-size: 16px;
230
+ color: #495057;
231
+ margin: 10px 0;
232
+ }
233
+ </style>
234
+
235
+ <div class="warmup-demo">
236
+ <div class="container">
237
+ <p class="subtitle">Mem allocation patterns during model loading</p>
238
+
239
+ <div class="controls">
240
+ <button class="btn" id="startBtn" onclick="startDemo()">Start Animation</button>
241
+ <button class="btn" id="resetBtn" onclick="resetDemo()">Reset</button>
242
+ </div>
243
+
244
+ <div class="demo-container">
245
+ <div class="side no-warmup">
246
+ <h2 data-no-toc>❌ Without Warmup</h2>
247
+ <div class="timing" id="noWarmupTime">0.00s</div>
248
+ <div class="layer-counter" id="noWarmupCounter">Layers loaded: 0/10</div>
249
+ <div class="phase-indicator" id="noWarmupPhase"></div>
250
+ <div class="memory-area" id="noWarmupArea"></div>
251
+ <div class="description">
252
+ <strong>Individual Allocations:</strong><br>
253
+ Each model layer triggers a separate cudaMalloc() call, creating memory fragmentation and allocation overhead.
254
+ <br><br>
255
+ 📦 <strong>Grey "malloc"</strong> = Memory allocation overhead<br>
256
+ ✅ <strong>Green "data"</strong> = Actual layer data loading
257
+ </div>
258
+ </div>
259
+
260
+ <div class="side with-warmup">
261
+ <h2 data-no-toc>✅ With Warmup</h2>
262
+ <div class="timing" id="warmupTime">0.00s</div>
263
+ <div class="layer-counter" id="warmupCounter">Layers loaded: 0/10</div>
264
+ <div class="phase-indicator" id="warmupPhase"></div>
265
+ <div class="memory-area" id="warmupArea">
266
+ <div class="warmup-container" id="warmupContainer">
267
+ <div class="warmup-fill" id="warmupFill"></div>
268
+ </div>
269
+ <div id="warmupLayers"></div>
270
+ </div>
271
+ <div class="description">
272
+ <strong>Pre-allocated Pool:</strong><br>
273
+ The warmup function calculates total memory needed and makes ONE large allocation. Subsequent layers load directly into this pool, eliminating malloc overhead.
274
+ <br><br>
275
+ 🔵 <strong>Blue container</strong> = Single large malloc (warmup)<br>
276
+ 🟢 <strong>Green progress bar</strong> = Layer data loading (no malloc needed)
277
+ </div>
278
+ </div>
279
+ </div>
280
+ </div>
281
+ </div>
282
+
283
+ <script>
284
+ let animationSpeed = 1 / 2.4;
285
+ let isRunning = false;
286
+ const totalLayers = 10;
287
+
288
+ function startDemo() {
289
+ if (isRunning) return;
290
+ isRunning = true;
291
+
292
+ document.getElementById('startBtn').disabled = true;
293
+ document.getElementById('resetBtn').disabled = true;
294
+
295
+ Promise.all([
296
+ animateNoWarmup(),
297
+ animateWithWarmup()
298
+ ]).then(() => {
299
+ isRunning = false;
300
+ document.getElementById('startBtn').disabled = false;
301
+ document.getElementById('resetBtn').disabled = false;
302
+ });
303
+ }
304
+
305
+ function resetDemo() {
306
+ if (isRunning) return;
307
+
308
+ document.getElementById('noWarmupArea').innerHTML = '';
309
+ document.getElementById('warmupLayers').innerHTML = '';
310
+ document.getElementById('warmupFill').style.width = '0%';
311
+ document.getElementById('warmupContainer').classList.remove('allocated');
312
+
313
+ document.getElementById('noWarmupTime').textContent = '0.00s';
314
+ document.getElementById('warmupTime').textContent = '0.00s';
315
+
316
+ document.getElementById('noWarmupCounter').textContent = 'Layers loaded: 0/10';
317
+ document.getElementById('warmupCounter').textContent = 'Layers loaded: 0/10';
318
+
319
+ document.getElementById('noWarmupPhase').textContent = '';
320
+ document.getElementById('warmupPhase').textContent = '';
321
+ }
322
+
323
+ async function animateNoWarmup() {
324
+ const container = document.getElementById('noWarmupArea');
325
+ const timeEl = document.getElementById('noWarmupTime');
326
+ const counterEl = document.getElementById('noWarmupCounter');
327
+ const phaseEl = document.getElementById('noWarmupPhase');
328
+
329
+ let currentTime = 0;
330
+ const baseDelay = 200 / animationSpeed;
331
+
332
+ phaseEl.textContent = 'Loading model layers...';
333
+
334
+ for (let i = 0; i < totalLayers; i++) {
335
+ const layerBox = document.createElement('div');
336
+ layerBox.className = 'layer-box';
337
+ container.appendChild(layerBox);
338
+
339
+ await sleep(baseDelay * 0.3);
340
+ layerBox.classList.add('allocating');
341
+ currentTime += 0.08;
342
+ timeEl.textContent = currentTime.toFixed(2) + 's';
343
+
344
+ await sleep(baseDelay * 0.7);
345
+ layerBox.classList.remove('allocating');
346
+ layerBox.classList.add('loaded');
347
+ currentTime += 0.12;
348
+ timeEl.textContent = currentTime.toFixed(2) + 's';
349
+
350
+ counterEl.textContent = `Layers loaded: ${i + 1}/${totalLayers}`;
351
+ }
352
+
353
+ phaseEl.textContent = 'Complete!';
354
+ }
355
+
356
+ async function animateWithWarmup() {
357
+ const container = document.getElementById('warmupLayers');
358
+ const timeEl = document.getElementById('warmupTime');
359
+ const counterEl = document.getElementById('warmupCounter');
360
+ const phaseEl = document.getElementById('warmupPhase');
361
+ const warmupContainer = document.getElementById('warmupContainer');
362
+ const warmupFill = document.getElementById('warmupFill');
363
+
364
+ let currentTime = 0;
365
+ const baseDelay = 200 / animationSpeed;
366
+
367
+ phaseEl.textContent = 'Warming up allocator...';
368
+ await sleep(baseDelay * 2);
369
+ warmupContainer.classList.add('allocated');
370
+ currentTime += 0.3;
371
+ timeEl.textContent = currentTime.toFixed(2) + 's';
372
+
373
+ phaseEl.textContent = 'Loading model layers...';
374
+
375
+ for (let i = 0; i < totalLayers; i++) {
376
+ const layerBox = document.createElement('div');
377
+ layerBox.className = 'layer-box loaded';
378
+ layerBox.style.width = '40px';
379
+ layerBox.style.height = '20px';
380
+ container.appendChild(layerBox);
381
+
382
+ const progress = ((i + 1) / totalLayers) * 100;
383
+ warmupFill.style.width = progress + '%';
384
+
385
+ await sleep(baseDelay * 0.5);
386
+ currentTime += 0.08;
387
+ timeEl.textContent = currentTime.toFixed(2) + 's';
388
+
389
+ counterEl.textContent = `Layers loaded: ${i + 1}/${totalLayers}`;
390
+ }
391
+
392
+ phaseEl.textContent = 'Complete!';
393
+ }
394
+
395
+ function sleep(ms) {
396
+ return new Promise(resolve => setTimeout(resolve, ms));
397
+ }
398
+ </script>
dist/index.html CHANGED
@@ -8,21 +8,21 @@
8
  <script src="https://d3js.org/d3.v7.min.js"></script>
9
  <meta name="viewport" content="width=device-width, initial-scale=1">
10
  <meta charset="utf8">
11
- <title>Scaling insanity: maintaining hundreds of model definitions</title>
12
  <link rel="stylesheet" href="style.css">
13
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css">
14
  </head>
15
  <body>
16
  <d-front-matter>
17
  <script id='distill-front-matter' type="text/json">{
18
- "title": "Scaling insanity: maintaining hundreds of model definitions",
19
  "description": "A peek into software engineering for the transformers library",
20
  "published": "Aug 21, 2025",
21
  "authors": [{"author": "Pablo Montalvo", "authorURL": "https://huggingface.co/Molbap"}]
22
  }</script>
23
  </d-front-matter>
24
  <d-title>
25
- <h1>Scaling insanity: maintaining hundreds of model definitions</h1>
26
  <p>A peek into software engineering for the transformers library</p>
27
  </d-title>
28
  <d-byline></d-byline>
@@ -48,13 +48,16 @@
48
  </nav>
49
  </d-contents>
50
  <h2>Introduction</h2>
51
- <p>The <code>transformers</code> library, built with <code>PyTorch</code>, supports all state-of-the-art LLMs, many VLMs, task-specific vision language models, video models, audio models, table models, classical encoders, to a global count of almost 400 models.
52
- The name of the library itself is mostly majority driven as many models are not even transformers architectures, like Mamba, Zamba, RWKV, and convolution-based models.
53
- Regardless, each of these is wrought by the research and engineering team that created them, then harmonized into a now famous interface, and callable with a simple <code>.from_pretrained</code> command.
54
- Inference works for all models, training is functional for most. The library is a foundation for many machine learning courses, cookbooks, and overall, several thousands other open-source libraries depend on it. All models are tested as part of a daily CI ensuring their preservation and reproducibility. Most importantly, it is <em>open-source</em> and has been written by the community for a large part.
55
- This isn’t really to brag but to set the stakes: what does it take to keep such a ship afloat, made of so many moving, unrelated parts?
56
- The ML wave has not stopped, there’s more and more models being added, at a steadily growing rate. <code>Transformers</code> is widely used, and we read the feedback that users post online. Whether its about a function that had 300+ keyword arguments, duplicated code and helpers, and mentions of <code>Copied from ... </code> everywhere, along with optimisation concerns. Text-only models are relatively tamed, but multimodal models remain to be harmonized.</p>
57
- <p>Here we will dissect what is the new design philosophy of transformers, as a continuation from the existing older <a href="https://huggingface.co/docs/transformers/en/philosophy">philosophy</a> page, and an accompanying <a href="https://huggingface.co/blog/transformers-design-philosophy">blog post from 2022</a> . Some time ago I dare not say how long, we discussed with transformers maintainers about the state of things. A lot of recent developments were satisfactory, but if we were only talking about these, self-congratulation would be the only goalpost. Reflecting on this philosophy now, as models pile up, is essential and will drive new developments.</p>
 
 
 
58
  <h3>What you will learn</h3>
59
  <p>Every reader, whether an OSS maintainer, power user, or casual fine-tuner, will walk away knowing how to reason about the <code>transformers</code> code base, how to use it better, how to meaningfully contribute to it.
60
  This will also showcase new features you might have missed so you’ll be up-to-date.</p>
@@ -113,7 +116,7 @@ This will also showcase new features you might have missed so you’ll be up-to-
113
  </li>
114
  <li class="tenet">
115
  <a id="modular-toolbox"></a>
116
- <strong>Modular Toolbox (Not Framework)</strong>
117
  <p>We ARE a toolbox. What we are not is a framework: you should not be FORCED to rewrite every modeling, but it is <em>better</em> for your model to be able to inherit from PreTrainedModel and have enabled TensorParallel, from_pretrained, sharding, push_to_hub, loss, as well as PEFT/TRL/SGLang/vLLM.</p>
118
  <em>This is the largest change. Provide tools and utilities, but don't force users into a rigid framework.</em>
119
  </li>
@@ -297,6 +300,35 @@ if self.config._attn_implementation != &quot;eager&quot;:
297
  <p>For better <em>information</em>, we plan to use <code>python</code> features such as <code>Annotated</code> for example, to inform users of what we expect typically in an argument. That way, higher-level information could be included directly in the type annotations.</p>
298
  <h2><a id="simpler-tensor-parallelism"></a> Simpler Tensor Parallelism</h2>
299
  <p>We want to touch minimally to the modeling code, and only modify it when <em>architectural changes</em> are involved. For instance, for tensor parallelism, we instead now specify a simple <code>tp_plan</code>.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  <h2><a id="layers-attentions-caches"></a> Layers, attentions and caches</h2>
301
  <p>With th</p>
302
  <h2><a id="community-kernels"></a>Community Kernels</h2>
@@ -331,7 +363,6 @@ Radically different architectures such as mamba have spawned their own dependenc
331
  </div>
332
 
333
  </p>
334
- <p><img src="static/graph_modular_related_models.png" alt="Graph showing modular related models"></p>
335
  <p>But there is no similar miracle for VLMs across the board.
336
  As you can see, there is a small DETR island, a little llava pocket, and so on, but it’s not comparable to the centrality observed.</p>
337
  <p>One problem is, this is only for <code>modular</code> models. Several models do NOT have a modular file. In other words, we have a big “hidden space here.”</p>
@@ -415,7 +446,7 @@ Example outputs:
415
  <h2>Modularity candidates</h2>
416
  <p>So the question abounds naturally: How can we modularize more?
417
  I took again a similarity measure and looked at the existing graphs. The tool is available on this <a href="https://huggingface.co/spaces/Molbap/transformers-modular-refactor">ZeroGPU-enabled Space</a>. It scans the whole transformers repository, and outputs a graph of candidates across models, using either a Jaccard similarity index (simple) or a SentenceTransformers embedding model. It is understandable that <a href="#encoders-ftw">encoder models still have a lion’s share of the game.</a> See also <a href="https://huggingface.co/blog/train-sparse-encoder">Tom Aarsen and Arhur Bresnu’s great blog post on the topic of sparse embeddings.</a>.</p>
418
- <p><img src="static/modular_candidates.png" alt="Modular candidates analysis"></p>
419
  <h2><a id="encoders-ftw"></a> The neverending stories of encoder models.</h2>
420
  <p>Models popularity speaks for itself! This is because the usage of encoders lies in embeddings obviously. So we have to keep the encoders part viable, usable, fine-tune-able.</p>
421
  <p><img src="static/popular_models_barplot.png" alt="Popular models bar plot"></p>
@@ -500,32 +531,61 @@ curl -X POST http://localhost:8000/v1/chat/completions \
500
  <li>having it immediately available to the community</li>
501
  <li>usable in vLLM, SGLang, and so on without additional code.</li>
502
  </ul>
503
- <p>## Inner cooking: CUDA Warmup</p>
504
  <p>Having a clean <em>external</em> API allows us to work on the true inner workings of transformers. One of the few recent additions was the <em>CUDA warmup</em> via <code>caching_allocator_warmup</code> which improved massively the loading footprint by pre-allocating GPU memory to avoid malloc bottlenecks during model loading.</p>
505
- <p><div style="border: 1px solid #e2e8f0; border-radius: 8px; background: white; margin: 1.5rem 0;">
506
- <div style="padding: 1rem; border-bottom: 1px solid #e2e8f0; background: #f8f9fa;">
507
- <h4 style="margin: 0 0 0.5rem 0; color: #495057;">🚀 CUDA Warmup Efficiency Benchmark</h4>
508
- <p style="margin: 0; font-size: 0.9em; color: #6c757d;">
509
- Real CUDA warmup benchmarking with actual Transformers models. Measure the performance impact of the caching_allocator_warmup function.
510
- </p>
511
- </div>
512
-
513
- <div style="padding: 1rem;">
514
- <iframe src=https://molbap-cuda-warmup-transformers.hf.space width=100% height=800px frameborder=0 style="border-radius: 8px; background: white;"></iframe>
515
- </div>
516
-
517
- <div style="padding: 1rem; border-top: 1px solid #e2e8f0; background: #f8f9fa; font-size: 0.9em; color: #6c757d;">
518
- Real CUDA warmup benchmarking with actual Transformers models. Measure the performance impact of the <code>caching_allocator_warmup</code> function at <code>transformers/src/transformers/modeling_utils.py:6186</code>. This interactive tool loads models twice - once with warmup disabled and once with warmup enabled - to demonstrate the significant loading time improvements.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
519
  </div>
520
- </div></p>
521
- <h3>Linkedin post (to remove)</h3>
522
- <p>Linkedin post for videos:</p>
523
- <p>In transformers, how do we deal with cross-model dependencies, while supporting ~400 models? Maybe you’ve seen the same 200-lines functions in too many <em>modeling_file.py</em>? Duplication isn’t inevitable.</p>
524
- <p>The “one‑model/one‑file” rule keeps every model readable and runnable. It also means identical code is copied hundreds of times. Maintenance hurts, contributor PRs snowball, and vision–language models especially end up in siloed forks.</p>
525
- <p>modular_*.py fixes the trade‑off, by auto-generating the modeling file from a modular file, which can use inheritance.</p>
526
- <p>With a small analyser I’ve mapped which models already share modular pieces and which 100‑plus still repeat themselves. Red nodes in the graph = lowest‑hanging fruit for refactor; blue = already modular.</p>
527
- <p>The result: contributors can focus on novel layers instead of boilerplate, reviews shrink from “new file diff” to “does this override make sense?”, and the codebase stays something you can actually open and read.</p>
528
- <p>If you maintain or ship models on top of Transformers, take a look at modular, in 2025 it’s how we keep shipping breadth without the bloat. 🛠️</p>
529
 
530
  </d-article>
531
 
@@ -534,7 +594,7 @@ curl -X POST http://localhost:8000/v1/chat/completions \
534
  const article = document.querySelector('d-article');
535
  const toc = document.querySelector('d-contents');
536
  if (toc) {
537
- const headings = article.querySelectorAll('h1, h2, h3, h4');
538
  let ToC = '<nav role="navigation" class="l-text figcaption">';
539
  ToC += '<div class="toc-header"><span class="toc-title">Table of Contents</span></div>';
540
  ToC += '<div class="toc-content">';
 
8
  <script src="https://d3js.org/d3.v7.min.js"></script>
9
  <meta name="viewport" content="width=device-width, initial-scale=1">
10
  <meta charset="utf8">
11
+ <title>Scaling Insanity: maintaining hundreds of model definitions</title>
12
  <link rel="stylesheet" href="style.css">
13
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css">
14
  </head>
15
  <body>
16
  <d-front-matter>
17
  <script id='distill-front-matter' type="text/json">{
18
+ "title": "Scaling Insanity: maintaining hundreds of model definitions",
19
  "description": "A peek into software engineering for the transformers library",
20
  "published": "Aug 21, 2025",
21
  "authors": [{"author": "Pablo Montalvo", "authorURL": "https://huggingface.co/Molbap"}]
22
  }</script>
23
  </d-front-matter>
24
  <d-title>
25
+ <h1>Scaling Insanity: maintaining hundreds of model definitions</h1>
26
  <p>A peek into software engineering for the transformers library</p>
27
  </d-title>
28
  <d-byline></d-byline>
 
48
  </nav>
49
  </d-contents>
50
  <h2>Introduction</h2>
51
+ <p>The <code>transformers</code> library, built with <code>PyTorch</code>, supports all state-of-the-art LLMs, many VLMs, task-specific vision language models, video models, audio models, table models, classical encoders, to a global count of almost 400 models.</p>
52
+ <p>The name of the library itself is mostly majority driven as many models are not even transformers architectures, like Mamba, Zamba, RWKV, and convolution-based models.</p>
53
+ <p>Regardless, each of these is wrought by the research and engineering team that created them, then harmonized into a now famous interface, and callable with a simple <code>.from_pretrained</code> command.</p>
54
+ <p>Inference works for all models, training is functional for most. The library is a foundation for many machine learning courses, cookbooks, and overall, several thousands other open-source libraries depend on it. All models are tested as part of a daily CI ensuring their preservation and reproducibility. Most importantly, it is <em>open-source</em> and has been written by the community for a large part.
55
+ This isn’t really to brag but to set the stakes: what does it take to keep such a ship afloat, made of so many moving, unrelated parts?</p>
56
+ <p>The ML wave has not stopped, there’s more and more models being added, at a steadily growing rate. <code>Transformers</code> is widely used, and we read the feedback that users post online. Whether it��s about a function that had 300+ keyword arguments, duplicated code and helpers, and mentions of <code>Copied from ... </code> everywhere, along with optimisation concerns. Text-only models are relatively tamed, but multimodal models remain to be harmonized.</p>
57
+ <p>Here we will dissect what is the new design philosophy of transformers, as a continuation from the existing older <a href="https://huggingface.co/docs/transformers/en/philosophy">philosophy</a> page, and an accompanying <a href="https://huggingface.co/blog/transformers-design-philosophy">blog post from 2022</a>.</p>
58
+ <p>More recently, and I recommend the read if it’s not done yet, a blog post about <a href="https://huggingface.co/blog/faster-transformers">recent upgrades to transformers</a> was written, explaining in particular what makes the library faster today.</p>
59
+ <p>Some time ago I dare not say how long, we discussed with transformers maintainers about the state of features in transformers. A lot of recent developments were satisfactory, but if we were only talking about these, self-congratulation would be the only goalpost.</p>
60
+ <p>Reflecting on this philosophy now, as models pile up, is essential and will drive new developments.</p>
61
  <h3>What you will learn</h3>
62
  <p>Every reader, whether an OSS maintainer, power user, or casual fine-tuner, will walk away knowing how to reason about the <code>transformers</code> code base, how to use it better, how to meaningfully contribute to it.
63
  This will also showcase new features you might have missed so you’ll be up-to-date.</p>
 
116
  </li>
117
  <li class="tenet">
118
  <a id="modular-toolbox"></a>
119
+ <strong>Modular Toolbox (Not A Framework)</strong>
120
  <p>We ARE a toolbox. What we are not is a framework: you should not be FORCED to rewrite every modeling, but it is <em>better</em> for your model to be able to inherit from PreTrainedModel and have enabled TensorParallel, from_pretrained, sharding, push_to_hub, loss, as well as PEFT/TRL/SGLang/vLLM.</p>
121
  <em>This is the largest change. Provide tools and utilities, but don't force users into a rigid framework.</em>
122
  </li>
 
300
  <p>For better <em>information</em>, we plan to use <code>python</code> features such as <code>Annotated</code> for example, to inform users of what we expect typically in an argument. That way, higher-level information could be included directly in the type annotations.</p>
301
  <h2><a id="simpler-tensor-parallelism"></a> Simpler Tensor Parallelism</h2>
302
  <p>We want to touch minimally to the modeling code, and only modify it when <em>architectural changes</em> are involved. For instance, for tensor parallelism, we instead now specify a simple <code>tp_plan</code>.</p>
303
+ <p>It is written once in the config and passed to <code>.from_pretrained()</code>.</p>
304
+ <p>The plan maps module name patterns to partitioning strategies. Strategies are resolved by the internal <code>ParallelInterface</code>, which wires to sharding implementations <code>ColwiseParallel</code>, <code>RowwiseParallel</code>, packed variants, and so on.</p>
305
+ <p><pre><code class="language-python"># In the model's config (example: ERNIE 4.5-style decoder blocks)
306
+ base_model_tp_plan = {
307
+ "layers.*.self_attn.q_proj": "colwise",
308
+ "layers.*.self_attn.k_proj": "colwise",
309
+ "layers.*.self_attn.v_proj": "colwise",
310
+ "layers.*.self_attn.o_proj": "rowwise",
311
+ "layers.*.mlp.gate_proj": "colwise",
312
+ "layers.*.mlp.up_proj": "colwise",
313
+ "layers.*.mlp.down_proj": "rowwise",
314
+ }
315
+
316
+ # Runtime
317
+ import torch
318
+ from transformers import AutoModelForCausalLM, AutoTokenizer
319
+
320
+ model_id = "your/model-or-local-checkpoint"
321
+ model = AutoModelForCausalLM.from_pretrained(
322
+ model_id,
323
+ dtype=torch.bfloat16,
324
+ tp_plan=base_model_tp_plan, # <-- plan defined above
325
+ )
326
+ tok = AutoTokenizer.from_pretrained(model_id)
327
+ inputs = tok("Hello", return_tensors="pt").to(model.device)
328
+ out = model(**inputs)</code></pre></p>
329
+ <p>Which allows a user to run with multiple processes per node, e.g. 4 GPUs:</p>
330
+ <p><code>torchrun --nproc-per-node 4 demo.py</code></p>
331
+ <p>Semantics stay in the model (a Linear stays a Linear), distribution is orthogonal and declared via strings: “colwise” splits columns of weights/bias across ranks; “rowwise” splits rows; packed variants shard fused weights; The mapping keys accept glob patterns like <code>layers.*.mlp.down_proj</code> to target repeated submodules.</p>
332
  <h2><a id="layers-attentions-caches"></a> Layers, attentions and caches</h2>
333
  <p>With th</p>
334
  <h2><a id="community-kernels"></a>Community Kernels</h2>
 
363
  </div>
364
 
365
  </p>
 
366
  <p>But there is no similar miracle for VLMs across the board.
367
  As you can see, there is a small DETR island, a little llava pocket, and so on, but it’s not comparable to the centrality observed.</p>
368
  <p>One problem is, this is only for <code>modular</code> models. Several models do NOT have a modular file. In other words, we have a big “hidden space here.”</p>
 
446
  <h2>Modularity candidates</h2>
447
  <p>So the question abounds naturally: How can we modularize more?
448
  I took again a similarity measure and looked at the existing graphs. The tool is available on this <a href="https://huggingface.co/spaces/Molbap/transformers-modular-refactor">ZeroGPU-enabled Space</a>. It scans the whole transformers repository, and outputs a graph of candidates across models, using either a Jaccard similarity index (simple) or a SentenceTransformers embedding model. It is understandable that <a href="#encoders-ftw">encoder models still have a lion’s share of the game.</a> See also <a href="https://huggingface.co/blog/train-sparse-encoder">Tom Aarsen and Arhur Bresnu’s great blog post on the topic of sparse embeddings.</a>.</p>
449
+ <p></p>
450
  <h2><a id="encoders-ftw"></a> The neverending stories of encoder models.</h2>
451
  <p>Models popularity speaks for itself! This is because the usage of encoders lies in embeddings obviously. So we have to keep the encoders part viable, usable, fine-tune-able.</p>
452
  <p><img src="static/popular_models_barplot.png" alt="Popular models bar plot"></p>
 
531
  <li>having it immediately available to the community</li>
532
  <li>usable in vLLM, SGLang, and so on without additional code.</li>
533
  </ul>
534
+ <h2>Cooking faster CUDA warmups</h2>
535
  <p>Having a clean <em>external</em> API allows us to work on the true inner workings of transformers. One of the few recent additions was the <em>CUDA warmup</em> via <code>caching_allocator_warmup</code> which improved massively the loading footprint by pre-allocating GPU memory to avoid malloc bottlenecks during model loading.</p>
536
+ <p><style>.warmup-demo body{background-color:#f5f5f5;margin:0;padding:20px;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.warmup-demo .container{background:#fff;border-radius:12px;max-width:1200px;margin:0 auto;padding:30px;box-shadow:0 4px 6px #0000001a}.warmup-demo h1{text-align:center;color:#333;margin-bottom:10px}.warmup-demo .subtitle{text-align:center;color:#666;margin-bottom:30px;font-size:16px}.warmup-demo .demo-container{gap:40px;margin-bottom:30px;display:flex}.warmup-demo .side{background:#fafafa;border:2px solid #ddd;border-radius:8px;flex:1;padding:20px}.warmup-demo .side h2{text-align:center;color:#333;margin-top:0}.warmup-demo .no-warmup h2{color:#d63384}.warmup-demo .with-warmup h2{color:#198754}.warmup-demo .memory-area{background:#fff;border:2px dashed #ccc;border-radius:6px;height:400px;margin:20px 0;padding:10px;position:relative;overflow:hidden}.warmup-demo .layer-box{background:#fff;border:2px solid #666;border-radius:4px;width:80px;height:30px;margin:3px;transition:all .3s;display:inline-block;position:relative}.warmup-demo .layer-box.allocating{background:#e9ecef;border-color:#adb5bd}.warmup-demo .layer-box.allocating:after{content:"malloc";color:#666;font-size:10px;font-weight:700;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.warmup-demo .layer-box.loaded{background:#d1e7dd;border-color:#198754}.warmup-demo .layer-box.loaded:after{content:"data";color:#198754;font-size:10px;font-weight:700;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.warmup-demo .warmup-container{background:#fff;border:3px solid #666;border-radius:6px;width:100%;height:60px;margin-bottom:20px;position:relative;overflow:hidden}.warmup-demo .warmup-container.allocated{background:#e7f1ff;border-color:#0d6efd}.warmup-demo .warmup-container:before{content:"Pre-allocated Memory Pool";color:#666;z-index:1;font-size:14px;font-weight:700;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.warmup-demo .warmup-container.allocated:before{color:#0d6efd}.warmup-demo .warmup-fill{z-index:2;background:linear-gradient(90deg,#198754,#20c997);border-radius:3px;width:0%;height:100%;transition:width .5s;position:relative}.warmup-demo .warmup-fill:after{content:"Layer Data Loading";color:#fff;white-space:nowrap;font-size:12px;font-weight:700;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.warmup-demo .timing{text-align:center;min-height:30px;margin:15px 0;font-size:24px;font-weight:700}.warmup-demo .no-warmup .timing{color:#d63384}.warmup-demo .with-warmup .timing{color:#198754}.warmup-demo .controls{text-align:center;margin:30px 0}.warmup-demo .btn{color:#fff;cursor:pointer;background:#0d6efd;border:none;border-radius:6px;margin:0 10px;padding:12px 24px;font-size:16px;transition:background .3s}.warmup-demo .btn:hover{background:#0b5ed7}.warmup-demo .btn:disabled{cursor:not-allowed;background:#6c757d}.warmup-demo .description{background:#f8f9fa;border-radius:6px;margin-top:15px;padding:15px;font-size:14px;line-height:1.5}.warmup-demo .phase-indicator{color:#666;text-align:center;min-height:20px;margin-top:10px;font-size:14px}.warmup-demo .layer-counter{text-align:center;color:#495057;margin:10px 0;font-size:16px}</style>
537
+
538
+ <div class=warmup-demo>
539
+ <div class=container>
540
+ <p class=subtitle>Mem allocation patterns during model loading</p>
541
+
542
+ <div class=controls>
543
+ <button class=btn id=startBtn onclick=startDemo()>Start Animation</button>
544
+ <button class=btn id=resetBtn onclick=resetDemo()>Reset</button>
545
+ </div>
546
+
547
+ <div class=demo-container>
548
+ <div class="no-warmup side">
549
+ <h2 data-no-toc>❌ Without Warmup</h2>
550
+ <div class=timing id=noWarmupTime>0.00s</div>
551
+ <div class=layer-counter id=noWarmupCounter>Layers loaded: 0/10</div>
552
+ <div class=phase-indicator id=noWarmupPhase></div>
553
+ <div class=memory-area id=noWarmupArea></div>
554
+ <div class=description>
555
+ <strong>Individual Allocations:</strong><br>
556
+ Each model layer triggers a separate cudaMalloc() call, creating memory fragmentation and allocation overhead.
557
+ <br><br>
558
+ 📦 <strong>Grey "malloc"</strong> = Memory allocation overhead<br>
559
+ ✅ <strong>Green "data"</strong> = Actual layer data loading
560
+ </div>
561
+ </div>
562
+
563
+ <div class="side with-warmup">
564
+ <h2 data-no-toc>✅ With Warmup</h2>
565
+ <div class=timing id=warmupTime>0.00s</div>
566
+ <div class=layer-counter id=warmupCounter>Layers loaded: 0/10</div>
567
+ <div class=phase-indicator id=warmupPhase></div>
568
+ <div class=memory-area id=warmupArea>
569
+ <div class=warmup-container id=warmupContainer>
570
+ <div class=warmup-fill id=warmupFill></div>
571
+ </div>
572
+ <div id=warmupLayers></div>
573
+ </div>
574
+ <div class=description>
575
+ <strong>Pre-allocated Pool:</strong><br>
576
+ The warmup function calculates total memory needed and makes ONE large allocation. Subsequent layers load directly into this pool, eliminating malloc overhead.
577
+ <br><br>
578
+ 🔵 <strong>Blue container</strong> = Single large malloc (warmup)<br>
579
+ 🟢 <strong>Green progress bar</strong> = Layer data loading (no malloc needed)
580
+ </div>
581
+ </div>
582
+ </div>
583
  </div>
584
+ </div>
585
+
586
+ <script>let animationSpeed=1/2.4,isRunning=!1,totalLayers=10;function startDemo(){isRunning||(isRunning=!0,document.getElementById("startBtn").disabled=!0,document.getElementById("resetBtn").disabled=!0,Promise.all([animateNoWarmup(),animateWithWarmup()]).then(()=>{isRunning=!1,document.getElementById("startBtn").disabled=!1,document.getElementById("resetBtn").disabled=!1}))}function resetDemo(){isRunning||(document.getElementById("noWarmupArea").innerHTML="",document.getElementById("warmupLayers").innerHTML="",document.getElementById("warmupFill").style.width="0%",document.getElementById("warmupContainer").classList.remove("allocated"),document.getElementById("noWarmupTime").textContent="0.00s",document.getElementById("warmupTime").textContent="0.00s",document.getElementById("noWarmupCounter").textContent="Layers loaded: 0/10",document.getElementById("warmupCounter").textContent="Layers loaded: 0/10",document.getElementById("noWarmupPhase").textContent="",document.getElementById("warmupPhase").textContent="")}async function animateNoWarmup(){let e=document.getElementById("noWarmupArea"),t=document.getElementById("noWarmupTime"),n=document.getElementById("noWarmupCounter"),a=document.getElementById("noWarmupPhase"),m=0,o=200/animationSpeed;a.textContent="Loading model layers...";for(let a=0;a<10;a++){let d=document.createElement("div");d.className="layer-box",e.appendChild(d),await sleep(.3*o),d.classList.add("allocating"),t.textContent=(m+=.08).toFixed(2)+"s",await sleep(.7*o),d.classList.remove("allocating"),d.classList.add("loaded"),t.textContent=(m+=.12).toFixed(2)+"s",n.textContent=`Layers loaded: ${a+1}/10`}a.textContent="Complete!"}async function animateWithWarmup(){let e=document.getElementById("warmupLayers"),t=document.getElementById("warmupTime"),n=document.getElementById("warmupCounter"),a=document.getElementById("warmupPhase"),m=document.getElementById("warmupContainer"),o=document.getElementById("warmupFill"),d=0,l=200/animationSpeed;a.textContent="Warming up allocator...",await sleep(2*l),m.classList.add("allocated"),t.textContent=(d+=.3).toFixed(2)+"s",a.textContent="Loading model layers...";for(let a=0;a<10;a++){let m=document.createElement("div");m.className="layer-box loaded",m.style.width="40px",m.style.height="20px",e.appendChild(m);let i=(a+1)/10*100;o.style.width=i+"%",await sleep(.5*l),t.textContent=(d+=.08).toFixed(2)+"s",n.textContent=`Layers loaded: ${a+1}/10`}a.textContent="Complete!"}function sleep(e){return new Promise(t=>setTimeout(t,e))}</script></p>
587
+ <h2>What is coming next</h2>
588
+ <p>It sounds dumb, but it’s true: the future is very soon. One tenet that will be broken when the next major version is released, v5, <a href="#backwards-compatibility">backwards compatibility</a> will be heavily broken. Instead, what we aim to be is way more of a <a href="#modular-toolbox">modular toolbox</a>, while maintaining a <a href="#consistent-public-surface">consistent public surface</a>.</p>
 
 
 
 
589
 
590
  </d-article>
591
 
 
594
  const article = document.querySelector('d-article');
595
  const toc = document.querySelector('d-contents');
596
  if (toc) {
597
+ const headings = [...article.querySelectorAll('h1, h2, h3, h4')].filter(h => !h.hasAttribute('data-no-toc'));
598
  let ToC = '<nav role="navigation" class="l-text figcaption">';
599
  ToC += '<div class="toc-header"><span class="toc-title">Table of Contents</span></div>';
600
  ToC += '<div class="toc-content">';
dist/main.bundle.js CHANGED
@@ -146,7 +146,7 @@ module.exports = styleTagTransform;
146
  var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
147
  ___CSS_LOADER_EXPORT___.i(_node_modules_css_loader_dist_cjs_js_transformers_custom_css__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .A);
148
  // Module
149
- ___CSS_LOADER_EXPORT___.push([module.id, `/* style.css - Transformers Playthrough */
150
 
151
  /* Import ultrascale-playbook base styles and add transformers-specific styling */
152
  /* Define colors */
@@ -885,7 +885,7 @@ iframe, .js-plotly-plot {
885
  margin-right: 0px;
886
  }
887
 
888
- /* Import transformers-specific styles */`, "",{"version":3,"sources":["webpack://./src/style.css"],"names":[],"mappings":"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","sourcesContent":["/* style.css - Transformers Playthrough */\n\n/* Import ultrascale-playbook base styles and add transformers-specific styling */\n/* Define colors */\n:root {\n --distill-gray: rgb(107, 114, 128);\n --distill-gray-light: rgb(185, 185, 185);\n --distill-gray-lighter: rgb(228, 228, 228);\n --distill-gray-lightest: rgb(245, 245, 245);\n --distill-blue: #007BFF;\n}\n\n/* Container for the controls */\n[id^=\"plot-\"] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 15px; /* Adjust the gap between controls as needed */\n}\n[id^=\"plot-\"] figure {\n margin-bottom: 0px;\n margin-top: 0px;\n padding: 0px;\n}\n.plotly_caption {\n font-style: italic;\n margin-top: 10px;\n}\n\n.plotly_controls {\n display: flex;\n flex-wrap: wrap;\n flex-direction: row;\n justify-content: center;\n align-items: flex-start;\n gap: 30px;\n}\n\n\n.plotly_input_container {\n display: flex;\n align-items: center;\n flex-direction: column;\n gap: 10px;\n}\n\n/* Style for the select dropdown */\n.plotly_input_container > select {\n padding: 2px 4px;\n /* border: 1px solid #ccc; */\n line-height: 1.5em;\n text-align: center;\n border-radius: 4px;\n font-size: 12px;\n background-color: var(--distill-gray-lightest);\n outline: none;\n}\n\n/* Style for the range input */\n\n.plotly_slider {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.plotly_slider > input[type=\"range\"] {\n -webkit-appearance: none;\n height: 2px;\n background: var(--distill-gray-light);\n border-radius: 5px;\n outline: none;\n}\n\n.plotly_slider > span {\n font-size: 14px;\n line-height: 1.6em;\n min-width: 16px;\n}\n\n.plotly_slider > input[type=\"range\"]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--distill-blue);\n cursor: pointer;\n}\n\n.plotly_slider > input[type=\"range\"]::-moz-range-thumb {\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--distill-blue);\n cursor: pointer;\n}\n\n/* Style for the labels */\n.plotly_input_container > label {\n font-size: 14px;\n font-weight: bold;\n}\n\n.main-plot-container {\n margin-top: 21px;\n margin-bottom: 35px;\n}\n\n.main-plot-container > figure {\n display: block !important;\n /* Let this be handled by graph-container */\n margin-bottom: 0px;\n margin-top: 0px;\n}\n.main-plot-container > div {\n display: none !important;\n}\n\n\n@media (min-width: 768px) {\n .main-plot-container > figure {\n display: none !important;\n }\n .main-plot-container > div {\n display: flex !important;\n }\n}\n\nd-byline .byline {\n grid-template-columns: 1fr;\n grid-column: text;\n font-size: 0.9rem;\n line-height: 1.8em;\n}\n\n@media (min-width: 768px) {\n d-byline .byline {\n grid-template-columns: 5fr 1fr 1fr;\n }\n}\n\n#title-plot {\n margin-top: 0px;\n margin-bottom: 0px;\n}\n\nd-contents > nav a.active {\n text-decoration: underline;\n}\n\n@media (max-width: 1199px) {\n d-contents {\n display: none;\n background: white;\n justify-self: start;\n align-self: start;\n padding-bottom: 0.5em;\n margin-bottom: 1em;\n padding-left: 0.25em;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n border-bottom-width: 1px;\n border-bottom-style: solid;\n border-bottom-color: rgba(0, 0, 0, 0.1);\n overflow-y: scroll;\n height: calc(100vh - 40px);\n scrollbar-width: none;\n z-index: -100;\n }\n}\n\nd-contents a:hover {\n border-bottom: none;\n}\n\ntoc-title {\n font-weight: bold;\n font-size: 1.2em;\n color: #333;\n}\n\ntoggle-icon {\n transition: transform 0.3s;\n}\n\ntoggle-icon.collapsed {\n transform: rotate(90deg);\n}\n\n.toc-content {\n margin-top: 15px;\n overflow: hidden;\n /* max-height: 1000px; */\n transition: max-height 0.3s ease-out;\n}\n\n.toc-content.collapsed {\n max-height: 0;\n margin-top: 0;\n}\n\n@media (min-width: 1200px) {\n d-article {\n /* Ensure d-article does not prevent sticky positioning */\n overflow: visible;\n }\n\n d-contents {\n align-self: start;\n background: white;\n grid-column-start: 1 !important;\n grid-column-end: 4 !important;\n grid-row: auto / span 6;\n justify-self: end;\n margin-top: 0em;\n padding-right: 3em;\n padding-left: 2em;\n /* border-right: 1px solid rgba(0, 0, 0, 0.1);\n border-right-width: 1px;\n border-right-style: solid;\n border-right-color: rgba(0, 0, 0, 0.1); */\n position: -webkit-sticky; /* For Safari */\n position: sticky;\n top: 10px; /* Adjust this value if needed */\n overflow-y: auto;\n height: calc(100vh - 40px);\n scrollbar-width: none;\n transition: max-height 0.3s ease-out;\n z-index: -100;\n }\n}\n\nd-contents nav h3 {\n margin-top: 0;\n margin-bottom: 1em;\n}\n\nd-contents nav div div {\n color: rgba(0, 0, 0, 0.8);\n font-weight: bold;\n}\n\nd-contents nav a {\n color: rgba(0, 0, 0, 0.8);\n border-bottom: none;\n text-decoration: none;\n}\n\nd-contents li {\n list-style-type: none;\n}\n\nd-contents ul, d-article d-contents ul {\n padding-left: 1em;\n}\n\nd-contents nav ul li {\n margin-bottom: .25em;\n}\n\nd-contents nav a:hover {\n text-decoration: underline solid rgba(0, 0, 0, 0.6);\n}\n\nd-contents nav ul {\n margin-top: 0;\n margin-bottom: 6px;\n}\n\n\nd-contents nav > div {\n display: block;\n outline: none;\n margin-bottom: 0.5em;\n}\n\nd-contents nav > div > a {\n font-size: 13px;\n font-weight: 600;\n}\n\nd-article aside {\n margin-bottom: 1em;\n}\n\nd-article img {\n max-width: 100%;\n}\n\n@media (min-width: 768px) {\n d-article aside {\n margin-bottom: 0;\n }\n}\n\nd-contents nav > div > a:hover,\nd-contents nav > ul > li > a:hover {\n text-decoration: none;\n}\n\n.note-box {\n background-color: #f6f8fa;\n border-left: 4px solid #444444;\n padding: 1rem;\n margin: 1rem 0; /* Keep this modest margin */\n border-radius: 6px;\n /* Add this to ensure the box only takes up needed space */\n display: inline-block;\n}\n\n.note-box-title {\n margin: 0;\n color: #444444;\n font-weight: 600;\n font-size: 1em;\n}\n\n.note-box-content {\n margin-top: 0.5rem;\n margin-bottom: 0; /* Ensure no bottom margin */\n color: #24292f;\n font-size: 0.9em;\n line-height: 1.5em;\n}\n\n/* For dark mode support */\n@media (prefers-color-scheme: dark) {\n .note-box {\n background-color: #1c1c1c;\n border-left-color: #888888;\n }\n .note-box-title {\n color: #888888;\n }\n .note-box-content {\n color: #d4d4d4;\n }\n}\n\nd-article {\n font-size: 1.0em;\n}\n\n.figure-legend {\n font-size: 0.9em;\n font-style: italic;\n color: var(--distill-gray);\n line-height: 1.5em;\n}\n\nd-code {\n font-size: 12px;\n}\n\n.large-image-background {\n width: 100vw;\n padding-top: 10px;\n padding-bottom: 10px;\n margin-left: calc(-50vw + 50%);\n margin-right: calc(-50vw + 50%);\n background: white;\n height: fit-content; /* This will make it match the image height */\n display: flex;\n justify-content: center; /* This will center your image */\n}\n\n.large-image-background-transparent {\n /* width: 100vw; */\n padding-top: 10px;\n padding-bottom: 10px;\n /* margin-left: calc(-50vw + 50%); */\n margin-left:-100px;\n margin-right: -100px;\n /* margin-right: calc(-50vw + 50%); */\n /* background: white; */\n height: fit-content; /* This will make it match the image height */\n display: flex;\n justify-content: center; /* This will center your image */\n}\n\n.boxed-image {\n padding: 0.5rem;\n background: white;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n}\n\nd-article li {\n margin-bottom: 0.0em;\n}\n\nd-article ul ul {\n margin-bottom: 0.0em;\n}\n\nd-article ol ol {\n margin-bottom: 0.0em;\n}\n\nd-article hr {\n grid-column: text;\n}\n\n/* Memory visualization */\n#graph-all {\n min-width: 500px;\n margin-right: 10px;\n margin-bottom: 2rem;\n padding: 0.5rem;\n background: #f9fafb;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n}\n\n\n/* Main container styles */\n#controls {\n max-width: 1200px;\n /* margin: 2rem auto; */\n margin-bottom: 2rem;\n margin-left: 10px;\n padding: 0.6rem;\n background: #f9fafb;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n}\n\n/* Grid layout */\n#controls {\n display: grid;\n grid-template-columns: 1fr 1fr;\n /* gap: 2rem; */\n}\n\n/* Cell styles */\n.cell {\n margin-bottom: 0.2rem;\n}\n\n/* Label styles */\nlabel {\n display: block;\n /* margin-bottom: 0.5rem; */\n font-size: 0.8rem;\n font-weight: 500;\n color: #374151;\n}\n\n/* Input container for range + number combination */\n.input-container {\n display: flex;\n gap: 1rem;\n align-items: center;\n}\n\n/* Range input styling */\ninput[type=\"range\"] {\n flex: 1;\n height: 6px;\n background: #e5e7eb;\n border-radius: 3px;\n appearance: none;\n outline: none;\n}\n\ninput[type=\"range\"]::-webkit-slider-thumb {\n appearance: none;\n width: 16px;\n height: 16px;\n background: #3b82f6;\n border-radius: 50%;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\ninput[type=\"range\"]::-webkit-slider-thumb:hover {\n background: #2563eb;\n}\n\n/* Number input styling */\ninput[type=\"number\"] {\n width: 80px;\n padding: 0.5rem;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n font-size: 0.9rem;\n color: #374151;\n}\n\n/* Select styling */\nselect {\n width: 100%;\n padding: 0.5rem;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n background: white;\n font-size: 0.9rem;\n color: #374151;\n cursor: pointer;\n}\n\n/* Checkbox styling */\ninput[type=\"checkbox\"] {\n width: 1.2rem;\n height: 1.2rem;\n margin-right: 0.5rem;\n border: 2px solid #e5e7eb;\n border-radius: 4px;\n cursor: pointer;\n}\n\n/* Column specific styles */\n.column-1 {\n padding-right: 0.5rem;\n}\n\n.column-2 {\n padding-left: 0.5rem;\n}\n\n/* Checkbox container */\n.checkbox-container {\n display: flex;\n align-items: center;\n margin-bottom: 1rem;\n}\n\n/* Memory visualization styles */\n.memory-block {\n background: #fff;\n border-radius: 8px;\n padding: 1rem;\n margin-bottom: 1rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.memory-title {\n font-size: 1.1rem;\n font-weight: 500;\n color: #374151;\n margin-bottom: 0.5rem;\n}\n\n.memory-value {\n font-size: 1.5rem;\n font-weight: 600;\n color: #3b82f6;\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n #controls {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n\n .column-1, .column-2 {\n padding: 0;\n }\n}\n\n/* Hover states and transitions */\ninput:hover, select:hover {\n border-color: #3b82f6;\n}\n\ninput:focus, select:focus {\n border-color: #2563eb;\n outline: none;\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);\n}\n\n/* Add smooth transitions */\ninput, select, button {\n transition: all 0.15s ease;\n}\n\n/* Preset dropdown special styling */\nselect[name=\"presets\"] {\n background-color: #f3f4f6;\n font-weight: 500;\n}\n\n/* Memory graph enhancements */\n.activation-memory {\n background: #dbeafe;\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 1rem;\n}\n\n.gradient-memory {\n background: #ede9fe;\n padding: 1rem;\n border-radius: 8px;\n}\n\n.order-button-second {\n background: linear-gradient(135deg, #6DB4C4, #D4A5B8);\n color: white;\n font-size: 18px;\n font-weight: 600;\n padding: 20px 20px;\n border: none;\n border-radius: 12px;\n cursor: pointer;\n text-transform: uppercase;\n letter-spacing: 1px;\n box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n }\n.order-button-second:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);\n}\n\n.order-button:active {\n transform: translateY(0);\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);\n}\n\n.order-button-second::before {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0));\n transition: left 0.5s ease;\n}\n\n.order-button-second:hover::before {\n left: 100%;\n}\n\n.order-button {\n background: linear-gradient(135deg, #6DB4C4, #D4A5B8);\n color: white;\n font-size: 18px;\n font-weight: 600;\n padding: 16px 32px;\n border: none;\n border-radius: 12px;\n cursor: pointer;\n text-transform: uppercase;\n letter-spacing: 1px;\n box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n }\n\n.order-button:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);\n}\n\n.order-button:active {\n transform: translateY(0);\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);\n}\n\n.order-button::before {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0));\n transition: left 0.5s ease;\n}\n\n.order-button:hover::before {\n left: 100%;\n}\n.order-button-container-second {\n /* display: flex; */\n justify-content: center;\n margin: 0px 0;\n}\n\n.order-button-container {\n display: flex;\n justify-content: center;\n margin: 0px 0 40px 0;\n}\n\nd-article img {\n width: 100%!important;\n}\n\n\niframe, .js-plotly-plot {\n width: 100%!important;\n margin-bottom: 20px;\n}\n\n.modebar-container {\n display: none;\n}\n\n#graph-container {\n display: grid; grid-template-columns: 1fr 1fr; align-items: center;\n}\n\n@media (max-width: 768px) {\n #graph-container {\n grid-template-columns: 1fr;\n }\n}\n\n@media (max-width: 1024px) {\n #graph-container {\n grid-template-columns: 1fr;\n }\n #graph-all {\n margin-right: 0px;\n }\n #controls {\n margin-left: 0px;\n }\n}\n\n.main-plot-container svg {\n background: transparent !important;\n}\n\n.large-image-background-transparent {\n margin-left: 0px;\n margin-right: 0px;\n}\n\n/* Import transformers-specific styles */\n@import url('./transformers-custom.css');"],"sourceRoot":""}]);
889
  // Exports
890
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
891
 
@@ -1973,11 +1973,11 @@ var update = injectStylesIntoStyleTag_default()(style/* default */.A, options);
1973
  /* harmony default export */ const src_style = (style/* default */.A && style/* default */.A.locals ? style/* default */.A.locals : undefined);
1974
 
1975
  ;// ./src/index.js
1976
- // Main JavaScript file for transformers playthrough
1977
 
1978
 
1979
  // Import any additional functionality
1980
- console.log('Transformers Playthrough loaded');
1981
 
1982
  // Add any custom JavaScript functionality here
1983
  document.addEventListener('DOMContentLoaded', function () {
 
146
  var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
147
  ___CSS_LOADER_EXPORT___.i(_node_modules_css_loader_dist_cjs_js_transformers_custom_css__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .A);
148
  // Module
149
+ ___CSS_LOADER_EXPORT___.push([module.id, `/* style.css - Scaling Insanity */
150
 
151
  /* Import ultrascale-playbook base styles and add transformers-specific styling */
152
  /* Define colors */
 
885
  margin-right: 0px;
886
  }
887
 
888
+ /* Import transformers-specific styles */`, "",{"version":3,"sources":["webpack://./src/style.css"],"names":[],"mappings":"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","sourcesContent":["/* style.css - Scaling Insanity */\n\n/* Import ultrascale-playbook base styles and add transformers-specific styling */\n/* Define colors */\n:root {\n --distill-gray: rgb(107, 114, 128);\n --distill-gray-light: rgb(185, 185, 185);\n --distill-gray-lighter: rgb(228, 228, 228);\n --distill-gray-lightest: rgb(245, 245, 245);\n --distill-blue: #007BFF;\n}\n\n/* Container for the controls */\n[id^=\"plot-\"] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 15px; /* Adjust the gap between controls as needed */\n}\n[id^=\"plot-\"] figure {\n margin-bottom: 0px;\n margin-top: 0px;\n padding: 0px;\n}\n.plotly_caption {\n font-style: italic;\n margin-top: 10px;\n}\n\n.plotly_controls {\n display: flex;\n flex-wrap: wrap;\n flex-direction: row;\n justify-content: center;\n align-items: flex-start;\n gap: 30px;\n}\n\n\n.plotly_input_container {\n display: flex;\n align-items: center;\n flex-direction: column;\n gap: 10px;\n}\n\n/* Style for the select dropdown */\n.plotly_input_container > select {\n padding: 2px 4px;\n /* border: 1px solid #ccc; */\n line-height: 1.5em;\n text-align: center;\n border-radius: 4px;\n font-size: 12px;\n background-color: var(--distill-gray-lightest);\n outline: none;\n}\n\n/* Style for the range input */\n\n.plotly_slider {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.plotly_slider > input[type=\"range\"] {\n -webkit-appearance: none;\n height: 2px;\n background: var(--distill-gray-light);\n border-radius: 5px;\n outline: none;\n}\n\n.plotly_slider > span {\n font-size: 14px;\n line-height: 1.6em;\n min-width: 16px;\n}\n\n.plotly_slider > input[type=\"range\"]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--distill-blue);\n cursor: pointer;\n}\n\n.plotly_slider > input[type=\"range\"]::-moz-range-thumb {\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--distill-blue);\n cursor: pointer;\n}\n\n/* Style for the labels */\n.plotly_input_container > label {\n font-size: 14px;\n font-weight: bold;\n}\n\n.main-plot-container {\n margin-top: 21px;\n margin-bottom: 35px;\n}\n\n.main-plot-container > figure {\n display: block !important;\n /* Let this be handled by graph-container */\n margin-bottom: 0px;\n margin-top: 0px;\n}\n.main-plot-container > div {\n display: none !important;\n}\n\n\n@media (min-width: 768px) {\n .main-plot-container > figure {\n display: none !important;\n }\n .main-plot-container > div {\n display: flex !important;\n }\n}\n\nd-byline .byline {\n grid-template-columns: 1fr;\n grid-column: text;\n font-size: 0.9rem;\n line-height: 1.8em;\n}\n\n@media (min-width: 768px) {\n d-byline .byline {\n grid-template-columns: 5fr 1fr 1fr;\n }\n}\n\n#title-plot {\n margin-top: 0px;\n margin-bottom: 0px;\n}\n\nd-contents > nav a.active {\n text-decoration: underline;\n}\n\n@media (max-width: 1199px) {\n d-contents {\n display: none;\n background: white;\n justify-self: start;\n align-self: start;\n padding-bottom: 0.5em;\n margin-bottom: 1em;\n padding-left: 0.25em;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n border-bottom-width: 1px;\n border-bottom-style: solid;\n border-bottom-color: rgba(0, 0, 0, 0.1);\n overflow-y: scroll;\n height: calc(100vh - 40px);\n scrollbar-width: none;\n z-index: -100;\n }\n}\n\nd-contents a:hover {\n border-bottom: none;\n}\n\ntoc-title {\n font-weight: bold;\n font-size: 1.2em;\n color: #333;\n}\n\ntoggle-icon {\n transition: transform 0.3s;\n}\n\ntoggle-icon.collapsed {\n transform: rotate(90deg);\n}\n\n.toc-content {\n margin-top: 15px;\n overflow: hidden;\n /* max-height: 1000px; */\n transition: max-height 0.3s ease-out;\n}\n\n.toc-content.collapsed {\n max-height: 0;\n margin-top: 0;\n}\n\n@media (min-width: 1200px) {\n d-article {\n /* Ensure d-article does not prevent sticky positioning */\n overflow: visible;\n }\n\n d-contents {\n align-self: start;\n background: white;\n grid-column-start: 1 !important;\n grid-column-end: 4 !important;\n grid-row: auto / span 6;\n justify-self: end;\n margin-top: 0em;\n padding-right: 3em;\n padding-left: 2em;\n /* border-right: 1px solid rgba(0, 0, 0, 0.1);\n border-right-width: 1px;\n border-right-style: solid;\n border-right-color: rgba(0, 0, 0, 0.1); */\n position: -webkit-sticky; /* For Safari */\n position: sticky;\n top: 10px; /* Adjust this value if needed */\n overflow-y: auto;\n height: calc(100vh - 40px);\n scrollbar-width: none;\n transition: max-height 0.3s ease-out;\n z-index: -100;\n }\n}\n\nd-contents nav h3 {\n margin-top: 0;\n margin-bottom: 1em;\n}\n\nd-contents nav div div {\n color: rgba(0, 0, 0, 0.8);\n font-weight: bold;\n}\n\nd-contents nav a {\n color: rgba(0, 0, 0, 0.8);\n border-bottom: none;\n text-decoration: none;\n}\n\nd-contents li {\n list-style-type: none;\n}\n\nd-contents ul, d-article d-contents ul {\n padding-left: 1em;\n}\n\nd-contents nav ul li {\n margin-bottom: .25em;\n}\n\nd-contents nav a:hover {\n text-decoration: underline solid rgba(0, 0, 0, 0.6);\n}\n\nd-contents nav ul {\n margin-top: 0;\n margin-bottom: 6px;\n}\n\n\nd-contents nav > div {\n display: block;\n outline: none;\n margin-bottom: 0.5em;\n}\n\nd-contents nav > div > a {\n font-size: 13px;\n font-weight: 600;\n}\n\nd-article aside {\n margin-bottom: 1em;\n}\n\nd-article img {\n max-width: 100%;\n}\n\n@media (min-width: 768px) {\n d-article aside {\n margin-bottom: 0;\n }\n}\n\nd-contents nav > div > a:hover,\nd-contents nav > ul > li > a:hover {\n text-decoration: none;\n}\n\n.note-box {\n background-color: #f6f8fa;\n border-left: 4px solid #444444;\n padding: 1rem;\n margin: 1rem 0; /* Keep this modest margin */\n border-radius: 6px;\n /* Add this to ensure the box only takes up needed space */\n display: inline-block;\n}\n\n.note-box-title {\n margin: 0;\n color: #444444;\n font-weight: 600;\n font-size: 1em;\n}\n\n.note-box-content {\n margin-top: 0.5rem;\n margin-bottom: 0; /* Ensure no bottom margin */\n color: #24292f;\n font-size: 0.9em;\n line-height: 1.5em;\n}\n\n/* For dark mode support */\n@media (prefers-color-scheme: dark) {\n .note-box {\n background-color: #1c1c1c;\n border-left-color: #888888;\n }\n .note-box-title {\n color: #888888;\n }\n .note-box-content {\n color: #d4d4d4;\n }\n}\n\nd-article {\n font-size: 1.0em;\n}\n\n.figure-legend {\n font-size: 0.9em;\n font-style: italic;\n color: var(--distill-gray);\n line-height: 1.5em;\n}\n\nd-code {\n font-size: 12px;\n}\n\n.large-image-background {\n width: 100vw;\n padding-top: 10px;\n padding-bottom: 10px;\n margin-left: calc(-50vw + 50%);\n margin-right: calc(-50vw + 50%);\n background: white;\n height: fit-content; /* This will make it match the image height */\n display: flex;\n justify-content: center; /* This will center your image */\n}\n\n.large-image-background-transparent {\n /* width: 100vw; */\n padding-top: 10px;\n padding-bottom: 10px;\n /* margin-left: calc(-50vw + 50%); */\n margin-left:-100px;\n margin-right: -100px;\n /* margin-right: calc(-50vw + 50%); */\n /* background: white; */\n height: fit-content; /* This will make it match the image height */\n display: flex;\n justify-content: center; /* This will center your image */\n}\n\n.boxed-image {\n padding: 0.5rem;\n background: white;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n}\n\nd-article li {\n margin-bottom: 0.0em;\n}\n\nd-article ul ul {\n margin-bottom: 0.0em;\n}\n\nd-article ol ol {\n margin-bottom: 0.0em;\n}\n\nd-article hr {\n grid-column: text;\n}\n\n/* Memory visualization */\n#graph-all {\n min-width: 500px;\n margin-right: 10px;\n margin-bottom: 2rem;\n padding: 0.5rem;\n background: #f9fafb;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n}\n\n\n/* Main container styles */\n#controls {\n max-width: 1200px;\n /* margin: 2rem auto; */\n margin-bottom: 2rem;\n margin-left: 10px;\n padding: 0.6rem;\n background: #f9fafb;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n}\n\n/* Grid layout */\n#controls {\n display: grid;\n grid-template-columns: 1fr 1fr;\n /* gap: 2rem; */\n}\n\n/* Cell styles */\n.cell {\n margin-bottom: 0.2rem;\n}\n\n/* Label styles */\nlabel {\n display: block;\n /* margin-bottom: 0.5rem; */\n font-size: 0.8rem;\n font-weight: 500;\n color: #374151;\n}\n\n/* Input container for range + number combination */\n.input-container {\n display: flex;\n gap: 1rem;\n align-items: center;\n}\n\n/* Range input styling */\ninput[type=\"range\"] {\n flex: 1;\n height: 6px;\n background: #e5e7eb;\n border-radius: 3px;\n appearance: none;\n outline: none;\n}\n\ninput[type=\"range\"]::-webkit-slider-thumb {\n appearance: none;\n width: 16px;\n height: 16px;\n background: #3b82f6;\n border-radius: 50%;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\ninput[type=\"range\"]::-webkit-slider-thumb:hover {\n background: #2563eb;\n}\n\n/* Number input styling */\ninput[type=\"number\"] {\n width: 80px;\n padding: 0.5rem;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n font-size: 0.9rem;\n color: #374151;\n}\n\n/* Select styling */\nselect {\n width: 100%;\n padding: 0.5rem;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n background: white;\n font-size: 0.9rem;\n color: #374151;\n cursor: pointer;\n}\n\n/* Checkbox styling */\ninput[type=\"checkbox\"] {\n width: 1.2rem;\n height: 1.2rem;\n margin-right: 0.5rem;\n border: 2px solid #e5e7eb;\n border-radius: 4px;\n cursor: pointer;\n}\n\n/* Column specific styles */\n.column-1 {\n padding-right: 0.5rem;\n}\n\n.column-2 {\n padding-left: 0.5rem;\n}\n\n/* Checkbox container */\n.checkbox-container {\n display: flex;\n align-items: center;\n margin-bottom: 1rem;\n}\n\n/* Memory visualization styles */\n.memory-block {\n background: #fff;\n border-radius: 8px;\n padding: 1rem;\n margin-bottom: 1rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.memory-title {\n font-size: 1.1rem;\n font-weight: 500;\n color: #374151;\n margin-bottom: 0.5rem;\n}\n\n.memory-value {\n font-size: 1.5rem;\n font-weight: 600;\n color: #3b82f6;\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n #controls {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n\n .column-1, .column-2 {\n padding: 0;\n }\n}\n\n/* Hover states and transitions */\ninput:hover, select:hover {\n border-color: #3b82f6;\n}\n\ninput:focus, select:focus {\n border-color: #2563eb;\n outline: none;\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);\n}\n\n/* Add smooth transitions */\ninput, select, button {\n transition: all 0.15s ease;\n}\n\n/* Preset dropdown special styling */\nselect[name=\"presets\"] {\n background-color: #f3f4f6;\n font-weight: 500;\n}\n\n/* Memory graph enhancements */\n.activation-memory {\n background: #dbeafe;\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 1rem;\n}\n\n.gradient-memory {\n background: #ede9fe;\n padding: 1rem;\n border-radius: 8px;\n}\n\n.order-button-second {\n background: linear-gradient(135deg, #6DB4C4, #D4A5B8);\n color: white;\n font-size: 18px;\n font-weight: 600;\n padding: 20px 20px;\n border: none;\n border-radius: 12px;\n cursor: pointer;\n text-transform: uppercase;\n letter-spacing: 1px;\n box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n }\n.order-button-second:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);\n}\n\n.order-button:active {\n transform: translateY(0);\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);\n}\n\n.order-button-second::before {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0));\n transition: left 0.5s ease;\n}\n\n.order-button-second:hover::before {\n left: 100%;\n}\n\n.order-button {\n background: linear-gradient(135deg, #6DB4C4, #D4A5B8);\n color: white;\n font-size: 18px;\n font-weight: 600;\n padding: 16px 32px;\n border: none;\n border-radius: 12px;\n cursor: pointer;\n text-transform: uppercase;\n letter-spacing: 1px;\n box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n }\n\n.order-button:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);\n}\n\n.order-button:active {\n transform: translateY(0);\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);\n}\n\n.order-button::before {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0));\n transition: left 0.5s ease;\n}\n\n.order-button:hover::before {\n left: 100%;\n}\n.order-button-container-second {\n /* display: flex; */\n justify-content: center;\n margin: 0px 0;\n}\n\n.order-button-container {\n display: flex;\n justify-content: center;\n margin: 0px 0 40px 0;\n}\n\nd-article img {\n width: 100%!important;\n}\n\n\niframe, .js-plotly-plot {\n width: 100%!important;\n margin-bottom: 20px;\n}\n\n.modebar-container {\n display: none;\n}\n\n#graph-container {\n display: grid; grid-template-columns: 1fr 1fr; align-items: center;\n}\n\n@media (max-width: 768px) {\n #graph-container {\n grid-template-columns: 1fr;\n }\n}\n\n@media (max-width: 1024px) {\n #graph-container {\n grid-template-columns: 1fr;\n }\n #graph-all {\n margin-right: 0px;\n }\n #controls {\n margin-left: 0px;\n }\n}\n\n.main-plot-container svg {\n background: transparent !important;\n}\n\n.large-image-background-transparent {\n margin-left: 0px;\n margin-right: 0px;\n}\n\n/* Import transformers-specific styles */\n@import url('./transformers-custom.css');"],"sourceRoot":""}]);
889
  // Exports
890
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
891
 
 
1973
  /* harmony default export */ const src_style = (style/* default */.A && style/* default */.A.locals ? style/* default */.A.locals : undefined);
1974
 
1975
  ;// ./src/index.js
1976
+ // Main JavaScript file for Scaling Insanity
1977
 
1978
 
1979
  // Import any additional functionality
1980
+ console.log('Scaling Insanity loaded');
1981
 
1982
  // Add any custom JavaScript functionality here
1983
  document.addEventListener('DOMContentLoaded', function () {
dist/main.bundle.js.map CHANGED
The diff for this file is too large to render. See raw diff
 
dist/style.css CHANGED
@@ -1,4 +1,4 @@
1
- /* style.css - Transformers Playthrough */
2
 
3
  /* Import ultrascale-playbook base styles and add transformers-specific styling */
4
  /* Define colors */
 
1
+ /* style.css - Scaling Insanity */
2
 
3
  /* Import ultrascale-playbook base styles and add transformers-specific styling */
4
  /* Define colors */
src/fragments/tp-plan.html CHANGED
@@ -1,27 +1,24 @@
 
 
 
 
 
 
 
 
 
 
1
 
2
- <pre><code class="language-python"># In the model's config (example: ERNIE 4.5-style decoder blocks)
3
- base_model_tp_plan = {
4
- "layers.*.self_attn.q_proj": "colwise",
5
- "layers.*.self_attn.k_proj": "colwise",
6
- "layers.*.self_attn.v_proj": "colwise",
7
- "layers.*.self_attn.o_proj": "rowwise",
8
- "layers.*.mlp.gate_proj": "colwise",
9
- "layers.*.mlp.up_proj": "colwise",
10
- "layers.*.mlp.down_proj": "rowwise",
11
- }
12
-
13
- # Runtime
14
- import torch
15
- from transformers import AutoModelForCausalLM, AutoTokenizer
16
-
17
- model_id = "your/model-or-local-checkpoint"
18
- model = AutoModelForCausalLM.from_pretrained(
19
- model_id,
20
- dtype=torch.bfloat16,
21
- tp_plan=base_model_tp_plan, # <-- plan defined above
22
- )
23
- tok = AutoTokenizer.from_pretrained(model_id)
24
- inputs = tok("Hello", return_tensors="pt").to(model.device)
25
- out = model(**inputs)</code></pre>
26
 
27
-
 
 
 
 
 
 
 
 
 
1
+ <pre><code class="language-python"># In the model's config (example: ERNIE 4.5-style decoder blocks)
2
+ base_model_tp_plan = {
3
+ "layers.*.self_attn.q_proj": "colwise",
4
+ "layers.*.self_attn.k_proj": "colwise",
5
+ "layers.*.self_attn.v_proj": "colwise",
6
+ "layers.*.self_attn.o_proj": "rowwise",
7
+ "layers.*.mlp.gate_proj": "colwise",
8
+ "layers.*.mlp.up_proj": "colwise",
9
+ "layers.*.mlp.down_proj": "rowwise",
10
+ }
11
 
12
+ # Runtime
13
+ import torch
14
+ from transformers import AutoModelForCausalLM, AutoTokenizer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ model_id = "your/model-or-local-checkpoint"
17
+ model = AutoModelForCausalLM.from_pretrained(
18
+ model_id,
19
+ dtype=torch.bfloat16,
20
+ tp_plan=base_model_tp_plan, # <-- plan defined above
21
+ )
22
+ tok = AutoTokenizer.from_pretrained(model_id)
23
+ inputs = tok("Hello", return_tensors="pt").to(model.device)
24
+ out = model(**inputs)</code></pre>
src/fragments/warmup_demo.html CHANGED
@@ -1,247 +1,240 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <style>
7
- body {
8
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
9
- margin: 0;
10
- padding: 20px;
11
- background-color: #f5f5f5;
12
- }
13
-
14
- .container {
15
- max-width: 1200px;
16
- margin: 0 auto;
17
- background: white;
18
- border-radius: 12px;
19
- padding: 30px;
20
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
21
- }
22
-
23
- h1 {
24
- text-align: center;
25
- color: #333;
26
- margin-bottom: 10px;
27
- }
28
-
29
- .subtitle {
30
- text-align: center;
31
- color: #666;
32
- margin-bottom: 30px;
33
- font-size: 16px;
34
- }
35
-
36
- .demo-container {
37
- display: flex;
38
- gap: 40px;
39
- margin-bottom: 30px;
40
- }
41
-
42
- .side {
43
- flex: 1;
44
- border: 2px solid #ddd;
45
- border-radius: 8px;
46
- padding: 20px;
47
- background: #fafafa;
48
- }
49
-
50
- .side h2 {
51
- text-align: center;
52
- margin-top: 0;
53
- color: #333;
54
- }
55
-
56
- .no-warmup h2 {
57
- color: #d63384;
58
- }
59
-
60
- .with-warmup h2 {
61
- color: #198754;
62
- }
63
-
64
- .memory-area {
65
- height: 400px;
66
- border: 2px dashed #ccc;
67
- border-radius: 6px;
68
- padding: 10px;
69
- margin: 20px 0;
70
- background: #fff;
71
- position: relative;
72
- overflow: hidden;
73
- }
74
-
75
- .layer-box {
76
- width: 80px;
77
- height: 30px;
78
- border: 2px solid #666;
79
- border-radius: 4px;
80
- margin: 3px;
81
- display: inline-block;
82
- position: relative;
83
- background: #fff;
84
- transition: all 0.3s ease;
85
- }
86
-
87
- .layer-box.allocating {
88
- background: #e9ecef;
89
- border-color: #adb5bd;
90
- }
91
-
92
- .layer-box.allocating::after {
93
- content: "malloc";
94
- position: absolute;
95
- top: 50%;
96
- left: 50%;
97
- transform: translate(-50%, -50%);
98
- font-size: 10px;
99
- color: #666;
100
- font-weight: bold;
101
- }
102
-
103
- .layer-box.loaded {
104
- background: #d1e7dd;
105
- border-color: #198754;
106
- }
107
-
108
- .layer-box.loaded::after {
109
- content: "data";
110
- position: absolute;
111
- top: 50%;
112
- left: 50%;
113
- transform: translate(-50%, -50%);
114
- font-size: 10px;
115
- color: #198754;
116
- font-weight: bold;
117
- }
118
-
119
- .warmup-container {
120
- width: 100%;
121
- height: 60px;
122
- border: 3px solid #666;
123
- border-radius: 6px;
124
- margin-bottom: 20px;
125
- background: #fff;
126
- position: relative;
127
- overflow: hidden;
128
- }
129
-
130
- .warmup-container.allocated {
131
- border-color: #0d6efd;
132
- background: #e7f1ff;
133
- }
134
-
135
- .warmup-container::before {
136
- content: "Pre-allocated Memory Pool";
137
- position: absolute;
138
- top: 50%;
139
- left: 50%;
140
- transform: translate(-50%, -50%);
141
- font-size: 14px;
142
- color: #666;
143
- font-weight: bold;
144
- z-index: 1;
145
- }
146
-
147
- .warmup-container.allocated::before {
148
- color: #0d6efd;
149
- }
150
-
151
- .warmup-fill {
152
- height: 100%;
153
- background: linear-gradient(90deg, #198754, #20c997);
154
- width: 0%;
155
- transition: width 0.5s ease;
156
- border-radius: 3px;
157
- position: relative;
158
- z-index: 2;
159
- }
160
-
161
- .warmup-fill::after {
162
- content: "Layer Data Loading";
163
- position: absolute;
164
- top: 50%;
165
- left: 50%;
166
- transform: translate(-50%, -50%);
167
- font-size: 12px;
168
- color: white;
169
- font-weight: bold;
170
- white-space: nowrap;
171
- }
172
-
173
- .timing {
174
- text-align: center;
175
- font-size: 24px;
176
- font-weight: bold;
177
- margin: 15px 0;
178
- min-height: 30px;
179
- }
180
-
181
- .no-warmup .timing {
182
- color: #d63384;
183
- }
184
-
185
- .with-warmup .timing {
186
- color: #198754;
187
- }
188
-
189
- .controls {
190
- text-align: center;
191
- margin: 30px 0;
192
- }
193
-
194
- .btn {
195
- background: #0d6efd;
196
- color: white;
197
- border: none;
198
- padding: 12px 24px;
199
- border-radius: 6px;
200
- font-size: 16px;
201
- cursor: pointer;
202
- margin: 0 10px;
203
- transition: background 0.3s ease;
204
- }
205
-
206
- .btn:hover {
207
- background: #0b5ed7;
208
- }
209
-
210
- .btn:disabled {
211
- background: #6c757d;
212
- cursor: not-allowed;
213
- }
214
-
215
-
216
- .description {
217
- background: #f8f9fa;
218
- padding: 15px;
219
- border-radius: 6px;
220
- margin-top: 15px;
221
- font-size: 14px;
222
- line-height: 1.5;
223
- }
224
-
225
- .phase-indicator {
226
- font-size: 14px;
227
- color: #666;
228
- text-align: center;
229
- margin-top: 10px;
230
- min-height: 20px;
231
- }
232
-
233
- .layer-counter {
234
- text-align: center;
235
- font-size: 16px;
236
- color: #495057;
237
- margin: 10px 0;
238
- }
239
- </style>
240
- </head>
241
- <body>
242
  <div class="container">
243
- <h1>CUDA Caching Allocator Warmup Visualization</h1>
244
- <p class="subtitle">Demonstrating memory allocation patterns during model loading</p>
245
 
246
  <div class="controls">
247
  <button class="btn" id="startBtn" onclick="startDemo()">Start Animation</button>
@@ -285,137 +278,121 @@
285
  </div>
286
  </div>
287
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
 
289
- <script>
290
- let animationSpeed = 1 / 2.4; // Slower animation
291
- let isRunning = false;
292
- const totalLayers = 10;
293
-
294
- function startDemo() {
295
- if (isRunning) return;
296
- isRunning = true;
297
-
298
- document.getElementById('startBtn').disabled = true;
299
- document.getElementById('resetBtn').disabled = true;
300
-
301
- // Start both animations simultaneously
302
- Promise.all([
303
- animateNoWarmup(),
304
- animateWithWarmup()
305
- ]).then(() => {
306
- isRunning = false;
307
- document.getElementById('startBtn').disabled = false;
308
- document.getElementById('resetBtn').disabled = false;
309
- });
310
- }
311
-
312
- function resetDemo() {
313
- if (isRunning) return;
314
-
315
- // Clear containers
316
- document.getElementById('noWarmupArea').innerHTML = '';
317
- document.getElementById('warmupLayers').innerHTML = '';
318
- document.getElementById('warmupFill').style.width = '0%';
319
- document.getElementById('warmupContainer').classList.remove('allocated');
320
-
321
- // Reset timers
322
- document.getElementById('noWarmupTime').textContent = '0.00s';
323
- document.getElementById('warmupTime').textContent = '0.00s';
324
-
325
- // Reset counters
326
- document.getElementById('noWarmupCounter').textContent = 'Layers loaded: 0/10';
327
- document.getElementById('warmupCounter').textContent = 'Layers loaded: 0/10';
328
 
329
- // Reset phase indicators
330
- document.getElementById('noWarmupPhase').textContent = '';
331
- document.getElementById('warmupPhase').textContent = '';
332
  }
333
 
334
- async function animateNoWarmup() {
335
- const container = document.getElementById('noWarmupArea');
336
- const timeEl = document.getElementById('noWarmupTime');
337
- const counterEl = document.getElementById('noWarmupCounter');
338
- const phaseEl = document.getElementById('noWarmupPhase');
339
-
340
- let currentTime = 0;
341
- const baseDelay = 200 / animationSpeed; // Base delay between operations
342
-
343
- phaseEl.textContent = 'Loading model layers...';
344
-
345
- for (let i = 0; i < totalLayers; i++) {
346
- // Create layer box
347
- const layerBox = document.createElement('div');
348
- layerBox.className = 'layer-box';
349
- container.appendChild(layerBox);
350
-
351
- // Malloc phase (grey)
352
- await sleep(baseDelay * 0.3);
353
- layerBox.classList.add('allocating');
354
- currentTime += 0.08; // malloc overhead
355
- timeEl.textContent = currentTime.toFixed(2) + 's';
356
-
357
- // Data loading phase (green)
358
- await sleep(baseDelay * 0.7);
359
- layerBox.classList.remove('allocating');
360
- layerBox.classList.add('loaded');
361
- currentTime += 0.12; // data transfer time
362
- timeEl.textContent = currentTime.toFixed(2) + 's';
363
-
364
- // Update counter
365
- counterEl.textContent = `Layers loaded: ${i + 1}/${totalLayers}`;
366
- }
367
-
368
- phaseEl.textContent = 'Complete!';
369
- }
370
 
371
- async function animateWithWarmup() {
372
- const container = document.getElementById('warmupLayers');
373
- const timeEl = document.getElementById('warmupTime');
374
- const counterEl = document.getElementById('warmupCounter');
375
- const phaseEl = document.getElementById('warmupPhase');
376
- const warmupContainer = document.getElementById('warmupContainer');
377
- const warmupFill = document.getElementById('warmupFill');
378
-
379
- let currentTime = 0;
380
- const baseDelay = 200 / animationSpeed;
381
-
382
- // Warmup phase
383
- phaseEl.textContent = 'Warming up allocator...';
384
- await sleep(baseDelay * 2);
385
- warmupContainer.classList.add('allocated');
386
- currentTime += 0.3; // warmup overhead
387
- timeEl.textContent = currentTime.toFixed(2) + 's';
388
 
389
- phaseEl.textContent = 'Loading model layers...';
 
390
 
391
- // Load layers directly into pre-allocated memory
392
- for (let i = 0; i < totalLayers; i++) {
393
- // Create layer indicator (much smaller since no malloc)
394
- const layerBox = document.createElement('div');
395
- layerBox.className = 'layer-box loaded';
396
- layerBox.style.width = '40px';
397
- layerBox.style.height = '20px';
398
- container.appendChild(layerBox);
399
 
400
- // Update progress bar
401
- const progress = ((i + 1) / totalLayers) * 100;
402
- warmupFill.style.width = progress + '%';
403
 
404
- // Only data transfer time (no malloc overhead)
405
- await sleep(baseDelay * 0.5);
406
- currentTime += 0.08; // faster due to no malloc
407
- timeEl.textContent = currentTime.toFixed(2) + 's';
 
 
408
 
409
- // Update counter
410
- counterEl.textContent = `Layers loaded: ${i + 1}/${totalLayers}`;
411
- }
412
 
413
- phaseEl.textContent = 'Complete!';
414
- }
 
415
 
416
- function sleep(ms) {
417
- return new Promise(resolve => setTimeout(resolve, ms));
418
  }
419
- </script>
420
- </body>
421
- </html>
 
 
 
 
 
 
1
+ <style>
2
+ .warmup-demo body {
3
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
4
+ margin: 0;
5
+ padding: 20px;
6
+ background-color: #f5f5f5;
7
+ }
8
+
9
+ .warmup-demo .container {
10
+ max-width: 1200px;
11
+ margin: 0 auto;
12
+ background: white;
13
+ border-radius: 12px;
14
+ padding: 30px;
15
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
16
+ }
17
+
18
+ .warmup-demo h1 {
19
+ text-align: center;
20
+ color: #333;
21
+ margin-bottom: 10px;
22
+ }
23
+
24
+ .warmup-demo .subtitle {
25
+ text-align: center;
26
+ color: #666;
27
+ margin-bottom: 30px;
28
+ font-size: 16px;
29
+ }
30
+
31
+ .warmup-demo .demo-container {
32
+ display: flex;
33
+ gap: 40px;
34
+ margin-bottom: 30px;
35
+ }
36
+
37
+ .warmup-demo .side {
38
+ flex: 1;
39
+ border: 2px solid #ddd;
40
+ border-radius: 8px;
41
+ padding: 20px;
42
+ background: #fafafa;
43
+ }
44
+
45
+ .warmup-demo .side h2 {
46
+ text-align: center;
47
+ margin-top: 0;
48
+ color: #333;
49
+ }
50
+
51
+ .warmup-demo .no-warmup h2 {
52
+ color: #d63384;
53
+ }
54
+
55
+ .warmup-demo .with-warmup h2 {
56
+ color: #198754;
57
+ }
58
+
59
+ .warmup-demo .memory-area {
60
+ height: 400px;
61
+ border: 2px dashed #ccc;
62
+ border-radius: 6px;
63
+ padding: 10px;
64
+ margin: 20px 0;
65
+ background: #fff;
66
+ position: relative;
67
+ overflow: hidden;
68
+ }
69
+
70
+ .warmup-demo .layer-box {
71
+ width: 80px;
72
+ height: 30px;
73
+ border: 2px solid #666;
74
+ border-radius: 4px;
75
+ margin: 3px;
76
+ display: inline-block;
77
+ position: relative;
78
+ background: #fff;
79
+ transition: all 0.3s ease;
80
+ }
81
+
82
+ .warmup-demo .layer-box.allocating {
83
+ background: #e9ecef;
84
+ border-color: #adb5bd;
85
+ }
86
+
87
+ .warmup-demo .layer-box.allocating::after {
88
+ content: "malloc";
89
+ position: absolute;
90
+ top: 50%;
91
+ left: 50%;
92
+ transform: translate(-50%, -50%);
93
+ font-size: 10px;
94
+ color: #666;
95
+ font-weight: bold;
96
+ }
97
+
98
+ .warmup-demo .layer-box.loaded {
99
+ background: #d1e7dd;
100
+ border-color: #198754;
101
+ }
102
+
103
+ .warmup-demo .layer-box.loaded::after {
104
+ content: "data";
105
+ position: absolute;
106
+ top: 50%;
107
+ left: 50%;
108
+ transform: translate(-50%, -50%);
109
+ font-size: 10px;
110
+ color: #198754;
111
+ font-weight: bold;
112
+ }
113
+
114
+ .warmup-demo .warmup-container {
115
+ width: 100%;
116
+ height: 60px;
117
+ border: 3px solid #666;
118
+ border-radius: 6px;
119
+ margin-bottom: 20px;
120
+ background: #fff;
121
+ position: relative;
122
+ overflow: hidden;
123
+ }
124
+
125
+ .warmup-demo .warmup-container.allocated {
126
+ border-color: #0d6efd;
127
+ background: #e7f1ff;
128
+ }
129
+
130
+ .warmup-demo .warmup-container::before {
131
+ content: "Pre-allocated Memory Pool";
132
+ position: absolute;
133
+ top: 50%;
134
+ left: 50%;
135
+ transform: translate(-50%, -50%);
136
+ font-size: 14px;
137
+ color: #666;
138
+ font-weight: bold;
139
+ z-index: 1;
140
+ }
141
+
142
+ .warmup-demo .warmup-container.allocated::before {
143
+ color: #0d6efd;
144
+ }
145
+
146
+ .warmup-demo .warmup-fill {
147
+ height: 100%;
148
+ background: linear-gradient(90deg, #198754, #20c997);
149
+ width: 0%;
150
+ transition: width 0.5s ease;
151
+ border-radius: 3px;
152
+ position: relative;
153
+ z-index: 2;
154
+ }
155
+
156
+ .warmup-demo .warmup-fill::after {
157
+ content: "Layer Data Loading";
158
+ position: absolute;
159
+ top: 50%;
160
+ left: 50%;
161
+ transform: translate(-50%, -50%);
162
+ font-size: 12px;
163
+ color: white;
164
+ font-weight: bold;
165
+ white-space: nowrap;
166
+ }
167
+
168
+ .warmup-demo .timing {
169
+ text-align: center;
170
+ font-size: 24px;
171
+ font-weight: bold;
172
+ margin: 15px 0;
173
+ min-height: 30px;
174
+ }
175
+
176
+ .warmup-demo .no-warmup .timing {
177
+ color: #d63384;
178
+ }
179
+
180
+ .warmup-demo .with-warmup .timing {
181
+ color: #198754;
182
+ }
183
+
184
+ .warmup-demo .controls {
185
+ text-align: center;
186
+ margin: 30px 0;
187
+ }
188
+
189
+ .warmup-demo .btn {
190
+ background: #0d6efd;
191
+ color: white;
192
+ border: none;
193
+ padding: 12px 24px;
194
+ border-radius: 6px;
195
+ font-size: 16px;
196
+ cursor: pointer;
197
+ margin: 0 10px;
198
+ transition: background 0.3s ease;
199
+ }
200
+
201
+ .warmup-demo .btn:hover {
202
+ background: #0b5ed7;
203
+ }
204
+
205
+ .warmup-demo .btn:disabled {
206
+ background: #6c757d;
207
+ cursor: not-allowed;
208
+ }
209
+
210
+ .warmup-demo .description {
211
+ background: #f8f9fa;
212
+ padding: 15px;
213
+ border-radius: 6px;
214
+ margin-top: 15px;
215
+ font-size: 14px;
216
+ line-height: 1.5;
217
+ }
218
+
219
+ .warmup-demo .phase-indicator {
220
+ font-size: 14px;
221
+ color: #666;
222
+ text-align: center;
223
+ margin-top: 10px;
224
+ min-height: 20px;
225
+ }
226
+
227
+ .warmup-demo .layer-counter {
228
+ text-align: center;
229
+ font-size: 16px;
230
+ color: #495057;
231
+ margin: 10px 0;
232
+ }
233
+ </style>
234
+
235
+ <div class="warmup-demo">
 
 
 
 
 
 
236
  <div class="container">
237
+ <p class="subtitle">Mem allocation patterns during model loading</p>
 
238
 
239
  <div class="controls">
240
  <button class="btn" id="startBtn" onclick="startDemo()">Start Animation</button>
 
278
  </div>
279
  </div>
280
  </div>
281
+ </div>
282
+
283
+ <script>
284
+ let animationSpeed = 1 / 2.4;
285
+ let isRunning = false;
286
+ const totalLayers = 10;
287
+
288
+ function startDemo() {
289
+ if (isRunning) return;
290
+ isRunning = true;
291
+
292
+ document.getElementById('startBtn').disabled = true;
293
+ document.getElementById('resetBtn').disabled = true;
294
+
295
+ Promise.all([
296
+ animateNoWarmup(),
297
+ animateWithWarmup()
298
+ ]).then(() => {
299
+ isRunning = false;
300
+ document.getElementById('startBtn').disabled = false;
301
+ document.getElementById('resetBtn').disabled = false;
302
+ });
303
+ }
304
+
305
+ function resetDemo() {
306
+ if (isRunning) return;
307
+
308
+ document.getElementById('noWarmupArea').innerHTML = '';
309
+ document.getElementById('warmupLayers').innerHTML = '';
310
+ document.getElementById('warmupFill').style.width = '0%';
311
+ document.getElementById('warmupContainer').classList.remove('allocated');
312
+
313
+ document.getElementById('noWarmupTime').textContent = '0.00s';
314
+ document.getElementById('warmupTime').textContent = '0.00s';
315
+
316
+ document.getElementById('noWarmupCounter').textContent = 'Layers loaded: 0/10';
317
+ document.getElementById('warmupCounter').textContent = 'Layers loaded: 0/10';
318
+
319
+ document.getElementById('noWarmupPhase').textContent = '';
320
+ document.getElementById('warmupPhase').textContent = '';
321
+ }
322
+
323
+ async function animateNoWarmup() {
324
+ const container = document.getElementById('noWarmupArea');
325
+ const timeEl = document.getElementById('noWarmupTime');
326
+ const counterEl = document.getElementById('noWarmupCounter');
327
+ const phaseEl = document.getElementById('noWarmupPhase');
328
+
329
+ let currentTime = 0;
330
+ const baseDelay = 200 / animationSpeed;
331
+
332
+ phaseEl.textContent = 'Loading model layers...';
333
+
334
+ for (let i = 0; i < totalLayers; i++) {
335
+ const layerBox = document.createElement('div');
336
+ layerBox.className = 'layer-box';
337
+ container.appendChild(layerBox);
338
+
339
+ await sleep(baseDelay * 0.3);
340
+ layerBox.classList.add('allocating');
341
+ currentTime += 0.08;
342
+ timeEl.textContent = currentTime.toFixed(2) + 's';
343
 
344
+ await sleep(baseDelay * 0.7);
345
+ layerBox.classList.remove('allocating');
346
+ layerBox.classList.add('loaded');
347
+ currentTime += 0.12;
348
+ timeEl.textContent = currentTime.toFixed(2) + 's';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
349
 
350
+ counterEl.textContent = `Layers loaded: ${i + 1}/${totalLayers}`;
 
 
351
  }
352
 
353
+ phaseEl.textContent = 'Complete!';
354
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355
 
356
+ async function animateWithWarmup() {
357
+ const container = document.getElementById('warmupLayers');
358
+ const timeEl = document.getElementById('warmupTime');
359
+ const counterEl = document.getElementById('warmupCounter');
360
+ const phaseEl = document.getElementById('warmupPhase');
361
+ const warmupContainer = document.getElementById('warmupContainer');
362
+ const warmupFill = document.getElementById('warmupFill');
 
 
 
 
 
 
 
 
 
 
363
 
364
+ let currentTime = 0;
365
+ const baseDelay = 200 / animationSpeed;
366
 
367
+ phaseEl.textContent = 'Warming up allocator...';
368
+ await sleep(baseDelay * 2);
369
+ warmupContainer.classList.add('allocated');
370
+ currentTime += 0.3;
371
+ timeEl.textContent = currentTime.toFixed(2) + 's';
 
 
 
372
 
373
+ phaseEl.textContent = 'Loading model layers...';
 
 
374
 
375
+ for (let i = 0; i < totalLayers; i++) {
376
+ const layerBox = document.createElement('div');
377
+ layerBox.className = 'layer-box loaded';
378
+ layerBox.style.width = '40px';
379
+ layerBox.style.height = '20px';
380
+ container.appendChild(layerBox);
381
 
382
+ const progress = ((i + 1) / totalLayers) * 100;
383
+ warmupFill.style.width = progress + '%';
 
384
 
385
+ await sleep(baseDelay * 0.5);
386
+ currentTime += 0.08;
387
+ timeEl.textContent = currentTime.toFixed(2) + 's';
388
 
389
+ counterEl.textContent = `Layers loaded: ${i + 1}/${totalLayers}`;
 
390
  }
391
+
392
+ phaseEl.textContent = 'Complete!';
393
+ }
394
+
395
+ function sleep(ms) {
396
+ return new Promise(resolve => setTimeout(resolve, ms));
397
+ }
398
+ </script>
webpack.config.js CHANGED
@@ -31,11 +31,19 @@ const loadFragmentsMap = (() => {
31
  const dottedPath = 'fragment-' + nameWithoutExt.replace(/\\/g, '-').replace(/\//g, '-').replace(/\./g, '-');
32
  const content = fs.readFileSync(filePath, "utf8");
33
  // Minify the HTML content using swcMinifyFragment
34
- const minifiedRes = await HtmlMinimizerPlugin.swcMinifyFragment({"tmp.html": content})
35
- if (minifiedRes.errors) {
36
- console.error(minifiedRes.errors)
 
 
 
 
 
 
 
 
 
37
  }
38
- const minifiedContent = minifiedRes.code;
39
  cachedFragments[dottedPath] = minifiedContent;
40
  }
41
  }));
@@ -325,10 +333,6 @@ module.exports = {
325
  }
326
  ]
327
  }),
328
- new HtmlMinimizerPlugin({
329
- test: /fragments\/.*\.html$/i,
330
- minify: HtmlMinimizerPlugin.swcMinifyFragment,
331
- })
332
  ]
333
  },
334
  };
 
31
  const dottedPath = 'fragment-' + nameWithoutExt.replace(/\\/g, '-').replace(/\//g, '-').replace(/\./g, '-');
32
  const content = fs.readFileSync(filePath, "utf8");
33
  // Minify the HTML content using swcMinifyFragment
34
+ let minifiedContent;
35
+ try {
36
+ const minifiedRes = await HtmlMinimizerPlugin.swcMinifyFragment({"tmp.html": content})
37
+ if (minifiedRes.errors) {
38
+ console.warn("HTML minification warnings:", minifiedRes.errors);
39
+ minifiedContent = content; // Use original content if errors
40
+ } else {
41
+ minifiedContent = minifiedRes.code;
42
+ }
43
+ } catch (error) {
44
+ console.warn(`Failed to minify fragment ${filePath}, using original content:`, error.message);
45
+ minifiedContent = content; // Fallback to original content
46
  }
 
47
  cachedFragments[dottedPath] = minifiedContent;
48
  }
49
  }));
 
333
  }
334
  ]
335
  }),
 
 
 
 
336
  ]
337
  },
338
  };