victor HF Staff commited on
Commit
09e5623
·
1 Parent(s): 704b01c

Revert trim indicator to simple ellipsis

Browse files
Files changed (2) hide show
  1. index.html +95 -231
  2. trimmer_demo.html +291 -0
index.html CHANGED
@@ -5,306 +5,171 @@
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Message Trimmer Demo - WildChat Conversations</title>
7
  <style>
8
- * {
9
- margin: 0;
10
- padding: 0;
11
- box-sizing: border-box;
 
 
 
 
 
12
  }
13
 
 
 
14
  body {
15
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
16
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
- padding: 20px;
 
18
  min-height: 100vh;
 
19
  }
20
 
21
  .container {
22
- max-width: 1200px;
23
  margin: 0 auto;
24
- background: white;
25
- border-radius: 12px;
26
- box-shadow: 0 20px 60px rgba(0,0,0,0.3);
27
  overflow: hidden;
28
  }
29
 
30
  header {
31
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
32
- color: white;
33
- padding: 30px;
34
  text-align: center;
35
  }
36
 
37
- h1 {
38
- font-size: 2em;
39
- margin-bottom: 10px;
40
- }
41
-
42
- .subtitle {
43
- opacity: 0.9;
44
- font-size: 0.95em;
45
- }
46
 
47
  .controls {
48
- padding: 25px 30px;
49
- background: #f8f9fa;
50
- border-bottom: 1px solid #e9ecef;
51
  }
52
 
53
- .control-group {
54
- margin-bottom: 20px;
55
- }
56
-
57
- .control-group:last-child {
58
- margin-bottom: 0;
59
- }
60
 
61
  label {
62
  display: block;
63
  font-weight: 600;
64
  margin-bottom: 8px;
65
- color: #495057;
66
  font-size: 0.9em;
67
  }
68
 
69
  input[type="range"] {
70
  width: 100%;
71
- height: 6px;
72
- border-radius: 3px;
73
- background: #dee2e6;
74
  outline: none;
75
  -webkit-appearance: none;
76
  }
77
-
78
  input[type="range"]::-webkit-slider-thumb {
79
- -webkit-appearance: none;
80
- appearance: none;
81
- width: 18px;
82
- height: 18px;
83
- border-radius: 50%;
84
- background: #667eea;
85
  cursor: pointer;
 
 
86
  }
87
-
88
  input[type="range"]::-moz-range-thumb {
89
- width: 18px;
90
- height: 18px;
91
- border-radius: 50%;
92
- background: #667eea;
93
- cursor: pointer;
94
- border: none;
95
  }
96
 
97
  .value-display {
98
  display: inline-block;
99
- background: #667eea;
100
- color: white;
101
- padding: 4px 12px;
102
- border-radius: 12px;
103
- font-size: 0.85em;
104
- font-weight: 600;
105
  margin-left: 10px;
 
 
106
  }
107
 
108
  select {
109
- width: 100%;
110
- padding: 10px;
111
- border: 2px solid #dee2e6;
112
- border-radius: 6px;
113
- font-size: 0.95em;
114
- background: white;
115
  cursor: pointer;
116
  }
 
117
 
118
- select:focus {
119
- outline: none;
120
- border-color: #667eea;
121
- }
122
 
123
- .conversation {
124
- padding: 30px;
125
- }
126
-
127
- .message {
128
- margin-bottom: 30px;
129
- animation: fadeIn 0.3s ease-in;
130
- }
131
-
132
- @keyframes fadeIn {
133
- from { opacity: 0; transform: translateY(10px); }
134
- to { opacity: 1; transform: translateY(0); }
135
- }
136
-
137
- .message-header {
138
- display: flex;
139
- align-items: center;
140
- margin-bottom: 12px;
141
- gap: 10px;
142
- }
143
 
 
144
  .role-badge {
145
- padding: 6px 14px;
146
- border-radius: 20px;
147
- font-size: 0.75em;
148
- font-weight: 700;
149
- text-transform: uppercase;
150
- letter-spacing: 0.5px;
151
- }
152
-
153
- .role-user {
154
- background: #e7f5ff;
155
- color: #1971c2;
156
- }
157
-
158
- .role-assistant {
159
- background: #f3f0ff;
160
- color: #5f3dc4;
161
- }
162
-
163
- .char-count {
164
- font-size: 0.75em;
165
- color: #868e96;
166
- font-weight: 500;
167
  }
 
