""" space/app.py — One for All HuggingFace ZeroGPU Gradio Space. Run locally (from space/ dir, with a local viz_data.json): cd space && VIZ_DATA_PATH=/path/to/viz_data.json python app.py """ from __future__ import annotations import os import html as _html_stdlib import gradio as gr import spaces import _data import _fig import _glb import _html import _probe # ── Startup: load data, fit UMAP, load student ─────────────────────────── HF_TOKEN = os.environ.get("HF_TOKEN") _local_viz = os.environ.get("VIZ_DATA_PATH") try: if _local_viz: VIZ = _data.load_from_path(_local_viz) print(f"[ofa-space] loaded viz from {_local_viz}") else: VIZ = _data.load_and_parse(HF_TOKEN) except Exception as e: print(f"[ofa-space] viz_data.json not available ({e}), using empty state") VIZ = _data.make_empty_viz() try: if VIZ["stacked"].shape[0] > 3: REDUCER = _data.fit_umap3d(VIZ["stacked"]) COORDS3D = REDUCER.embedding_ print(f"[ofa-space] UMAP done: {COORDS3D.shape}") else: print(f"[ofa-space] not enough points for UMAP: {VIZ['stacked'].shape[0]}") REDUCER = None COORDS3D = None except Exception as e: print(f"[ofa-space] UMAP failed ({e}), 3D disabled") REDUCER = None COORDS3D = None try: TOK, STUDENT, GATING = _probe.load_student(HF_TOKEN) _MODEL_READY = True except Exception as e: print(f"[ofa-space] Student not available ({e}). Probe disabled.") TOK = STUDENT = GATING = None _MODEL_READY = False _INIT_GLB = _glb.build_glb(VIZ, COORDS3D, []) print(f"[ofa-space] GLB path: {_INIT_GLB}") if _INIT_GLB: print(f"[ofa-space] GLB exists: {os.path.exists(_INIT_GLB)}, size: {os.path.getsize(_INIT_GLB)} bytes") # Camera: pull back far enough to see all points at startup if COORDS3D is not None: import numpy as _np _span = float(_np.linalg.norm(COORDS3D.max(axis=0) - COORDS3D.min(axis=0))) _CAM = (45, 30, _span * 1.8) else: _CAM = (45, 30, 10) def _response_html(text: str) -> str: safe = _html_stdlib.escape(text).replace("\n", "
") return ( '
' '
MODEL RESPONSE
' f'
{safe}
' "
" ) # ── ZeroGPU probe handler ───────────────────────────────────────────────── @spaces.GPU def probe_fn(text: str, probe_points: list) -> tuple: no_change = _glb.build_glb(VIZ, COORDS3D, probe_points), probe_points, "", "", "" if not text.strip(): return no_change if not _MODEL_READY or REDUCER is None: msg = _html.gate_html([0.2] * 5, VIZ["teacher_names"] or ["—"] * 5) return _glb.build_glb(VIZ, COORDS3D, probe_points), probe_points, "", msg, "" device = "cuda" if __import__("torch").cuda.is_available() else "cpu" STUDENT.to(device) answer = _probe.generate_response(text, STUDENT, TOK) new_pt, gate_weights = _probe.run_probe(text, STUDENT, TOK, GATING, REDUCER) updated = probe_points + [new_pt] glb_path = _glb.build_glb(VIZ, COORDS3D, updated) gate_h = _html.gate_html(gate_weights, VIZ["teacher_names"]) task_h = _html.task_html(gate_weights, VIZ["teacher_names"]) resp_h = _response_html(answer) return glb_path, updated, resp_h, gate_h, task_h # ── CSS ─────────────────────────────────────────────────────────────────── CSS = """ /* ── Variables ─────────────────────────────────────────── */ :root { --bg: #080b10; --panel: #0d1117; --panel2: #111620; --border: #1c2129; --border-hi: #30363d; --indigo: #7c3aed; --indigo-dim: rgba(124,58,237,0.18); --cyan: #06b6d4; --amber: #f59e0b; --green: #34d399; --pink: #f472b6; --text: #e6edf3; --text-dim: #8b949e; --text-faint: #484f58; --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace; --radius: 10px; } /* ── Base ───────────────────────────────────────────────── */ * { box-sizing: border-box; } .gradio-container { background: var(--bg) !important; background-image: radial-gradient(ellipse 90% 60% at 10% -5%, rgba(124,58,237,0.07) 0%, transparent 55%), radial-gradient(ellipse 70% 50% at 90% 105%, rgba(6,182,212,0.05) 0%, transparent 55%) !important; font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif; min-height: 100vh; } footer { display: none !important; } /* ── All blocks: remove default boxy look ───────────────── */ .block { background: var(--panel) !important; border: 1px solid var(--border) !important; border-radius: var(--radius) !important; box-shadow: 0 1px 3px rgba(0,0,0,0.4), 0 0 0 0 transparent !important; transition: border-color 0.25s, box-shadow 0.25s !important; padding: 0 !important; } .block:hover { border-color: var(--border-hi) !important; } /* Remove the double-border that Gradio adds */ .block .block { border: none !important; background: transparent !important; } /* ── Label text ─────────────────────────────────────────── */ label > span, .label-wrap span, .block-label span { font-family: var(--mono) !important; font-size: 10px !important; font-weight: 600 !important; letter-spacing: 0.09em !important; text-transform: uppercase !important; color: var(--text-faint) !important; } /* ── Textarea / input ───────────────────────────────────── */ textarea, input[type="text"], input[type="number"] { background: #060a10 !important; border: 1px solid var(--border-hi) !important; color: var(--text) !important; border-radius: 8px !important; font-size: 13px !important; line-height: 1.6 !important; transition: border-color 0.2s, box-shadow 0.2s !important; resize: vertical !important; } textarea:focus, input[type="text"]:focus { border-color: var(--indigo) !important; box-shadow: 0 0 0 3px rgba(124,58,237,0.12), 0 0 18px rgba(124,58,237,0.18) !important; outline: none !important; } textarea::placeholder { color: var(--text-faint) !important; } /* ── Primary button ─────────────────────────────────────── */ button.primary, button[variant="primary"] { background: linear-gradient(135deg, #6d28d9, var(--indigo)) !important; border: 1px solid rgba(124,58,237,0.45) !important; border-radius: 8px !important; color: #fff !important; font-family: var(--mono) !important; font-size: 12px !important; font-weight: 700 !important; letter-spacing: 0.07em !important; text-transform: uppercase !important; padding: 10px 22px !important; transition: all 0.2s ease !important; box-shadow: 0 2px 10px rgba(124,58,237,0.22) !important; cursor: pointer !important; } button.primary:hover { background: linear-gradient(135deg, var(--indigo), #8b5cf6) !important; box-shadow: 0 4px 20px rgba(124,58,237,0.45), 0 0 0 1px rgba(124,58,237,0.35) !important; transform: translateY(-1px) !important; } button.primary:active { transform: translateY(0) !important; } /* Secondary buttons */ button.secondary { background: var(--panel2) !important; border: 1px solid var(--border-hi) !important; color: var(--text-dim) !important; border-radius: 8px !important; transition: all 0.2s !important; } button.secondary:hover { border-color: var(--indigo) !important; color: var(--text) !important; } /* ── Tabs: underline style (Linear / GitHub / Vercel) ───── */ .tabs > .tab-nav, div[role="tablist"] { background: transparent !important; border-bottom: 1px solid var(--border) !important; gap: 0 !important; padding: 0 2px !important; } .tab-nav button, div[role="tab"] { background: transparent !important; border: none !important; border-bottom: 2px solid transparent !important; border-radius: 0 !important; color: var(--text-dim) !important; font-family: var(--mono) !important; font-size: 11px !important; font-weight: 600 !important; letter-spacing: 0.07em !important; text-transform: uppercase !important; padding: 10px 18px 9px !important; margin-bottom: -1px !important; transition: color 0.18s, border-color 0.18s !important; box-shadow: none !important; } .tab-nav button:hover { color: var(--text) !important; border-bottom-color: rgba(124,58,237,0.4) !important; } .tab-nav button.selected { color: var(--indigo) !important; border-bottom: 2px solid var(--indigo) !important; background: transparent !important; box-shadow: none !important; } /* ── Plotly / charts: transparent background ────────────── */ .plot-container, .plot-container > div, .js-plotly-plot { background: transparent !important; } /* ── Model3D container ──────────────────────────────────── */ div[data-testid="model3d"], .model3D-component { border-radius: var(--radius) !important; overflow: hidden !important; border: 1px solid var(--border) !important; box-shadow: 0 0 40px rgba(124,58,237,0.08) inset !important; } /* ── Scrollbars ─────────────────────────────────────────── */ ::-webkit-scrollbar { width: 5px; height: 5px; } ::-webkit-scrollbar-track { background: var(--bg); } ::-webkit-scrollbar-thumb { background: var(--border-hi); border-radius: 99px; } ::-webkit-scrollbar-thumb:hover { background: var(--text-faint); } /* ── Animated LIVE badge ─────────────────────────────────── */ @keyframes pulse-dot { 0%, 100% { opacity: 1; box-shadow: 0 0 6px var(--cyan); } 50% { opacity: 0.5; box-shadow: 0 0 2px var(--cyan); } } .live-dot { animation: pulse-dot 1.8s ease-in-out infinite; } /* ── Fade-in on load ─────────────────────────────────────── */ @keyframes fadeUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .gradio-container > .main > .wrap { animation: fadeUp 0.45s ease; } /* ── Row/col gaps ────────────────────────────────────────── */ .gap { gap: 14px !important; } .row { gap: 14px !important; } """ # ── Layout ──────────────────────────────────────────────────────────────── with gr.Blocks(css=CSS, theme=gr.themes.Base(), title="One for All") as demo: gr.HTML(_html.header_html()) probe_state = gr.State([]) with gr.Tabs(): # ── Tab 1: Almas ────────────────────────────────────────────────── with gr.TabItem("Souls"): with gr.Row(): with gr.Column(scale=6): umap_plot = gr.Model3D( value=_INIT_GLB, display_mode="solid", clear_color=[0.031, 0.043, 0.063, 1.0], height=500, label=None, camera_position=_CAM, ) gr.HTML(_glb.build_legend_html(VIZ)) with gr.Column(scale=4): gr.HTML( '
' 'Probe the student' 'LIVE' '
' ) prompt_box = gr.Textbox( lines=4, placeholder="Ask anything — code, math, language…", label="", ) run_btn = gr.Button("Run", variant="primary") resp_out = gr.HTML() gate_out = gr.HTML() task_out = gr.HTML() gr.HTML( '
↑ new probe point will appear in soul space
' ) # ── Tab 2: Geometria ────────────────────────────────────────────── with gr.TabItem("Geometry"): with gr.Row(): with gr.Column(scale=7): gr.Plot( value=_fig.build_cka_fig(VIZ["cka"]), label="CKA geometry alignment", ) with gr.Column(scale=3): cka_matrix = VIZ["cka"].get("matrix", []) if cka_matrix: import numpy as _np mat = _np.array(cka_matrix) n = mat.shape[0] mask = ~_np.eye(n, dtype=bool) mean_off = float(mat[mask].mean()) masked = mat.copy() _np.fill_diagonal(masked, 1.0) min_idx = _np.unravel_index(masked.argmin(), masked.shape) hard_pair = (VIZ["cka"]["models"][min_idx[0]], VIZ["cka"]["models"][min_idx[1]]) hard_val = float(masked[min_idx]) gr.HTML( f'
' f'
{mean_off:.3f}
' f'
' f'mean off-diagonal CKA
' f'
hardest pair
' f'
' f'{hard_pair[0]} ↔ {hard_pair[1]}' f' {hard_val:.2f}
' f'
' ) # ── Tab 3: Treino ───────────────────────────────────────────────── with gr.TabItem("Training"): with gr.Row(): gr.Plot( value=_fig.build_curves_fig(VIZ["curves"]), label="Loss curves", ) gr.Plot( value=_fig.build_gate_area_fig(VIZ["curves"]), label="Gate evolution", ) # ── Event wiring ────────────────────────────────────────────────────── run_btn.click( probe_fn, inputs=[prompt_box, probe_state], outputs=[umap_plot, probe_state, resp_out, gate_out, task_out], ) if __name__ == "__main__": demo.launch()