ghrua commited on
Commit
1286deb
·
1 Parent(s): cb7092d

update information

Browse files
Files changed (1) hide show
  1. templates/index.html +122 -103
templates/index.html CHANGED
@@ -3,107 +3,129 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Interactive Position Visualizer</title>
7
  <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <style>
10
- /* Custom floating message style */
11
  #floating-msg {
12
- transition: all 0.3s ease;
13
  opacity: 0;
14
  pointer-events: none;
15
  }
16
- #floating-msg.visible {
17
- opacity: 1;
 
 
 
 
18
  }
19
  </style>
20
  </head>
21
- <body class="bg-gray-50 text-gray-800 font-sans p-6">
22
 
23
- <div class="max-w-6xl mx-auto">
24
- <div class="flex justify-between items-center mb-6">
25
- <h1 class="text-3xl font-bold text-indigo-700">Model Context Visualizer</h1>
26
-
27
- <div id="queue-indicator" class="hidden bg-blue-100 text-blue-800 text-xs font-semibold px-3 py-1 rounded-full border border-blue-200 shadow-sm flex items-center gap-2">
28
- <span class="relative flex h-2 w-2">
29
- <span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
30
- <span class="relative inline-flex rounded-full h-2 w-2 bg-blue-500"></span>
31
- </span>
32
- <span id="queue-text">Queue: 0</span>
 
 
33
  </div>
34
- </div>
35
 
36
- <div id="truncation-warning" class="hidden mb-4 bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4" role="alert">
37
- <p class="font-bold">Notice</p>
38
- <p>Your input was truncated to the first 512 tokens to ensure performance.</p>
 
 
 
 
 
39
  </div>
40
 
41
- <div class="bg-white p-6 rounded-lg shadow-md mb-6 grid grid-cols-1 md:grid-cols-4 gap-4 items-end">
42
- <div class="md:col-span-2">
43
- <label class="block text-sm font-medium text-gray-700 mb-1">Input Context</label>
44
- <textarea id="sentenceInput" rows="3"
45
- class="w-full p-2 border border-gray-300 rounded focus:ring-2 focus:ring-indigo-500 outline-none resize-y"
46
- placeholder="Enter text...">Please revise the following tokens:
 
47
  Input: A B C D E F G
48
  Output: G F E D C B A
49
  </textarea>
50
- </div>
51
-
52
- <div>
53
- <label class="block text-sm font-medium text-gray-700 mb-1">Layer Index</label>
54
- <select id="layerSelect" class="w-full p-2 border border-gray-300 rounded bg-white">
55
- <option value="5">Layer 5</option>
56
- <option value="6">Layer 6</option>
57
- <option value="7">Layer 7</option>
58
- <option value="8">Layer 8</option>
59
- <option value="9">Layer 9</option>
60
- <option value="10">Layer 10</option>
61
- <option value="11">Layer 11</option>
62
- <option value="12">Layer 12</option>
63
- <option value="13">Layer 13</option>
64
- <option value="14">Layer 14</option>
65
- <option value="15">Layer 15</option>
66
- </select>
67
  </div>
68
 
69
- <div>
70
- <label class="block text-sm font-medium text-gray-700 mb-1">Attention Head</label>
71
- <select id="headSelect" class="w-full p-2 border border-gray-300 rounded bg-white">
72
- <option value="0">Head 0</option>
73
- <option value="1">Head 1</option>
74
- <option value="2">Head 2</option>
75
- <option value="3">Head 3</option>
76
- <option value="4">Head 4</option>
77
- <option value="5">Head 5</option>
78
- <option value="6">Head 6</option>
79
- <option value="7">Head 7</option>
80
- <option value="8">Head 8</option>
81
- <option value="9">Head 9</option>
82
- <option value="10">Head 10</option>
83
- <option value="11">Head 11</option>
84
- <option value="12">Head 12</option>
85
- <option value="13">Head 13</option>
86
- <option value="14">Head 14</option>
87
- <option value="15">Head 15</option>
88
- </select>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  </div>
90
 
91
- <button onclick="fetchData()" id="computeBtn" class="md:col-span-4 bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded transition shadow-sm flex justify-center items-center gap-2">
92
  <span>Compute & Visualize</span>
93
  </button>
94
  </div>
 
 
 
 
 
 
 
 