168
 
169
  .message-content {
170
- background: #f8f9fa;
171
- padding: 20px;
172
- border-radius: 8px;
173
- border-left: 4px solid #dee2e6;
174
- position: relative;
175
  }
 
 
176
 
177
- .message-user .message-content {
178
- border-left-color: #1971c2;
179
- }
180
-
181
- .message-assistant .message-content {
182
- border-left-color: #5f3dc4;
183
- }
184
 
185
- .original {
186
- margin-bottom: 15px;
187
- padding-bottom: 15px;
188
- border-bottom: 2px dashed #dee2e6;
189
- }
190
-
191
- .trimmed {
192
- background: #fff3bf;
193
- padding: 15px;
194
- border-radius: 6px;
195
- border: 2px solid #ffd43b;
196
  }
 
197
 
198
  .section-label {
199
- font-size: 0.7em;
200
- font-weight: 700;
201
- text-transform: uppercase;
202
- letter-spacing: 0.5px;
203
- color: #495057;
204
- margin-bottom: 8px;
205
- }
206
-
207
- .trimmed .section-label {
208
- color: #e67700;
209
  }
 
210
 
211
- .content-text {
212
- line-height: 1.6;
213
- color: #212529;
214
- white-space: pre-wrap;
215
- word-wrap: break-word;
216
- }
217
 
218
  .stats {
219
- margin-top: 10px;
220
- padding: 10px;
221
- background: rgba(255,255,255,0.7);
222
- border-radius: 4px;
223
- font-size: 0.8em;
224
- color: #495057;
225
- }
226
-
227
- .stats strong {
228
- color: #212529;
229
- }
230
-
231
- .reduction {
232
- color: #e67700;
233
- font-weight: 600;
234
  }
 
 
235
 
236
  .code-reference {
237
- background: #f8f9fa;
238
- border: 1px solid #dee2e6;
239
- border-radius: 6px;
240
- padding: 20px;
241
- margin: 20px 30px;
242
- font-family: 'Monaco', 'Menlo', monospace;
243
- font-size: 0.85em;
244
- line-height: 1.6;
245
- }
246
-
247
- .code-reference h3 {
248
- margin-bottom: 15px;
249
- color: #495057;
250
- font-size: 1em;
251
- }
252
-
253
- .code-line {
254
- color: #212529;
255
- margin: 4px 0;
256
- }
257
-
258
- .comment {
259
- color: #6c757d;
260
  }
 
 
 
261
 
262
  button {
263
- background: #667eea;
264
- color: white;
265
- border: none;
266
- padding: 10px 20px;
267
- border-radius: 6px;
268
- cursor: pointer;
269
- font-size: 0.9em;
270
- font-weight: 600;
271
- margin-top: 10px;
272
- }
273
-
274
- button:hover {
275
- background: #5568d3;
276
  }
 
277
 
278
  .info-box {
279
- background: #e7f5ff;
280
- border: 2px solid #1971c2;
281
- border-radius: 8px;
282
- padding: 20px;
283
- margin: 20px 30px;
284
  }
 
 
285
 
286
- .info-box h3 {
287
- color: #1971c2;
288
- margin-bottom: 10px;
289
- font-size: 1em;
290
- }
291
-
292
- .info-box p {
293
- color: #495057;
294
- line-height: 1.6;
295
- font-size: 0.9em;
296
- }
297
-
298
- .no-trim {
299
- background: #d3f9d8;
300
- padding: 15px;
301
- border-radius: 6px;
302
- border: 2px solid #51cf66;
303
- }
304
-
305
- .no-trim .section-label {
306
- color: #2b8a3e;
307
- }
308
  </style>
309
  </head>
310
  <body>
@@ -318,8 +183,7 @@
318
  <h3>About This Demo</h3>
319
  <p>
