PeterPinetree commited on
Commit
b373af6
·
verified ·
1 Parent(s): 7e75e3e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -38
app.py CHANGED
@@ -2,7 +2,8 @@
2
  import json
3
  from pathlib import Path
4
  import threading, time
5
-
 
6
  import solara
7
  import pandas as pd
8
  import plotly.graph_objects as go
@@ -236,52 +237,92 @@ def AutoPredictWatcher():
236
  solara.use_effect(effect, [text, auto])
237
  return solara.Text("", style={"display": "none"})
238
 
239
- # ---------- Predictions list ----------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  @solara.component
241
  def PredictionsList():
242
- df = preds_rx.value
243
- with solara.Column(gap="6px", style={"maxWidth": "720px"}):
244
- solara.Markdown("### Prediction")
245
- solara.Text(
246
- " # probs token predicted next token",
247
- style={
248
- "color": "var(--muted)",
249
- "fontFamily": 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
250
- },
251
- )
252
 
253
- for i, row in df.iterrows():
254
- tid = int(row["id"])
255
- prob = row["probs"]
256
- tok_disp = display_token_from_id(tid)
257
- row_label = fmt_row(i, prob, tid, tok_disp)
258
 
259
- # Wrapper DIV catches pointer/hover; Button handles click (and also hooks hover)
260
  with solara.Div(
261
- classes=["rowbtn"], # styling on the wrapper
262
- style={"justifyContent": "flex-start", "width": "100%"},
263
- attributes={"tabindex": "0", "role": "button"},
264
- # ---- HOVER = preview neighborhood (wrapper) ----
265
- on_mouse_enter=lambda *args, tid=tid: preview_token(tid),
266
- on_mouse_over=lambda *args, tid=tid: preview_token(tid),
267
- on_mouse_move=lambda *args, tid=tid: preview_token(tid),
268
- on_pointer_enter=lambda *args, tid=tid: preview_token(tid),
269
- on_pointer_move=lambda *args, tid=tid: preview_token(tid),
270
- on_focus=lambda *args, tid=tid: preview_token(tid), # keyboard focus
271
  ):
272
  solara.Button(
273
  row_label,
274
- classes=[], # keep wrapper styled; leave button unstyled
275
- style={"justifyContent": "flex-start", "width": "100%"},
276
- # ---- CLICK = append token to text ----
277
  on_click=lambda *args, tid=tid: append_token(tid),
278
- # Redundant hover hooks on the button too (helps on some builds)
279
- on_mouse_enter=lambda *args, tid=tid: preview_token(tid),
280
- on_mouse_over=lambda *args, tid=tid: preview_token(tid),
281
- on_mouse_move=lambda *args, tid=tid: preview_token(tid),
282
- on_pointer_enter=lambda *args, tid=tid: preview_token(tid),
283
- on_pointer_move=lambda *args, tid=tid: preview_token(tid),
284
- on_focus=lambda *args, tid=tid: preview_token(tid),
 
285
  )
286
 
287
  # ---------- Page ----------
 
2
  import json
3
  from pathlib import Path
4
  import threading, time
5
+ import anywidget
6
+ import traitlets as t
7
  import solara
8
  import pandas as pd
9
  import plotly.graph_objects as go
 
237
  solara.use_effect(effect, [text, auto])
238
  return solara.Text("", style={"display": "none"})
239
 
240
+ class HoverList(anywidget.AnyWidget):
241
+ """
242
+ Renders the prediction rows in the browser and streams hover/click
243
+ events back to Python via synced traitlets.
244
+ """
245
+ # Browser code: builds the list and wires events
246
+ _esm = """
247
+ export function render({ model, el }) {
248
+ const make = () => {
249
+ const items = model.get('items') || [];
250
+ el.innerHTML = "";
251
+ const wrap = document.createElement('div');
252
+ wrap.style.display = 'flex';
253
+ wrap.style.flexDirection = 'column';
254
+ items.forEach(({tid, label}) => {
255
+ const btn = document.createElement('button');
256
+ btn.textContent = label;
257
+ btn.className = 'rowbtn'; // your existing CSS
258
+ btn.setAttribute('type', 'button');
259
+ btn.setAttribute('role', 'button');
260
+ btn.setAttribute('tabindex', '0');
261
+
262
+ // hover → preview
263
+ const preview = () => {
264
+ model.set('hovered_id', tid);
265
+ model.save_changes();
266
+ };
267
+ btn.addEventListener('mouseenter', preview);
268
+ btn.addEventListener('mouseover', preview);
269
+ btn.addEventListener('mousemove', preview);
270
+ btn.addEventListener('focus', preview);
271
+
272
+ // click → append
273
+ btn.addEventListener('click', () => {
274
+ model.set('clicked_id', tid);
275
+ model.save_changes();
276
+ });
277
+
278
+ wrap.appendChild(btn);
279
+ });
280
+ el.appendChild(wrap);
281
+ };
282
+
283
+ // initial render
284
+ make();
285
+
286
+ // re-render when items change
287
+ model.on('change:items', make);
288
+ }
289
+ """
290
+ # Data flowing between JS and Python
291
+ items = t.List(trait=t.Dict()).tag(sync=True) # [{tid:int, label:str}, ...]
292
+ hovered_id = t.Int(allow_none=True).tag(sync=True)
293
+ clicked_id = t.Int(allow_none=True).tag(sync=True)
294
+
295
+
296
  @solara.component
297
  def PredictionsList():
298
+ token_probs = token_probs_rx.value or []
299
+ selected_token_id = selected_token_id_rx.value
 
 
 
 
 
 
 
 
300
 
301
+ with solara.Column():
302
+ for tid, prob in token_probs[:10]:
303
+ row_label = f"{id_to_token.get(tid, tid)} ({prob:.2f})"
304
+ is_selected = tid == selected_token_id
 
305
 
 
306
  with solara.Div(
307
+ style={
308
+ "background": "#333" if is_selected else "transparent",
309
+ "padding": "2px",
310
+ "borderRadius": "4px",
311
+ },
312
+ on_mouse_enter=lambda tid=tid: preview_token(tid),
313
+ on_mouse_leave=lambda tid=tid: preview_token(None),
 
 
 
314
  ):
315
  solara.Button(
316
  row_label,
 
 
 
317
  on_click=lambda *args, tid=tid: append_token(tid),
318
+ style={
319
+ "justifyContent": "flex-start",
320
+ "width": "100%",
321
+ "textAlign": "left",
322
+ "color": "#38bdf8" if is_selected else "white",
323
+ },
324
+ on_mouse_enter=lambda tid=tid: preview_token(tid),
325
+ on_mouse_leave=lambda tid=tid: preview_token(None),
326
  )
327
 
328
  # ---------- Page ----------