95
 
96
- <div class="relative bg-white p-2 rounded-lg shadow-lg border border-gray-100" style="min-height: 550px;">
97
- <button onclick="resetView()" class="absolute top-0 right-4 z-20 bg-gray-200 hover:bg-gray-300 text-gray-700 text-xs font-bold py-1 px-3 rounded border border-gray-300 transition">
98
- Reset Selection
99
  </button>
100
- <div id="chartDiv" style="width: 100%; height: 550px;"></div>
101
- <div id="floating-msg" class="absolute top-4 left-1/2 transform -translate-x-1/2 bg-gray-900 text-white px-6 py-4 rounded shadow-xl max-w-lg z-10 text-center">
102
- <p class="text-xs text-gray-400 uppercase tracking-wide mb-1">Local Context (i-k to i+k)</p>
103
- <p id="context-text" class="text-lg font-medium">Click a data point to see context...</p>
 
 
104
  </div>
105
  </div>
106
- </div>
107
 
108
  <script>
109
  let currentData = [];
@@ -111,11 +133,14 @@ Output: G F E D C B A
111
 
112
  document.addEventListener('DOMContentLoaded', () => {
113
  fetchData();
114
- // Start polling the queue status
115
  setInterval(updateQueueStatus, 2000);
 
 
 
 
 
116
  });
117
 
118
- // --- NEW: QUEUE STATUS POLLER ---
119
  async function updateQueueStatus() {
120
  try {
121
  const res = await fetch('/queue_status');
@@ -125,10 +150,9 @@ Output: G F E D C B A
125
  const el = document.getElementById('queue-indicator');
126
  const txt = document.getElementById('queue-text');
127
 
128
- // Show if there is a queue
129
  if (count > 0) {
130
  el.classList.remove('hidden');
131
- txt.innerText = `Waitlist: ${count} users`;
132
  } else {
133
  el.classList.add('hidden');
134
  }
@@ -142,14 +166,11 @@ Output: G F E D C B A
142
  const head = document.getElementById('headSelect').value;
143
  const btn = document.getElementById('computeBtn');
144
  const btnText = btn.querySelector('span');
145
-
146
- // Save original text
147
  const originalText = "Compute & Visualize";
148
 
149
- // Set loading state
150
- btnText.innerText = "Processing (Queued)...";
151
  btn.disabled = true;
152
- btn.classList.add('opacity-50', 'cursor-not-allowed');
153
 
154
  try {
155
  const response = await fetch('/process_sentence', {
@@ -161,7 +182,7 @@ Output: G F E D C B A
161
  const contentType = response.headers.get("content-type");
162
  if (!contentType || !contentType.includes("application/json")) {
163
  const text = await response.text();
164
- throw new Error(`Server returned non-JSON response: ${text.substring(0, 100)}...`);
165
  }
166
 
167
  const result = await response.json();
@@ -172,24 +193,20 @@ Output: G F E D C B A
172
  document.getElementById('floating-msg').classList.remove('visible');
173
 
174
  const warningEl = document.getElementById('truncation-warning');
175
- if (result.truncated) {
176
- warningEl.classList.remove('hidden');
177
- } else {
178
- warningEl.classList.add('hidden');
179
- }
180
 
181
  } else {
182
  alert("Backend Error: " + (result.message || "Unknown error"));
183
  }
184
 
185
  } catch (error) {
186
- console.error("Full Error Details:", error);
187
  alert("Request Failed: " + error.message);
188
  } finally {
189
  btnText.innerText = originalText;
190
  btn.disabled = false;
191
- btn.classList.remove('opacity-50', 'cursor-not-allowed');
192
- // Force an immediate queue check
193
  updateQueueStatus();
194
  }
195
  }
@@ -202,23 +219,25 @@ Output: G F E D C B A
202
  const trace = {
203
  x: xVals, y: yVals, text: tVals,
204
  mode: 'markers',
205
- marker: { size: 8, color: '#3b82f6', opacity: 0.7, line: { width: 0 } },
206
  type: 'scatter', hoverinfo: 'text+x+y'
207
  };
208
 
 
209
  const layout = {
210
- title: { text: 'Assigned vs Original Positions' },
211
- xaxis: { title: 'Original Positions in Context' },
212
- yaxis: { title: 'Assigned Positions' },
213
  hovermode: 'closest', dragmode: 'zoom',
214
- margin: { t: 40, r: 40, b: 40, l: 60 }
 
215
  };
216
 
217
- const config = { responsive: true, displayModeBar: true };
218
  Plotly.newPlot('chartDiv', [trace], layout, config);
219
 
220
  const plotDiv = document.getElementById('chartDiv');
221
- plotDiv.on('plotly_click', function(data) {
222
  if(data.points.length > 0) highlightContext(data.points[0].pointIndex);
223
  });
224
  plotDiv.on('plotly_doubleclick', () => setTimeout(resetView, 100));
@@ -228,13 +247,13 @@ Output: G F E D C B A
228
  const n = currentData.length;
229
  const start = Math.max(0, centerIndex - K);
230
  const end = Math.min(n - 1, centerIndex + K);
231
- const colors = new Array(n).fill('rgba(200, 200, 200, 0.4)');
232
- const sizes = new Array(n).fill(6);
233
  let contextTokens = [];
234
 
235
  for (let i = start; i <= end; i++) {
236
- colors[i] = '#ef4444';
237
- sizes[i] = 14;
238
  contextTokens.push(currentData[i].t);
239
  }
240
 
@@ -247,8 +266,8 @@ Output: G F E D C B A
247
  if(currentData.length === 0) return;
248
  const n = currentData.length;
249
  Plotly.restyle('chartDiv', {
250
- 'marker.color': [new Array(n).fill('#3b82f6')],
251
- 'marker.size': [new Array(n).fill(8)]
252
  });
253
  document.getElementById('floating-msg').classList.remove('visible');
254
  }
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>RePo Visualizer</title>
7
  <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <style>
10
+ /* Float msg style */
11
  #floating-msg {
12
+ transition: opacity 0.3s ease;
13
  opacity: 0;
14
  pointer-events: none;
15
  }