320
  This demo shows how the <strong>trimMiddle()</strong> function works in the LLM router architecture.
321
- The function trims messages by keeping the start (60%) and end (40%) with a clear
322
- <strong>[... CONTENT TRIMMED ...]</strong> indicator in between,
323
  reducing token count while preserving context for intent classification.
324
  Adjust the max length sliders below to see how different messages are trimmed.
325
  </p>
@@ -362,7 +226,7 @@
362
  </div>
363
 
364
  <div id="conversationDisplay" class="conversation">
365
- <p style="text-align: center; color: #868e96;">Loading conversations...</p>
366
  </div>
367
  </div>
368
 
@@ -371,7 +235,7 @@
371
  function trimMiddle(content, maxLength) {
372
  if (content.length <= maxLength) return content;
373
 
374
- const indicator = " [... CONTENT TRIMMED ...] ";
375
  const availableLength = maxLength - indicator.length;
376
 
377
  if (availableLength <= 0) {
@@ -411,7 +275,7 @@
411
  } catch (error) {
412
  console.error('Error loading conversations:', error);
413
  document.getElementById('conversationDisplay').innerHTML =
414
- '<p style="text-align: center; color: #dc3545;">Error loading conversations. Please refresh the page.</p>';
415
  }
416
  }
417
 
@@ -460,7 +324,7 @@
460
  <div class="message-header">
461
  <span class="role-badge role-${message.role}">${message.role}</span>
462
  <span class="char-count">${content.length} characters</span>
463
- ${isLastUser ? '<span class="char-count" style="color: #2b8a3e; font-weight: 600;">★ Latest user message - preserved</span>' : ''}
464
  </div>
465
  <div class="message-content">
466
  <div class="original">
 
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Message Trimmer Demo - WildChat Conversations</title>
7
  <style>
8
+ :root {
9
+ --bg: #0b0b0b;
10
+ --surface: #111111;
11
+ --surface-2: #141414;
12
+ --text: #eaeaea;
13
+ --muted: #9b9b9b;
14
+ --border: #1f1f1f;
15
+ --accent: #8ab4f8; /* subtle blue */
16
+ --radius: 12px;
17
  }
18
 
19
+ * { margin: 0; padding: 0; box-sizing: border-box; }
20
+
21
  body {
22
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
23
+ background: var(--bg);
24
+ color: var(--text);
25
+ padding: 24px;
26
  min-height: 100vh;
27
+ line-height: 1.45;
28
  }
29
 
30
  .container {
31
+ max-width: 1100px;
32
  margin: 0 auto;
33
+ background: var(--surface);
34
+ border: 1px solid var(--border);
35
+ border-radius: var(--radius);
36
  overflow: hidden;
37
  }
38
 
39
  header {
40
+ background: transparent;
41
+ border-bottom: 1px solid var(--border);
42
+ padding: 28px 30px;
43
  text-align: center;
44
  }
45
 
46
+ h1 { font-size: 1.75em; font-weight: 700; letter-spacing: 0.2px; }
47
+ .subtitle { color: var(--muted); font-size: 0.95em; margin-top: 6px; }
 
 
 
 
 
 
 
48
 
49
  .controls {
50
+ padding: 24px 30px;
51
+ background: var(--surface-2);
52
+ border-bottom: 1px solid var(--border);
53
  }
54
 
55
+ .control-group { margin-bottom: 18px; }
56
+ .control-group:last-child { margin-bottom: 0; }
 
 
 
 
 
57
 
58
  label {
59
  display: block;
60
  font-weight: 600;
61
  margin-bottom: 8px;
62
+ color: var(--muted);
63
  font-size: 0.9em;
64
  }
65
 
66
  input[type="range"] {
67
  width: 100%;
68
+ height: 4px;
69
+ border-radius: 2px;
70
+ background: #222;
71
  outline: none;
72
  -webkit-appearance: none;
73
  }
 
74
  input[type="range"]::-webkit-slider-thumb {
75
+ -webkit-appearance: none; appearance: none;
76
+ width: 16px; height: 16px; border-radius: 50%;
77
+ background: var(--accent);
 
 
 
78
  cursor: pointer;
79
+ border: 2px solid #0d0d0d;
80
+ box-shadow: 0 0 0 2px rgba(138,180,248,0.15);
81
  }
 
