soumi guria commited on
Commit
77f89a1
Β·
2 Parent(s): 6ec90aa6783f47

Merge branch 'main' of https://github.com/soumiguria/cognitive-load-manager

Browse files
frontend/dist/index.html CHANGED
@@ -4,7 +4,7 @@
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
  <title>CLM Dashboard</title>
7
- <script type="module" crossorigin src="/assets/index-CPBwWvcP.js"></script>
8
  <link rel="stylesheet" crossorigin href="/assets/index-DHB-7DK0.css">
9
  </head>
10
  <body style="margin:0;background:#f1f5f9">
 
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
  <title>CLM Dashboard</title>
7
+ <script type="module" crossorigin src="/assets/index-BJKK8Bcl.js"></script>
8
  <link rel="stylesheet" crossorigin href="/assets/index-DHB-7DK0.css">
9
  </head>
10
  <body style="margin:0;background:#f1f5f9">
frontend/src/components/Dashboard.jsx CHANGED
@@ -216,6 +216,205 @@ function ScoringFormulaCard() {
216
  )
217
  }
218
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  // ── Main Dashboard ─────────────────────────────────────────────────────────────
220
  export default function Dashboard() {
221
  // ── mode: 'stream' (auto-play via SSE) | 'manual' (interactive) ────────────
@@ -813,8 +1012,13 @@ export default function Dashboard() {
813
  </>
814
  )}
815
 
816
- {/* ── Reward scoring formula β€” always visible ── */}
817
  <div style={{ marginTop: 20 }}>
 
 
 
 
 
818
  <ScoringFormulaCard />
819
  </div>
820
 
 
216
  )
217
  }
218
 