16
+ #floating-msg.visible { opacity: 1; }
17
+
18
+ /* Ensure Plotly fills the container */
19
+ .js-plotly-plot, .plot-container {
20
+ width: 100% !important;
21
+ height: 100% !important;
22
  }
23
  </style>
24
  </head>
25
+ <body class="h-screen w-screen overflow-hidden bg-gray-50 text-gray-800 font-sans flex">
26
 
27
+ <aside class="w-80 (min-w-[320px]) flex flex-col bg-white border-r border-gray-200 shadow-lg z-20 shrink-0">
28
+
29
+ <div class="p-4 border-b border-gray-100">
30
+ <div class="flex justify-between items-center mb-2">
31
+ <h2 class="text-xl font-bold text-indigo-700">RePo Visualizer</h2>
32
+ <div id="queue-indicator" class="hidden bg-blue-50 text-blue-700 text-[10px] font-bold px-2 py-1 rounded-full border border-blue-200 flex items-center gap-1">
33
+ <span class="relative flex h-1.5 w-1.5">
34
+ <span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
35
+ <span class="relative inline-flex rounded-full h-1.5 w-1.5 bg-blue-500"></span>
36
+ </span>
37
+ <span id="queue-text">Wait: 0</span>
38
+ </div>
39
  </div>
 
40
 
41
+ <div class="text-xs text-gray-500 bg-gray-50 p-2 rounded border border-gray-100 leading-tight space-y-1">
42
+ <p><strong>RePo</strong> aims to re-structure context like humans by assigning non-linear positions in dense space.</p>
43
+ <div class="flex gap-2 pt-1 border-t border-gray-200 mt-1">
44
+ <span>⚠️ <strong>CPU Only</strong></span>
45
+ <a href="https://www.arxiv.org/abs/2512.14391" target="_blank" class="text-blue-600 hover:underline">Paper</a>
46
+ <a href="https://github.com/SakanaAI/repo" target="_blank" class="text-blue-600 hover:underline">Code</a>
47
+ </div>
48
+ </div>
49
  </div>
50
 
51
+ <div class="p-4 flex flex-col gap-3 flex-1 overflow-y-auto">
52
+
53
+ <div class="flex flex-col flex-1 min-h-[100px]">
54
+ <label class="text-xs font-semibold text-gray-700 uppercase mb-1">Input Context</label>
55
+ <textarea id="sentenceInput"
56
+ class="w-full flex-1 p-2 text-sm border border-gray-300 rounded focus:ring-1 focus:ring-indigo-500 outline-none resize-none bg-gray-50"
57
+ placeholder="Enter text...">Please revise the following tokens:
58
  Input: A B C D E F G