82
  input[type="range"]::-moz-range-thumb {
83
+ width: 16px; height: 16px; border-radius: 50%;
84
+ background: var(--accent);
85
+ cursor: pointer; border: 2px solid #0d0d0d;
 
 
 
86
  }
87
 
88
  .value-display {
89
  display: inline-block;
90
+ color: var(--accent);
91
+ padding: 2px 10px;
92
+ border-radius: 999px;
93
+ font-size: 0.85em; font-weight: 600;
 
 
94
  margin-left: 10px;
95
+ border: 1px solid var(--border);
96
+ background: #0e0e0e;
97
  }
98
 
99
  select {
100
+ width: 100%; padding: 10px 12px;
101
+ border: 1px solid var(--border); border-radius: 8px;
102
+ font-size: 0.95em; background: #0f0f0f; color: var(--text);
 
 
 
103
  cursor: pointer;
104
  }
105
+ select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(138,180,248,0.15); }
106
 
107
+ .conversation { padding: 26px 30px; }
 
 
 
108
 
109
+ .message { margin-bottom: 28px; animation: fadeIn 0.25s ease-in; }
110
+ @keyframes fadeIn { from { opacity: 0; transform: translateY(6px);} to { opacity: 1; transform: translateY(0);} }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
+ .message-header { display: flex; align-items: center; margin-bottom: 10px; gap: 10px; }
113
  .role-badge {
114
+ padding: 6px 12px; border-radius: 999px; font-size: 0.72em; font-weight: 700;
115
+ text-transform: uppercase; letter-spacing: 0.5px; background: #0f0f0f; color: var(--muted);
116
+ border: 1px solid var(--border);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  }
118
+ .char-count { font-size: 0.75em; color: var(--muted); font-weight: 500; }
119
 
120
  .message-content {
121
+ background: var(--surface-2);
122
+ padding: 18px; border-radius: 10px; border-left: 3px solid var(--border);
 
 
 
123
  }
