Paar, F. (Ferdinand) commited on
Commit
38be7c4
·
1 Parent(s): 71654ae

final run2

Browse files
Files changed (1) hide show
  1. frontend/index.html +281 -139
frontend/index.html CHANGED
@@ -6,165 +6,111 @@
6
  <title>DeepGaze</title>
7
  <link rel="stylesheet" href="static/styles.css" />
8
  <script src="https://d3js.org/d3.v6.min.js"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  </head>
10
  <body>
11
- <!-- A header spanning the full width -->
12
  <header>
13
  <h1>DeepGaze</h1>
14
  </header>
15
-
16
- <!-- Main container that splits the page into a left main (75%) and right aside (25%) -->
17
  <div class="container">
18
  <main>
19
  <!-- About Attention Section -->
20
  <section class="about-section">
21
  <h2>About Attention</h2>
22
  <p>
23
- Transformer networks are built from multiple layers, and each layer is divided into several attention heads.
24
- Each head computes its own attention matrix by combining "queries" and "keys"—the fundamental elements that
25
- help the network decide how much focus to give to different parts of the input.
26
  </p>
27
  <p>
28
- You can think of each query as a question that a token asks, such as "Are there adjectives in front of me?"
29
- Meanwhile, each key serves as a potential answer, carrying the token's characteristics. When the model compares
30
- queries with keys, it determines the strength of their match and, therefore, how much influence one token should
31
  have on another.
32
  </p>
33
  <p>
34
- For example, consider the phrase "fluffy blue monster." One token might generate a query like, "Is the word in
35
- front of me an adjective?" In this case, the tokens "fluffy" and "blue"—which are adjectives—provide keys that
36
- answer this question strongly, while "monster," being a noun, offers a weaker response. This interplay of
37
- questions (queries) and answers (keys) is what creates the attention matrix for each head.
38
  </p>
39
  <p>
40
- Each attention head focuses on different relationships and patterns within the text, allowing the network to
41
- capture a rich and nuanced understanding of the language. Despite the critical role that these attention mechanisms
42
- play, it's interesting to note that only about one third of all the weights in a large language model are actually
43
- in the attention blocks. So while the famous slogan "attention is all you need" highlights the importance of these
44
- connections, in terms of sheer weight, it's only one third of what you really need!
45
- </p>
46
- <p>
47
- In summary, transformer models use multiple layers with several attention heads per layer to build complex
48
- relationships between tokens. Each head creates an attention matrix by matching queries (questions) to keys
49
- (answers), as seen in our "fluffy blue monster" example. Even though attention is crucial for the model's performance,
50
- remember that it only accounts for roughly one third of the model’s overall weights.
51
  </p>
52
  </section>
53
-
54
  <!-- Deep Gaze into Attention Heads Section -->
55
  <section class="deep-gaze-section">
56
  <h2>A Deep Gaze into Attention Heads</h2>