59
  Output: G F E D C B A
60
  </textarea>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  </div>
62
 
63
+ <div class="grid grid-cols-2 gap-2">
64
+ <div>
65
+ <label class="text-xs font-semibold text-gray-700 uppercase mb-1">Layer</label>
66
+ <select id="layerSelect" class="w-full p-1.5 text-sm border border-gray-300 rounded bg-white">
67
+ <option value="5">Layer 5</option>
68
+ <option value="6">Layer 6</option>
69
+ <option value="7">Layer 7</option>
70
+ <option value="8">Layer 8</option>
71
+ <option value="9">Layer 9</option>
72
+ <option value="10">Layer 10</option>
73
+ <option value="11">Layer 11</option>
74
+ <option value="12">Layer 12</option>
75
+ <option value="13">Layer 13</option>
76
+ <option value="14">Layer 14</option>
77
+ <option value="15">Layer 15</option>
78
+ </select>
79
+ </div>
80
+ <div>
81
+ <label class="text-xs font-semibold text-gray-700 uppercase mb-1">Head</label>
82
+ <select id="headSelect" class="w-full p-1.5 text-sm border border-gray-300 rounded bg-white">
83
+ <option value="0">Head 0</option>
84
+ <option value="1">Head 1</option>
85
+ <option value="2">Head 2</option>
86
+ <option value="3">Head 3</option>
87
+ <option value="4">Head 4</option>
88
+ <option value="5">Head 5</option>
89
+ <option value="6">Head 6</option>
90
+ <option value="7">Head 7</option>
91
+ <option value="8">Head 8</option>
92
+ <option value="9">Head 9</option>
93
+ <option value="10">Head 10</option>
94
+ <option value="11">Head 11</option>
95
+ <option value="12">Head 12</option>
96
+ <option value="13">Head 13</option>
97
+ <option value="14">Head 14</option>
98
+ <option value="15">Head 15</option>
99
+ </select>
100
+ </div>
101
  </div>
102
 
103
+ <button onclick="fetchData()" id="computeBtn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded text-sm transition shadow-sm flex justify-center items-center gap-2">
104
  <span>Compute & Visualize</span>
105
  </button>
106
  </div>
107
+ </aside>
108
+
109
+ <main class="flex-1 flex flex-col relative h-full">
110
+
111
+ <div id="truncation-warning" class="hidden w-full bg-yellow-100 border-b border-yellow-200 text-yellow-800 text-xs px-4 py-2 flex items-center justify-between">
112
+ <span><strong>Notice:</strong> Input truncated to 512 tokens for performance.</span>
113
+ <button onclick="this.parentElement.classList.add('hidden')" class="text-yellow-900 font-bold hover:text-yellow-600">×</button>
114
+ </div>
115
 
116
+ <div class="flex-1 relative bg-white overflow-hidden p-2">
117
+ <button onclick="resetView()" class="absolute top-4 right-4 z-10 bg-white/90 hover:bg-gray-100 text-gray-600 text-xs font-bold py-1 px-3 rounded border border-gray-300 shadow-sm transition">
118
+ Reset Zoom
119
  </button>
120
+
121
+ <div id="chartDiv" class="w-full h-full"></div>
122
+
123
+ <div id="floating-msg" class="absolute top-4 left-1/2 transform -translate-x-1/2 bg-gray-900/90 backdrop-blur-sm text-white px-4 py-3 rounded shadow-xl max-w-lg z-20 text-center pointer-events-none">
124
+ <p class="text-[10px] text-gray-400 uppercase tracking-wide mb-1">Local Context (i-k to i+k)</p>
125
+ <p id="context-text" class="text-sm font-medium leading-relaxed">Click a point...</p>
126
  </div>
127
  </div>
128
+ </main>
129
 
130
  <script>
131
  let currentData = [];
 
133
 