219
+ // ── Training Performance Card (data from CLM_GRPO_Training.ipynb) ──────────────
220
+ // Mean reward sampled at training checkpoints from the GRPO training run.
221
+ const TRAINING_CURVE = [
222
+ { step: 1, reward: 0.1006 },
223
+ { step: 50, reward: 0.0882 },
224
+ { step: 100, reward: 0.1192 },
225
+ { step: 200, reward: 0.1010 },
226
+ { step: 300, reward: 0.1383 },
227
+ { step: 400, reward: 0.1700 },
228
+ { step: 500, reward: 0.2201 },
229
+ { step: 600, reward: 0.2542 },
230
+ { step: 700, reward: 0.2595 },
231
+ { step: 800, reward: 0.2648 },
232
+ { step: 900, reward: 0.2345 },
233
+ { step: 1000, reward: 0.2648 },
234
+ ]
235
+
236
+ // Per-action mean reward measured before training (heuristic baseline) and
237
+ // after 1000 steps of GRPO training.
238
+ const ACTION_COMPARISON = [
239
+ { action: 'Work', before: 0.045, after: 0.102 },
240
+ { action: 'Focus', before: 0.124, after: 0.249 },
241
+ { action: 'Break', before: 0.030, after: 0.030 },
242
+ { action: 'Delay', before: 0.010, after: 0.010 },
243
+ ]
244
+
245
+ function TrainingLineChart({ data, height = 160 }) {
246
+ const W = 720
247
+ const padL = 36, padR = 16, padT = 18, padB = 28
248
+ const innerW = W - padL - padR
249
+ const innerH = height - padT - padB
250
+ const xs = data.map(d => d.step)
251
+ const ys = data.map(d => d.reward)
252
+ const xLo = Math.min(...xs), xHi = Math.max(...xs)
253
+ const yLo = Math.min(0, ...ys), yHi = Math.max(...ys, 0.3)
254
+ const px = v => padL + ((v - xLo) / (xHi - xLo || 1)) * innerW
255
+ const py = v => padT + innerH - ((v - yLo) / (yHi - yLo || 1)) * innerH
256
+ const pts = data.map(d => `${px(d.step)},${py(d.reward)}`).join(' ')
257
+
258
+ return (
259
+ <svg viewBox={`0 0 ${W} ${height}`} width="100%" height={height}
260
+ preserveAspectRatio="none" style={{ display: 'block' }}>
261
+ {/* Y axis grid */}
262
+ {[0, 0.1, 0.2, 0.3].map(g => (
263
+ <g key={g}>
264
+ <line x1={padL} y1={py(g)} x2={W - padR} y2={py(g)}
265
+ stroke="#e2e8f0" strokeWidth="1" />
266
+ <text x={padL - 6} y={py(g) + 3} fontSize="10" fill="#94a3b8" textAnchor="end">
267
+ {g.toFixed(2)}
268
+ </text>
269
+ </g>
270
+ ))}
271
+ {/* X axis labels */}
272
+ {[0, 250, 500, 750, 1000].map(s => (
273
+ <text key={s} x={px(s)} y={height - 8} fontSize="10" fill="#94a3b8"
274
+ textAnchor="middle">step {s}</text>
275
+ ))}
276
+ {/* Area + line */}
277
+ <polyline
278
+ points={[`${px(xLo)},${py(yLo)}`, ...data.map(d => `${px(d.step)},${py(d.reward)}`),
279
+ `${px(xHi)},${py(yLo)}`].join(' ')}
280
+ fill="#6366f122" stroke="none"
281
+ />
282
+ <polyline points={pts} fill="none" stroke="#6366f1" strokeWidth="2.5"
283
+ strokeLinejoin="round" strokeLinecap="round" />
284
+ {data.map(d => (
285
+ <circle key={d.step} cx={px(d.step)} cy={py(d.reward)} r="3" fill="#6366f1" />
286
+ ))}
287
+ </svg>
288
+ )
289
+ }
290
+
291
+ function ActionComparisonChart({ data, height = 200 }) {
292
+ const W = 520
293
+ const padL = 60, padR = 16, padT = 18, padB = 36
294
+ const innerW = W - padL - padR
295
+ const innerH = height - padT - padB
296
+ const yMax = Math.max(...data.flatMap(d => [d.before, d.after]), 0.3) * 1.1
297
+ const groupW = innerW / data.length
298
+ const barW = (groupW - 18) / 2
299
+
300
+ return (
301
+ <svg viewBox={`0 0 ${W} ${height}`} width="100%" height={height}
302
+ preserveAspectRatio="none" style={{ display: 'block' }}>
303
+ {/* Y grid */}
304
+ {[0, 0.1, 0.2, 0.3].map(g => {
305
+ const y = padT + innerH - (g / yMax) * innerH
306
+ return (
307
+ <g key={g}>
308
+ <line x1={padL} y1={y} x2={W - padR} y2={y}
309
+ stroke="#e2e8f0" strokeWidth="1" />
310
+ <text x={padL - 6} y={y + 3} fontSize="10" fill="#94a3b8" textAnchor="end">
311
+ {g.toFixed(2)}
312
+ </text>
313
+ </g>
314
+ )
315
+ })}
316
+ {data.map((d, i) => {
317
+ const gx = padL + i * groupW + 9
318
+ const hBefore = (d.before / yMax) * innerH
319
+ const hAfter = (d.after / yMax) * innerH
320
+ return (
321
+ <g key={d.action}>
322
+ <rect x={gx} y={padT + innerH - hBefore} width={barW} height={hBefore}
323
+ fill="#94a3b8" rx="3" />
324
+ <rect x={gx + barW + 4} y={padT + innerH - hAfter} width={barW} height={hAfter}
325
+ fill="#6366f1" rx="3" />
326
+ <text x={gx + barW + 2} y={padT + innerH - hBefore - 4}
327
+ fontSize="9" fill="#64748b" textAnchor="middle">{d.before.toFixed(3)}</text>
328
+ <text x={gx + barW + barW + 6} y={padT + innerH - hAfter - 4}
329
+ fontSize="9" fontWeight="700" fill="#4338ca" textAnchor="middle">
330
+ {d.after.toFixed(3)}
331
+ </text>
332
+ <text x={gx + barW + 2} y={height - 14} fontSize="11" fontWeight="600"
333
+ fill="#334155" textAnchor="middle">{d.action}</text>
334
+ </g>
335
+ )
336
+ })}
337
+ </svg>
338
+ )
339
+ }
340
+
341
+ function TrainingPerformanceCard() {
342
+ const first = TRAINING_CURVE[0].reward
343
+ const last = TRAINING_CURVE[TRAINING_CURVE.length - 1].reward
344
+ const lift = (((last - first) / (Math.abs(first) || 1)) * 100).toFixed(0)
345
+
346
+ return (
347
+ <div style={{ background: '#fff', border: '1px solid #e2e8f0',
348
+ borderRadius: 14, padding: '20px 20px 16px', marginBottom: 16 }}>
349
+ <div style={{ marginBottom: 14, display: 'flex', alignItems: 'center',
350
+ justifyContent: 'space-between', flexWrap: 'wrap', gap: 12 }}>
351
+ <div>
352
+ <div style={{ fontSize: 14, fontWeight: 800, color: '#0f172a', marginBottom: 4 }}>
353
+ Training Performance β€” Before vs After GRPO
354
+ </div>
355
+ <div style={{ fontSize: 11, color: '#64748b' }}>
356
+ Measured during 1000-step GRPO fine-tuning of the policy on the CLM environment
357
+ </div>
358
+ </div>
359
+ <div style={{ display: 'flex', gap: 10 }}>
360
+ <div style={{ background: '#f1f5f9', borderRadius: 10, padding: '8px 14px',
361
+ textAlign: 'center', minWidth: 90 }}>
362
+ <div style={{ fontSize: 9, color: '#94a3b8', fontWeight: 700,
363
+ textTransform: 'uppercase', letterSpacing: '.06em' }}>Before</div>
364
+ <div style={{ fontSize: 18, fontWeight: 800, color: '#475569' }}>
365
+ {first.toFixed(3)}
366
+ </div>
367
+ </div>
368
+ <div style={{ background: '#eef2ff', borderRadius: 10, padding: '8px 14px',
369
+ textAlign: 'center', minWidth: 90 }}>
370
+ <div style={{ fontSize: 9, color: '#6366f1', fontWeight: 700,
371
+ textTransform: 'uppercase', letterSpacing: '.06em' }}>After</div>
372
+ <div style={{ fontSize: 18, fontWeight: 800, color: '#4338ca' }}>
373
+ {last.toFixed(3)}
374
+ </div>
375
+ </div>
376
+ <div style={{ background: '#f0fdf4', borderRadius: 10, padding: '8px 14px',
377
+ textAlign: 'center', minWidth: 90 }}>
378
+ <div style={{ fontSize: 9, color: '#16a34a', fontWeight: 700,
379
+ textTransform: 'uppercase', letterSpacing: '.06em' }}>Lift</div>
380
+ <div style={{ fontSize: 18, fontWeight: 800, color: '#16a34a' }}>
381
+ +{lift}%
382
+ </div>
383
+ </div>
384
+ </div>
385
+ </div>
386
+
387
+ <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 14 }}>
388
+ <div style={{ background: '#f8fafc', borderRadius: 10, padding: 12,
389
+ border: '1px solid #e2e8f0' }}>
390
+ <div style={{ fontSize: 10, fontWeight: 700, color: '#94a3b8',
391
+ textTransform: 'uppercase', letterSpacing: '.07em', marginBottom: 8 }}>
392
+ Mean Reward Across Training Steps
393
+ </div>
394
+ <TrainingLineChart data={TRAINING_CURVE} height={170} />
395
+ </div>
396
+
397
+ <div style={{ background: '#f8fafc', borderRadius: 10, padding: 12,
398
+ border: '1px solid #e2e8f0' }}>
399
+ <div style={{ fontSize: 10, fontWeight: 700, color: '#94a3b8',
400
+ textTransform: 'uppercase', letterSpacing: '.07em', marginBottom: 8,
401
+ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
402
+ <span>Per-Action Reward</span>
403
+ <span style={{ fontSize: 10, fontWeight: 600, color: '#64748b' }}>
404
+ <span style={{ display: 'inline-block', width: 9, height: 9, background: '#94a3b8',
405
+ borderRadius: 2, verticalAlign: 'middle', marginRight: 4 }} />Before
406
+ &ensp;
407
+ <span style={{ display: 'inline-block', width: 9, height: 9, background: '#6366f1',
408
+ borderRadius: 2, verticalAlign: 'middle', marginRight: 4 }} />After
409
+ </span>
410
+ </div>
411
+ <ActionComparisonChart data={ACTION_COMPARISON} height={170} />
412
+ </div>
413
+ </div>
414
+ </div>
415
+ )
416
+ }
417
+
418
  // ── Main Dashboard ─────────────────────────────────────────────────────────────
419
  export default function Dashboard() {
420
  // ── mode: 'stream' (auto-play via SSE) | 'manual' (interactive) ────────────
 
1012
  </>
1013
  )}
1014
 
1015
+ {/* ── Training performance β€” before vs after GRPO ── */}
1016
  <div style={{ marginTop: 20 }}>
1017
+ <TrainingPerformanceCard />
1018
+ </div>
1019
+
1020
+ {/* ── Reward scoring formula β€” always visible ── */}
1021
+ <div>
1022
  <ScoringFormulaCard />
1023
  </div>
1024