57
- <p>Click on the head that looks interesting gaze deeper into it in the next section</p>
58
- <!-- Text Input & Process Button -->
59
- <form id="textForm" class="text-form">
60
- <textarea
61
- id="inputText"
62
- rows="2"x
63
- cols="50"
64
- placeholder="Enter your text here..."
65
- autofocus
66
- ></textarea>
67
- <button type="submit">Process</button>
68
- </form>
69
- <style>
70
- .text-form button {
71
- background-color: #800000; /* Bordo red */
72
- color: #fff; /* White text */
73
- border: none;
74
- padding: 8px 12px;
75
- font-size: 14px;
76
- border-radius: 4px;
77
- cursor: pointer;
78
- }
79
- </style>
80
- <html lang="en">
81
- <head>
82
- <meta charset="UTF-8" />
83
- <title>Head & Layer Display</title>
84
- <style>
85
- .info-container {
86
- display: flex;
87
- align-items: center;
88
- margin: 5px 0;
89
- font-size: 0.9rem; /* smaller text */
90
- }
91
- .info-container .label {
92
- margin-right: 5px;
93
- }
94
- .info-container .number-box {
95
- border: 1px solid #800000; /* bordo red */
96
- border-radius: 4px;
97
- padding: 2px 6px;
98
- font-weight: bold;
99
- color: #800000;
100
- min-width: 20px;
101
- text-align: center;
102
- }
103
- </style>
104
- </head>
105
- <body>
106
- <div id="head" class="info-container">
107
- <span class="label">Head:</span>
108
- <span class="number-box">3</span>
109
- </div>
110
- <div id="layer" class="info-container">
111
- <span class="label">Layer:</span>
112
- <span class="number-box">5</span>
113
- </div>
114
- </body>
115
- </html>
116
- <!-- Layer/Head Selection -->
117
- <!-- <form id="headSelection" class="selection-form">
118
- <label for="layers">Choose a layer:</label>
119
- <select name="layers" id="layers">
120
- <option value="1">1</option>
121
- <option value="2">2</option>
122
- <option value="3">3</option>
123
- <option value="4">4</option>
124
- <option value="5">5</option>
125
- <option value="6">6</option>
126
- <option value="7">7</option>
127
- <option value="8">8</option>
128
- <option value="9">9</option>
129
- <option value="10">10</option>
130
- <option value="11">11</option>
131
- <option value="12">12</option>
132
- </select>
133
-
134
- <label for="heads">Choose a head:</label>
135
- <select name="heads" id="heads">
136
- <option value="1">1</option>
137
- <option value="2">2</option>
138
- <option value="3">3</option>
139
- <option value="4">4</option>
140
- <option value="5">5</option>
141
- <option value="6">6</option>
142
- <option value="7">7</option>
143
- <option value="8">8</option>
144
- <option value="9">9</option>
145
- <option value="10">10</option>
146
- <option value="11">11</option>
147
- <option value="12">12</option>
148
- </select>
149
- </form> -->
150
-
151
-
152
-
153
- <!-- Output Area -->
154
-
155
  </section>
 
 
156
  <section class="model_view">
157
  <div id="model_view_container">
158
- <p></p>
159
- </div>
160
- <div id="layer">
161
- <p></p>
162
  </div>
163
- <div id="head">
164
- <p></p>
 
 
 
 
 
 
 
 
165
  </div>
166
-
167
  </section>
 
 
168
  <section class="hover-visualization">
169
  <h2>Hover Visualization</h2>
170
  <p>
@@ -172,15 +118,211 @@
172
  to see the attention weights for that token across all heads.
173
  </p>
174
  <div id="tokenContainer"></div>
175
-
176
  </section>
 
 
 
 
 
 
177
  </main>
178
-
179
- <!-- Right side (25%) to be used for footnotes or left empty -->
180
- <aside>
181
- Test
182
- </aside>
183
  </div>
184
-
185
- <script src="static/script.js?v=20265"</script></script>
186
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  <title>DeepGaze</title>
7
  <link rel="stylesheet" href="static/styles.css" />
8
  <script src="https://d3js.org/d3.v6.min.js"></script>
9
+ <style>
10
+ /* Process button styling */
11
+ .text-form button {
12
+ background-color: #800000; /* Bordo red */
13
+ color: #fff;
14
+ border: none;
15
+ padding: 8px 12px;
16
+ font-size: 14px;
17
+ border-radius: 4px;
18
+ cursor: pointer;
19
+ }
20
+ /* Info container styling for head and layer display */
21
+ .info-container {
22
+ display: flex;
23
+ align-items: center;
24
+ margin: 5px 0;
25
+ font-size: 0.9rem;
26
+ }
27
+ .info-container .label {
28
+ margin-right: 5px;
29
+ }
30
+ .info-container .number-box {
31
+ border: 1px solid #800000;
32
+ border-radius: 4px;
33
+ padding: 2px 6px;
34
+ font-weight: bold;
35
+ color: #800000;
36
+ min-width: 20px;
37
+ text-align: center;
38
+ }
39
+ </style>
40
  </head>
41
  <body>