134
  document.addEventListener('DOMContentLoaded', () => {
135
  fetchData();
 
136
  setInterval(updateQueueStatus, 2000);
137
+
138
+ // Ensure chart resizes if window resizes
139
+ window.onresize = function() {
140
+ Plotly.Plots.resize(document.getElementById('chartDiv'));
141
+ };
142
  });
143
 
 
144
  async function updateQueueStatus() {
145
  try {
146
  const res = await fetch('/queue_status');
 
150
  const el = document.getElementById('queue-indicator');
151
  const txt = document.getElementById('queue-text');
152
 
 
153
  if (count > 0) {
154
  el.classList.remove('hidden');
155
+ txt.innerText = `Wait: ${count}`;
156
  } else {
157
  el.classList.add('hidden');
158
  }
 
166
  const head = document.getElementById('headSelect').value;
167
  const btn = document.getElementById('computeBtn');
168
  const btnText = btn.querySelector('span');
 
 
169
  const originalText = "Compute & Visualize";
170
 
171
+ btnText.innerText = "Processing...";
 
172
  btn.disabled = true;
173
+ btn.classList.add('opacity-75', 'cursor-not-allowed');
174
 
175
  try {
176
  const response = await fetch('/process_sentence', {
 
182
  const contentType = response.headers.get("content-type");
183
  if (!contentType || !contentType.includes("application/json")) {
184
  const text = await response.text();
185
+ throw new Error(`Server err: ${text.substring(0, 50)}...`);
186
  }
187
 
188
  const result = await response.json();
 
193
  document.getElementById('floating-msg').classList.remove('visible');
194
 
195
  const warningEl = document.getElementById('truncation-warning');
196
+ if (result.truncated) warningEl.classList.remove('hidden');
197
+ else warningEl.classList.add('hidden');
 
 
 
198
 
199
  } else {
200
  alert("Backend Error: " + (result.message || "Unknown error"));
201
  }
202
 
203
  } catch (error) {
204
+ console.error(error);
205
  alert("Request Failed: " + error.message);
206
  } finally {
207
  btnText.innerText = originalText;
208
  btn.disabled = false;
209
+ btn.classList.remove('opacity-75', 'cursor-not-allowed');
 
210
  updateQueueStatus();
211
  }
212
  }
 
219
  const trace = {
220
  x: xVals, y: yVals, text: tVals,
221
  mode: 'markers',
222
+ marker: { size: 6, color: '#4f46e5', opacity: 0.6, line: { width: 0 } }, // Indigio-600
223
  type: 'scatter', hoverinfo: 'text+x+y'
224
  };
225
 
226
+ // Calculate tighter margins to maximize screen space
227
  const layout = {
228
+ title: { text: 'Position Analysis', font: {size: 14} },
229
+ xaxis: { title: 'Token Index' },
230
+ yaxis: { title: 'Assigned Position' },
231
  hovermode: 'closest', dragmode: 'zoom',
232
+ margin: { t: 30, r: 20, b: 40, l: 50 },
233
+ autosize: true
234
  };
235
 
236
+ const config = { responsive: true, displayModeBar: true, displaylogo: false };
237
  Plotly.newPlot('chartDiv', [trace], layout, config);
238
 
239
  const plotDiv = document.getElementById('chartDiv');
240
+ plotDiv.on('plotly_click', (data) => {
241
  if(data.points.length > 0) highlightContext(data.points[0].pointIndex);
242
  });
243
  plotDiv.on('plotly_doubleclick', () => setTimeout(resetView, 100));
 
247
  const n = currentData.length;
248
  const start = Math.max(0, centerIndex - K);
249
  const end = Math.min(n - 1, centerIndex + K);
250
+ const colors = new Array(n).fill('rgba(200, 200, 200, 0.3)');
251
+ const sizes = new Array(n).fill(5);
252
  let contextTokens = [];
253
 
254
  for (let i = start; i <= end; i++) {
255
+ colors[i] = '#ef4444'; // Red Highlight
256
+ sizes[i] = 12;
257
  contextTokens.push(currentData[i].t);
258
  }
259
 
 
266
  if(currentData.length === 0) return;
267
  const n = currentData.length;
268
  Plotly.restyle('chartDiv', {
269
+ 'marker.color': [new Array(n).fill('#4f46e5')],
270
+ 'marker.size': [new Array(n).fill(6)]
271
  });
272
  document.getElementById('floating-msg').classList.remove('visible');
273
  }