124
+ .message-user .message-content { border-left-color: #2a2a2a; }
125
+ .message-assistant .message-content { border-left-color: var(--accent); }
126
 
127
+ .original { margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px dashed var(--border); }
 
 
 
 
 
 
128
 
129
+ .trimmed, .no-trim {
130
+ background: var(--surface);
131
+ padding: 14px; border-radius: 8px; border: 1px solid var(--border);
 
 
 
 
 
 
 
 
132
  }
133
+ .trimmed { border-color: rgba(138,180,248,0.35); }
134
 
135
  .section-label {
136
+ font-size: 0.7em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;
137
+ color: var(--muted); margin-bottom: 8px;
 
 
 
 
 
 
 
 
138
  }
139
+ .trimmed .section-label { color: var(--accent); }
140
 
141
+ .content-text { line-height: 1.6; color: var(--text); white-space: pre-wrap; word-wrap: break-word; }
 
 
 
 
 
142
 
143
  .stats {
144
+ margin-top: 10px; padding: 10px; border-radius: 6px; font-size: 0.8em; color: var(--muted);
145
+ background: #0f0f0f; border: 1px solid var(--border);
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  }
147
+ .stats strong { color: var(--text); }
148
+ .reduction { color: var(--accent); font-weight: 600; }
149
 
150
  .code-reference {
151
+ background: #0f0f0f; border: 1px solid var(--border); border-radius: 8px; padding: 18px; margin: 20px 30px;
152
+ font-family: 'Monaco', 'Menlo', monospace; font-size: 0.85em; line-height: 1.6; color: var(--text);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  }
154
+ .code-reference h3 { margin-bottom: 12px; color: var(--muted); font-size: 1em; font-weight: 600; }
155
+ .code-line { color: var(--text); margin: 4px 0; }
156
+ .comment { color: #7a7a7a; }
157
 
158
  button {
159
+ background: #0f0f0f; color: var(--text); border: 1px solid var(--border);
160
+ padding: 10px 16px; border-radius: 8px; cursor: pointer; font-size: 0.9em; font-weight: 600; margin-top: 10px;
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
+ button:hover { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(138,180,248,0.15); }
163
 
164
  .info-box {
165
+ background: var(--surface-2); border: 1px solid var(--border); border-left: 3px solid var(--accent);
166
+ border-radius: 8px; padding: 18px; margin: 20px 30px;
 
 
 
167
  }
168
+ .info-box h3 { color: var(--text); margin-bottom: 8px; font-size: 1em; }
169
+ .info-box p { color: var(--muted); line-height: 1.6; font-size: 0.9em; }
170
 
171
+ /* Focus styles */
172
+ :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  </style>
174
  </head>
175
  <body>
 
183
  <h3>About This Demo</h3>
184
  <p>
185
  This demo shows how the <strong>trimMiddle()</strong> function works in the LLM router architecture.
186
+ The function trims messages by keeping the start (60%) and end (40%) with an ellipsis in between,
 
187
  reducing token count while preserving context for intent classification.
188
  Adjust the max length sliders below to see how different messages are trimmed.
189
  </p>
 
226
  </div>
227
 
228
  <div id="conversationDisplay" class="conversation">
229
+ <p style="text-align: center; color: var(--muted);">Loading conversations...</p>
230
  </div>
231
  </div>
232
 
 
235
  function trimMiddle(content, maxLength) {
236
  if (content.length <= maxLength) return content;
237
 
238
+ const indicator = "";
239
  const availableLength = maxLength - indicator.length;
240
 
241
  if (availableLength <= 0) {
 
275
  } catch (error) {
276
  console.error('Error loading conversations:', error);
277
  document.getElementById('conversationDisplay').innerHTML =
278
+ '<p style="text-align: center; color: var(--accent);">Error loading conversations. Please refresh the page.</p>';
279
  }
280
  }
281
 
 
324
  <div class="message-header">
325
  <span class="role-badge role-${message.role}">${message.role}</span>
326
  <span class="char-count">${content.length} characters</span>
327
+ ${isLastUser ? '<span class="char-count" style="color: var(--accent); font-weight: 600;">★ Latest user message · preserved</span>' : ''}
328
  </div>
329
  <div class="message-content">
330
  <div class="original">
trimmer_demo.html ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <title>Message Trimmer Demo - WildChat Conversations</title>
7
+ <style>
8
+ :root {
9
+ --bg: #0b0b0b;
10
+ --surface: #111111;
11
+ --surface-2: #141414;
12
+ --text: #eaeaea;
13
+ --muted: #9b9b9b;
14
+ --border: #1f1f1f;
15
+ --accent: #8ab4f8;
16
+ --radius: 12px;
17
+ }
18
+
19
+ * { margin: 0; padding: 0; box-sizing: border-box; }
20
+
21
+ body {
22
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
23
+ background: var(--bg); color: var(--text);
24
+ padding: 24px; min-height: 100vh; line-height: 1.45;
25
+ }
26
+
27
+ .container { max-width: 1100px; margin: 0 auto; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
28
+ header { background: transparent; border-bottom: 1px solid var(--border); padding: 28px 30px; text-align: center; }
29
+ h1 { font-size: 1.75em; font-weight: 700; letter-spacing: 0.2px; }
30
+ .subtitle { color: var(--muted); font-size: 0.95em; margin-top: 6px; }
31
+
32
+ .controls { padding: 24px 30px; background: var(--surface-2); border-bottom: 1px solid var(--border); }
33
+ .control-group { margin-bottom: 18px; }
34
+ .control-group:last-child { margin-bottom: 0; }
35
+
36
+ label { display: block; font-weight: 600; margin-bottom: 8px; color: var(--muted); font-size: 0.9em; }
37
+
38
+ input[type="range"] { width: 100%; height: 4px; border-radius: 2px; background: #222; outline: none; -webkit-appearance: none; }
39
+ input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--accent); cursor: pointer; border: 2px solid #0d0d0d; box-shadow: 0 0 0 2px rgba(138,180,248,0.15); }
40
+ input[type="range"]::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--accent); cursor: pointer; border: 2px solid #0d0d0d; }
41
+
42
+ .value-display { display: inline-block; color: var(--accent); padding: 2px 10px; border-radius: 999px; font-size: 0.85em; font-weight: 600; margin-left: 10px; border: 1px solid var(--border); background: #0e0e0e; }
43
+
44
+ select { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 0.95em; background: #0f0f0f; color: var(--text); cursor: pointer; }
45
+ select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(138,180,248,0.15); }
46
+
47
+ .conversation { padding: 26px 30px; }
48
+ .message { margin-bottom: 28px; animation: fadeIn 0.25s ease-in; }
49
+ @keyframes fadeIn { from { opacity: 0; transform: translateY(6px);} to { opacity: 1; transform: translateY(0);} }
50
+
51
+ .message-header { display: flex; align-items: center; margin-bottom: 10px; gap: 10px; }
52
+ .role-badge { padding: 6px 12px; border-radius: 999px; font-size: 0.72em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; background: #0f0f0f; color: var(--muted); border: 1px solid var(--border); }
53
+ .char-count { font-size: 0.75em; color: var(--muted); font-weight: 500; }
54
+
55
+ .message-content { background: var(--surface-2); padding: 18px; border-radius: 10px; border-left: 3px solid var(--border); }
56
+ .message-user .message-content { border-left-color: #2a2a2a; }
57
+ .message-assistant .message-content { border-left-color: var(--accent); }
58
+
59
+ .original { margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px dashed var(--border); }
60
+ .trimmed, .no-trim { background: var(--surface); padding: 14px; border-radius: 8px; border: 1px solid var(--border); }
61
+ .trimmed { border-color: rgba(138,180,248,0.35); }
62
+
63
+ .section-label { font-size: 0.7em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: var(--muted); margin-bottom: 8px; }
64
+ .trimmed .section-label { color: var(--accent); }
65
+
66
+ .content-text { line-height: 1.6; color: var(--text); white-space: pre-wrap; word-wrap: break-word; }
67
+ .stats { margin-top: 10px; padding: 10px; background: #0f0f0f; border: 1px solid var(--border); border-radius: 6px; font-size: 0.8em; color: var(--muted); }
68
+ .stats strong { color: var(--text); }
69
+ .reduction { color: var(--accent); font-weight: 600; }
70
+
71
+ .code-reference { background: #0f0f0f; border: 1px solid var(--border); border-radius: 8px; padding: 18px; margin: 20px 30px; font-family: 'Monaco', 'Menlo', monospace; font-size: 0.85em; line-height: 1.6; color: var(--text); }
72
+ .code-reference h3 { margin-bottom: 12px; color: var(--muted); font-size: 1em; font-weight: 600; }
73
+ .code-line { color: var(--text); margin: 4px 0; }
74
+ .comment { color: #7a7a7a; }
75
+
76
+ button { background: #0f0f0f; color: var(--text); border: 1px solid var(--border); padding: 10px 16px; border-radius: 8px; cursor: pointer; font-size: 0.9em; font-weight: 600; margin-top: 10px; }
77
+ button:hover { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(138,180,248,0.15); }
78
+
79
+ .info-box { background: var(--surface-2); border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 8px; padding: 18px; margin: 20px 30px; }
80
+ .info-box h3 { color: var(--text); margin-bottom: 8px; font-size: 1em; }
81
+ .info-box p { color: var(--muted); line-height: 1.6; font-size: 0.9em; }
82
+
83
+ :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
84
+ </style>
85
+ </head>
86
+ <body>
87
+ <div class="container">
88
+ <header>
89
+ <h1>Message Trimmer Demo</h1>
90
+ <p class="subtitle">Demonstrating trim functions on real WildChat-1M conversations</p>
91
+ </header>
92
+
93
+ <div class="info-box">
94
+ <h3>About This Demo</h3>
95
+ <p>
96
+ This demo shows how the <strong>trimMiddle()</strong> function works in the LLM router architecture.
97
+ The function trims messages by keeping the start (60%) and end (40%) with an ellipsis in between,
98
+ reducing token count while preserving context for intent classification.
99
+ Adjust the max length sliders below to see how different messages are trimmed.
100
+ </p>
101
+ </div>
102
+
103
+ <div class="controls">
104
+ <div class="control-group">
105
+ <label>
106
+ Max Assistant Message Length: <span class="value-display" id="assistantLengthValue">500</span>
107
+ </label>
108
+ <input type="range" id="assistantLength" min="50" max="1000" value="500" step="10">
109
+ </div>
110
+
111
+ <div class="control-group">
112
+ <label>
113
+ Max Previous User Message Length: <span class="value-display" id="userLengthValue">400</span>
114
+ </label>
115
+ <input type="range" id="userLength" min="50" max="1000" value="400" step="10">
116
+ </div>
117
+
118
+ <div class="control-group">
119
+ <label>Select Conversation:</label>
120
+ <select id="conversationSelect">
121
+ <option value="0">Loading conversations...</option>
122
+ </select>
123
+ </div>
124
+ </div>
125
+
126
+ <div class="code-reference">
127
+ <h3>Implementation (from src/lib/server/router/arch.ts)</h3>
128
+ <div class="code-line"><span class="comment">// Trim assistant messages to reduce routing prompt size</span></div>
129
+ <div class="code-line">if (m.role === "assistant") {</div>
130
+ <div class="code-line">&nbsp;&nbsp;return { ...m, content: trimMiddle(m.content, maxAssistantLength) };</div>
131
+ <div class="code-line">}</div>
132
+ <div class="code-line"></div>
133
+ <div class="code-line"><span class="comment">// Trim previous user messages (latest preserved)</span></div>
134
+ <div class="code-line">if (m.role === "user" && idx !== lastUserIndex) {</div>
135
+ <div class="code-line">&nbsp;&nbsp;return { ...m, content: trimMiddle(m.content, maxPrevUserLength) };</div>
136
+ <div class="code-line">}</div>
137
+ </div>
138
+
139
+ <div id="conversationDisplay" class="conversation">
140
+ <p style="text-align: center; color: var(--muted);">Loading conversations...</p>
141
+ </div>
142
+ </div>
143
+
144
+ <script>
145
+ // Implementation of trimMiddle function from arch.ts
146
+ function trimMiddle(content, maxLength) {
147
+ if (content.length <= maxLength) return content;
148
+
149
+ const indicator = "…";
150
+ const availableLength = maxLength - indicator.length;
151
+
152
+ if (availableLength <= 0) {
153
+ return content.slice(0, maxLength);
154
+ }
155
+
156
+ // Reserve more space for the start (60%)
157
+ const startLength = Math.ceil(availableLength * 0.6);
158
+ const endLength = availableLength - startLength;
159
+
160
+ if (endLength <= 0) {
161
+ return content.slice(0, availableLength) + indicator;
162
+ }
163
+
164
+ const start = content.slice(0, startLength);
165
+ const end = content.slice(-endLength);
166
+
167
+ return start + indicator + end;
168
+ }
169
+
170
+ // Fetch and store conversations
171
+ let conversations = [];
172
+
173
+ async function loadConversations() {
174
+ try {
175
+ const response = await fetch('https://datasets-server.huggingface.co/rows?dataset=allenai%2FWildChat-1M&config=default&split=train&offset=0&length=100');
176
+ const data = await response.json();
177
+
178
+ // Filter for conversations with multiple turns
179
+ conversations = data.rows
180
+ .filter(row => row.row.conversation && row.row.conversation.length >= 2)
181
+ .map(row => row.row.conversation)
182
+ .slice(0, 20); // Take first 20 conversations
183
+
184
+ populateConversationSelect();
185
+ displayConversation(0);
186
+ } catch (error) {
187
+ console.error('Error loading conversations:', error);
188
+ document.getElementById('conversationDisplay').innerHTML =
189
+ '<p style="text-align: center; color: var(--accent);">Error loading conversations. Please refresh the page.</p>';
190
+ }
191
+ }
192
+
193
+ function populateConversationSelect() {
194
+ const select = document.getElementById('conversationSelect');
195
+ select.innerHTML = conversations.map((conv, idx) => {
196
+ const preview = conv[0].content.slice(0, 60).replace(/\n/g, ' ');
197
+ return `<option value="${idx}">Conversation ${idx + 1}: ${preview}...</option>`;
198
+ }).join('');
199
+ }
200
+
201
+ function displayConversation(index) {
202
+ const conversation = conversations[index];
203
+ if (!conversation) return;
204
+
205
+ const assistantLength = parseInt(document.getElementById('assistantLength').value);
206
+ const userLength = parseInt(document.getElementById('userLength').value);
207
+
208
+ const lastUserIndex = conversation.map((m, idx) => ({ idx, role: m.role }))
209
+ .reverse()
210
+ .find(m => m.role === 'user')?.idx ?? -1;
211
+
212
+ let html = '';
213
+
214
+ conversation.forEach((message, idx) => {
215
+ const isUser = message.role === 'user';
216
+ const isLastUser = idx === lastUserIndex;
217
+ const content = message.content;
218
+ let trimmed = content;
219
+ let shouldTrim = false;
220
+
221
+ // Apply trimming logic
222
+ if (message.role === 'assistant') {
223
+ trimmed = trimMiddle(content, assistantLength);
224
+ shouldTrim = content.length > assistantLength;
225
+ } else if (message.role === 'user' && !isLastUser) {
226
+ trimmed = trimMiddle(content, userLength);
227
+ shouldTrim = content.length > userLength;
228
+ }
229
+
230
+ const reductionPercent = shouldTrim ?
231
+ (((content.length - trimmed.length) / content.length) * 100).toFixed(1) : 0;
232
+
233
+ html += `
234
+ <div class="message message-${message.role}">
235
+ <div class="message-header">
236
+ <span class="role-badge role-${message.role}">${message.role}</span>
237
+ <span class="char-count">${content.length} characters</span>
238
+ ${isLastUser ? '<span class="char-count" style="color: var(--accent); font-weight: 600;">★ Latest user message · preserved</span>' : ''}
239
+ </div>
240
+ <div class="message-content">
241
+ <div class="original">
242
+ <div class="section-label">Original</div>
243
+ <div class="content-text">${escapeHtml(content)}</div>
244
+ </div>
245
+ <div class="${shouldTrim ? 'trimmed' : 'no-trim'}">
246
+ <div class="section-label">${shouldTrim ? 'Trimmed for Router' : 'No Trimming Required'}</div>
247
+ <div class="content-text">${escapeHtml(trimmed)}</div>
248
+ ${shouldTrim ? `
249
+ <div class="stats">
250
+ <strong>Original:</strong> ${content.length} chars |
251
+ <strong>Trimmed:</strong> ${trimmed.length} chars |
252
+ <span class="reduction">Reduced by ${reductionPercent}%</span>
253
+ </div>
254
+ ` : ''}
255
+ </div>
256
+ </div>
257
+ </div>
258
+ `;
259
+ });
260
+
261
+ document.getElementById('conversationDisplay').innerHTML = html;
262
+ }
263
+
264
+ function escapeHtml(text) {
265
+ const div = document.createElement('div');
266
+ div.textContent = text;
267
+ return div.innerHTML;
268
+ }
269
+
270
+ // Event listeners
271
+ document.getElementById('assistantLength').addEventListener('input', (e) => {
272
+ document.getElementById('assistantLengthValue').textContent = e.target.value;
273
+ const selectedIndex = parseInt(document.getElementById('conversationSelect').value);
274
+ displayConversation(selectedIndex);
275
+ });
276
+
277
+ document.getElementById('userLength').addEventListener('input', (e) => {
278
+ document.getElementById('userLengthValue').textContent = e.target.value;
279
+ const selectedIndex = parseInt(document.getElementById('conversationSelect').value);
280
+ displayConversation(selectedIndex);
281
+ });
282
+
283
+ document.getElementById('conversationSelect').addEventListener('change', (e) => {
284
+ displayConversation(parseInt(e.target.value));
285
+ });
286
+
287
+ // Initialize
288
+ loadConversations();
289
+ </script>
290
+ </body>
291
+ </html>