42
+ <!-- Header -->
43
  <header>
44
  <h1>DeepGaze</h1>
45
  </header>
46
+ <!-- Main container -->
 
47
  <div class="container">
48
  <main>
49
  <!-- About Attention Section -->
50
  <section class="about-section">
51
  <h2>About Attention</h2>
52
  <p>
53
+ Transformer networks are built from multiple layers, and each layer is divided into several attention heads.
54
+ Each head computes its own attention matrix by combining "queries" and "keys"—the fundamental elements that help
55
+ the network decide how much focus to give to different parts of the input.
56
  </p>
57
  <p>
58
+ You can think of each query as a question that a token asks, such as "Are there adjectives in front of me?"
59
+ Meanwhile, each key serves as a potential answer, carrying the token's characteristics. When the model compares
60
+ queries with keys, it determines the strength of their match and, therefore, how much influence one token should
61
  have on another.
62
  </p>
63
  <p>
64
+ For example, consider the phrase "fluffy blue monster." One token might generate a query like, "Is the word in front
65
+ of me an adjective?" In this case, the tokens "fluffy" and "blue"—which are adjectives—provide keys that answer this
66
+ question strongly, while "monster," being a noun, offers a weaker response. This interplay of questions (queries)
67
+ and answers (keys) is what creates the attention matrix for each head.
68
  </p>
69
  <p>
70
+ Each attention head focuses on different relationships and patterns within the text, allowing the network to capture
71
+ a rich and nuanced understanding of the language. Despite the critical role that these attention mechanisms play,
72
+ it's interesting to note that only about one third of all the weights in a large language model are actually in the
73
+ attention blocks. So while the famous slogan "attention is all you need" highlights the importance of these connections,
74
+ in terms of sheer weight, it's only one third of what you really need!
 
 
 
 
 
 
75
  </p>
76
  </section>
77
+
78
  <!-- Deep Gaze into Attention Heads Section -->
79
  <section class="deep-gaze-section">
80
  <h2>A Deep Gaze into Attention Heads</h2>
81
+ <p>Click on a head that looks interesting to gaze deeper into it in the next section</p>
82
+ <!-- Text Input & Process Button -->
83
+ <form id="textForm" class="text-form">
84
+ <textarea
85
+ id="inputText"
86
+ rows="2"
87
+ cols="50"
88
+ placeholder="Enter your text here..."
89
+ autofocus
90
+ ></textarea>
91
+ <button type="submit">Process</button>
92
+ </form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  </section>
94
+
95
+ <!-- Model View Section -->
96
  <section class="model_view">
97
  <div id="model_view_container">
98
+ <!-- Thumbnails of attention heads will be rendered here -->
 
 
 
99
  </div>
100
+ <!-- Display for selected head and layer -->
101
+ <div id="display_info">
102
+ <div id="display_head" class="info-container">
103
+ <span class="label">Head:</span>
104
+ <span class="number-box">-</span>
105
+ </div>
106
+ <div id="display_layer" class="info-container">
107
+ <span class="label">Layer:</span>
108
+ <span class="number-box">-</span>
109
+ </div>
110
  </div>
 
111
  </section>
112
+
113
+ <!-- Hover Visualization Section -->
114
  <section class="hover-visualization">
115
  <h2>Hover Visualization</h2>
116
  <p>
 
118
  to see the attention weights for that token across all heads.
119
  </p>
120
  <div id="tokenContainer"></div>
 
121
  </section>
122
+
123
+ <!-- Output area (for debugging) -->
124
+ <section id="outputSection">
125
+ <div id="output"></div>
126
+ </section>
127
+
128
  </main>
129
+ <!-- (Optional aside can be added here) -->
 
 
 
 
130
  </div>
131
+
132
+ <!-- Script -->
133
+ <script>
134
+ // Global variable to store fetched data
135
+ let currentData = null;
136
+
137
+ // Form submit handler
138
+ document.getElementById('textForm').addEventListener('submit', async (e) => {
139
+ e.preventDefault();
140
+ const inputText = document.getElementById('inputText').value;
141
+
142
+ try {
143
+ const response = await fetch('/process', {
144
+ method: 'POST',
145
+ headers: { 'Content-Type': 'application/json' },
146
+ body: JSON.stringify({ text: inputText })
147
+ });
148
+
149
+ if (!response.ok) {
150
+ throw new Error('Network response was not ok');
151
+ }
152
+ const data = await response.json();
153
+ currentData = data; // Store globally for use in click handlers
154
+
155
+ // Use data.tokens and data.attention from your POST response
156
+ displayOutput(data);
157
+ displayHoverTokens(data, 0, 0);
158
+ renderModelView(data.tokens, data.attention);
159
+ } catch (error) {
160
+ console.error('Error:', error);
161
+ document.getElementById('output').innerText = 'Error processing text.';
162
+ }
163
+ });
164
+
165
+ function renderModelView(tokens, attention) {
166
+ const container = document.getElementById("model_view_container");
167
+ if (!container) return;
168
+ container.innerHTML = "";
169
+
170
+ const gridContainer = document.createElement("div");
171
+ gridContainer.style.display = "grid";
172
+ gridContainer.style.gridTemplateColumns = "repeat(12, 120px)";
173
+ gridContainer.style.gridGap = "10px";
174
+ gridContainer.style.padding = "20px";
175
+
176
+ // Loop over all 12 layers and 12 heads
177
+ for (let layerIdx = 0; layerIdx < 12; layerIdx++) {
178
+ for (let headIdx = 0; headIdx < 12; headIdx++) {
179
+ const thumbnail = createAttentionThumbnail(tokens, attention, layerIdx, headIdx);
180
+ gridContainer.appendChild(thumbnail);
181
+ }
182
+ }
183
+
184
+ container.appendChild(gridContainer);
185
+ }
186
+
187
+ function createAttentionThumbnail(tokens, attention, layerIdx, headIdx) {
188
+ const padding = 20;
189
+ const tokenHeight = 20;
190
+ const width = 120;
191
+ // Compute the thumbnail height dynamically based on the number of tokens.
192
+ const height = padding * 2 + tokens.length * tokenHeight;
193
+ const maxLineWidth = 4;
194
+ const maxOpacity = 0.8;
195
+
196
+ // Compute the right-side x-coordinate numerically.
197
+ const xRight = width - padding;
198
+
199
+ // Create a thumbnail container using D3.
200
+ const thumbnail = d3.select(document.createElement("div"))
201
+ .style("position", "relative")
202
+ .style("height", height + "px")
203
+ .style("width", width + "px")
204
+ .style("border", "1px solid #ddd")
205
+ .style("border-radius", "4px")
206
+ .style("padding", "5px")
207
+ .style("background", "#fff");
208
+
209
+ // Append an SVG container with fixed dimensions.
210
+ const svg = thumbnail.append("svg")
211
+ .attr("width", width)
212
+ .attr("height", height);
213
+
214
+ // Add header text (e.g., "L4 H4") to show the layer and head number.
215
+ svg.append("text")
216
+ .attr("x", width / 2)
217
+ .attr("y", 15)
218
+ .attr("text-anchor", "middle")
219
+ .attr("font-size", "10")
220
+ .text(`L${layerIdx + 1} H${headIdx + 1}`);
221
+
222
+ // (Removed drawing token text to keep the view clean.)
223
+
224
+ // Draw attention lines with per-row normalization.
225
+ attention[layerIdx][headIdx].forEach((sourceWeights, sourceIdx) => {
226
+ const rowMax = Math.max(...sourceWeights) || 1;
227
+ sourceWeights.forEach((weight, targetIdx) => {
228
+ if (weight > 0.01 && sourceIdx !== targetIdx) {
229
+ const normalizedWeight = weight / rowMax;
230
+ svg.append("line")
231
+ .attr("x1", padding)
232
+ .attr("y1", padding + sourceIdx * tokenHeight - 5)
233
+ .attr("x2", xRight)
234
+ .attr("y2", padding + targetIdx * tokenHeight - 5)
235
+ .attr("stroke", "#800000") // Bordo red
236
+ .attr("stroke-width", Math.max(0.5, normalizedWeight * maxLineWidth))
237
+ .attr("opacity", Math.min(maxOpacity, normalizedWeight * 2))
238
+ .attr("stroke-linecap", "round");
239
+ }
240
+ });
241
+ });
242
+
243
+ // Click handler: update the head and layer display.
244
+ thumbnail.on("click", function() {
245
+ d3.select("#display_head .number-box").text(headIdx + 1);
246
+ d3.select("#display_layer .number-box").text(layerIdx + 1);
247
+ displayHoverTokens(currentData, layerIdx, headIdx);
248
+ });
249
+
250
+ return thumbnail.node();
251
+ }
252
+
253
+ // Function to display raw tokens and attention data for debugging.
254
+ function displayOutput(data) {
255
+ const outputDiv = document.getElementById('output');
256
+ outputDiv.innerHTML = `
257
+ <h2>Tokens</h2>
258
+ <pre>${JSON.stringify(data.tokens, null, 2)}</pre>
259
+ <h2>Attention</h2>
260
+ <pre>${JSON.stringify(data.attention, null, 2)}</pre>
261
+ `;
262
+ }
263
+
264
+ function renderTokens(tokens, attentionData, layer_idx, head_idx) {
265
+ const container = document.getElementById('tokenContainer');
266
+ container.innerHTML = "";
267
+
268
+ tokens.forEach((token, index) => {
269
+ const span = document.createElement('span');
270
+ span.textContent = token.replace("Ġ", "") + " ";
271
+ span.style.fontSize = "32px";
272
+ span.addEventListener('mouseenter', () => {
273
+ highlightAttention(index, attentionData, layer_idx, head_idx);
274
+ });
275
+ span.addEventListener('mouseleave', () => {
276
+ resetTokenSizes();
277
+ });
278
+ container.appendChild(span);
279
+ });
280
+ }
281
+
282
+ function displayHoverTokens(data, layer_idx, head_idx) {
283
+ let tokens, attentionMatrix;
284
+ if (!data.tokens || !data.attention) {
285
+ tokens = ['This', 'is', 'a', 'test', '.'];
286
+ attentionMatrix = Array(12)
287
+ .fill(null)
288
+ .map(() => Array(12).fill(null).map(() => Array(tokens.length).fill(0)));
289
+ } else {
290
+ tokens = data.tokens;
291
+ attentionMatrix = data.attention;
292
+ }
293
+ renderTokens(tokens, attentionMatrix, layer_idx, head_idx);
294
+ }
295
+
296
+ function resetTokenSizes() {
297
+ const container = document.getElementById("tokenContainer");
298
+ Array.from(container.children).forEach((span) => {
299
+ span.style.fontSize = "32px";
300
+ });
301
+ }
302
+
303
+ function highlightAttention(index, attentionData, layer_idx, head_idx) {
304
+ const container = document.getElementById('tokenContainer');
305
+ const row = attentionData[layer_idx][head_idx][index];
306
+ if (!row) {
307
+ console.warn(`No attention data for token index ${index}`);
308
+ return;
309
+ }
310
+
311
+ const weights = row.slice(0, index);
312
+ const maxWeight = Math.max(...attentionData[layer_idx][head_idx]) || 1;
313
+ const baseFontSize = 32;
314
+ const maxIncrease = 20;
315
+
316
+ Array.from(container.children).forEach((span, idx) => {
317
+ if (idx < index) {
318
+ const weight = weights[idx];
319
+ const newFontSize = baseFontSize + (weight / maxWeight) * maxIncrease;
320
+ span.style.fontSize = newFontSize + "px";
321
+ } else {
322
+ span.style.fontSize = baseFontSize + "px";
323
+ }
324
+ });
325
+ }
326
+ </script>
327
+ </body>
328
+ </html>