"""AI Model X-Ray - Structural Health Scanner. Single-file Gradio app. Upload or select a transformer; get a per-layer structural-health diagnostic: which layers are compressible (immune), which are fragile (critical), and how the model compares to reference architectures. Dark mission-control theme (Octopus palette). All panels are gr.HTML blocks re-rendered from a scan result produced by analysis.py. Pre-loaded models read from a precomputed cache (instant, no GPU); custom models trigger a live scan. Run: python app.py -> http://localhost:7860 """ from __future__ import annotations import html import math import traceback import gradio as gr import analysis as ax # Optional ZeroGPU decorator (no-op when `spaces` is unavailable, e.g. locally). try: import spaces # type: ignore GPU = spaces.GPU(duration=300) except Exception: # pragma: no cover - local / non-Spaces environment def GPU(fn): return fn # --------------------------------------------------------------------------- # # Palette # --------------------------------------------------------------------------- # BG = "#0f0f14" CARD = "#1a1b26" BORDER = "#2a2b36" FG = "#f8f8fb" FG2 = "#8888a0" EMERALD = "#10B981" AMBER = "#EF9F27" RED = "#E24B4A" REGIME_COLOR = {"immune": EMERALD, "buffer": AMBER, "critical": RED} DROPDOWN_CHOICES = [ ("bert-base-uncased (Encoder, 12L x 12H, 110M)", "bert-base-uncased"), ("gpt2 (Decoder, 12L x 12H, 124M)", "gpt2"), ("google/vit-base-patch16-224 (Vision, 12L x 12H, 86M)", "google/vit-base-patch16-224"), ("distilbert-base-uncased (Encoder, 6L x 12H, 66M)", "distilbert-base-uncased"), ] # =========================================================================== # CSS # =========================================================================== CSS = """ .gradio-container { background:#0f0f14 !important; color:#f8f8fb !important; max-width:100% !important; font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif !important; } .gradio-container .block, .gradio-container .form, .gradio-container .panel, .gradio-container .gap { background:transparent !important; border:none !important; box-shadow:none !important; } footer { display:none !important; } .gradio-container button { background:#191a24 !important; color:#cdd2e6 !important; border:1px solid #2a2b36 !important; box-shadow:none !important; font-weight:600 !important; transition:border-color .15s ease,color .15s ease; } .gradio-container button:hover { border-color:#3a3d50 !important; color:#f3f4fa !important; } /* ---- top bar ---- */ #xr-topbar { display:flex !important; flex-direction:row !important; align-items:center; gap:10px; padding:12px 18px; width:100%; box-sizing:border-box; background:linear-gradient(90deg,#15161f,#1a1b26); border:1px solid #2a2b36; border-radius:14px; margin-bottom:8px; } #xr-topbar > * { flex-shrink:0; } #tb-logo-col { flex:1 1 auto; min-width:0; } .tb-logo { font-size:21px; font-weight:800; color:#f8f8fb; letter-spacing:.02em; } .tb-logo .xr { color:#10B981; } .tb-sub { font-size:11.5px; color:#8888a0; margin-top:2px; letter-spacing:.06em; text-transform:uppercase; } .tb-badge { display:inline-flex; align-items:center; gap:8px; padding:7px 14px; border-radius:999px; font-size:12px; font-weight:700; letter-spacing:.04em; white-space:nowrap; background:rgba(16,185,129,.12); color:#10B981; border:1px solid #1c5641; } /* ---- section titles + cards ---- */ .sec-title { font-size:11px; letter-spacing:.13em; text-transform:uppercase; color:#8888a0; font-weight:800; margin:16px 2px 8px; } .sec-title .n { color:#10B981; } .card { background:#1a1b26; border:1px solid #2a2b36; border-radius:14px; padding:14px 16px; } /* ---- model info rows ---- */ .kv { display:flex; justify-content:space-between; align-items:center; padding:7px 2px; border-bottom:1px solid #20212b; font-size:13px; } .kv:last-child { border-bottom:none; } .kv .k { color:#8888a0; } .kv .v { font-weight:800; color:#f8f8fb; font-family:ui-monospace,Consolas,monospace; } .pill-arch { padding:2px 10px; border-radius:999px; font-size:11px; font-weight:800; background:rgba(16,185,129,.14); color:#10B981; } /* ---- arc gauge ---- */ .gauge-wrap { position:relative; width:200px; height:150px; margin:6px auto 0; animation:pop .5s ease; } .gauge-svg { width:200px; height:200px; position:absolute; top:0; left:0; } .g-track { fill:none; stroke:#23242f; stroke-width:13; stroke-linecap:round; } .g-val { fill:none; stroke-width:13; stroke-linecap:round; transition:stroke-dashoffset .8s cubic-bezier(.3,1,.4,1),stroke .3s; } .gauge-center { position:absolute; top:48px; left:0; width:200px; text-align:center; } .gauge-num { font-size:44px; font-weight:800; line-height:1; } .gauge-lbl { font-size:12px; letter-spacing:.12em; font-weight:800; margin-top:6px; text-transform:uppercase; } .gauge-cap { text-align:center; color:#8888a0; font-size:11px; margin-top:30px; letter-spacing:.04em; } @keyframes pop { from{opacity:0;transform:scale(.94)} to{opacity:1;transform:scale(1)} } /* ---- key metrics ---- */ .metrics { display:grid; grid-template-columns:1fr 1fr; gap:10px; } .metric { background:#14151d; border:1px solid #2a2b36; border-radius:11px; padding:11px 12px; } .metric .mv { font-size:23px; font-weight:800; font-family:ui-monospace,Consolas,monospace; line-height:1; } .metric .ml { font-size:10.5px; color:#8888a0; margin-top:6px; letter-spacing:.04em; text-transform:uppercase; } /* ---- risk map ---- */ .pills { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:12px; } .pill { display:inline-flex; align-items:center; gap:7px; padding:6px 13px; border-radius:999px; font-size:12px; font-weight:700; border:1px solid #2a2b36; background:#14151d; } .pill .dot { width:9px; height:9px; border-radius:50%; } .riskgrid { display:grid; grid-template-columns:repeat(auto-fill,minmax(112px,1fr)); gap:9px; } .rcell { background:#14151d; border:1px solid #2a2b36; border-radius:11px; padding:11px 11px 10px; cursor:pointer; position:relative; overflow:hidden; transition:transform .12s ease,border-color .15s ease; animation:pop .35s ease; } .rcell:hover { transform:translateY(-2px); border-color:#3a3d50; } .rcell.sel { border-color:#f8f8fb; box-shadow:0 0 0 2px #f8f8fb inset, 0 6px 18px rgba(0,0,0,.45); transform:translateY(-2px); } .rcell.flash { animation:cellflash .45s ease; } @keyframes cellflash { 0% { box-shadow:0 0 0 2px #f8f8fb inset, 0 0 0 0 rgba(248,248,251,.55); } 100% { box-shadow:0 0 0 2px #f8f8fb inset, 0 0 0 16px rgba(248,248,251,0); } } .rcell .bar-top { position:absolute; top:0; left:0; right:0; height:3px; } .rcell .rc-l { font-size:11px; color:#8888a0; font-weight:700; letter-spacing:.04em; } .rcell .rc-rho { font-size:21px; font-weight:800; margin:5px 0 2px; font-family:ui-monospace,Consolas,monospace; } .rcell .rc-badge { font-size:9.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; } /* ---- spectral profile ---- */ .spec-row { display:flex; align-items:center; gap:9px; margin:6px 0; font-size:12px; } .spec-lbl { width:34px; color:#8888a0; font-family:ui-monospace,Consolas,monospace; font-size:11px; flex:0 0 auto; } .spec-track { flex:1; height:22px; background:#14151d; border-radius:6px; position:relative; overflow:hidden; } .spec-fill { height:100%; border-radius:6px; animation:grow .6s ease; transform-origin:left; } .spec-inval { position:absolute; left:9px; top:0; height:22px; line-height:22px; font-family:ui-monospace,Consolas,monospace; font-size:11.5px; font-weight:800; color:#ffffff; text-shadow:0 1px 2px rgba(0,0,0,.6); pointer-events:none; } @keyframes grow { from{transform:scaleX(.02)} to{transform:scaleX(1)} } /* color key shown beside the section title */ .spec-key { float:right; font-size:10.5px; font-weight:700; letter-spacing:0; text-transform:none; color:#cdd2e6; } .spec-key b { font-weight:700; color:#cdd2e6; } /* ---- layer detail ---- */ .detail .kv .v.big { font-size:15px; } .regime-banner { padding:10px 12px; border-radius:11px; font-weight:800; font-size:13px; margin-bottom:10px; display:flex; align-items:center; justify-content:space-between; letter-spacing:.03em; } /* ---- comparison table ---- */ .cmp { width:100%; border-collapse:collapse; font-size:12px; } .cmp th { text-align:left; color:#8888a0; font-weight:700; padding:6px 7px; border-bottom:1px solid #2a2b36; font-size:10.5px; letter-spacing:.04em; text-transform:uppercase; } .cmp td { padding:7px 7px; border-bottom:1px solid #20212b; color:#dfe2ee; font-family:ui-monospace,Consolas,monospace; } .cmp tr.me td { background:rgba(16,185,129,.1); color:#f8f8fb; font-weight:800; } .cmp tr.me td:first-child { color:#10B981; } /* ---- pruning rec ---- */ .rec-big { font-size:30px; font-weight:800; color:#10B981; line-height:1; font-family:ui-monospace,Consolas,monospace; } .rec-sub { color:#8888a0; font-size:12px; margin:5px 0 12px; } .rec-list { list-style:none; padding:0; margin:8px 0 0; } .rec-list li { display:flex; justify-content:space-between; padding:5px 2px; font-size:12.5px; border-bottom:1px solid #20212b; } .rec-list li .ln { color:#dfe2ee; } .rec-list li .hd { color:#8888a0; font-family:ui-monospace,Consolas,monospace; } .rec-warn { margin-top:12px; padding:10px 12px; border-radius:10px; background:rgba(226,75,74,.1); border:1px solid rgba(226,75,74,.4); color:#ff8f8e; font-size:12.5px; font-weight:600; } .rec-ok { margin-top:12px; padding:10px 12px; border-radius:10px; background:rgba(16,185,129,.08); border:1px solid rgba(16,185,129,.35); color:#7fe8c4; font-size:12.5px; font-weight:600; } /* ---- scan button ---- */ #scan-btn, #scan-btn button { background:linear-gradient(90deg,#0c7a57,#10B981) !important; color:#fff !important; font-weight:800 !important; letter-spacing:.05em !important; border:none !important; font-size:14px !important; padding:11px !important; } #scan-btn:hover, #scan-btn button:hover { filter:brightness(1.09); } /* dark inputs */ #xr-controls { --input-background-fill:#101019; --block-background-fill:#1a1b26; --border-color-primary:#2a2b36; --body-text-color:#e8eaf2; --body-text-color-subdued:#9aa0b5; } #xr-controls input, #xr-controls textarea, #xr-controls .wrap, #xr-controls .container { background:#101019 !important; color:#e8eaf2 !important; border-color:#2a2b36 !important; } #xr-controls ul.options, #xr-controls .options { background:#101019 !important; border:1px solid #2a2b36 !important; color:#e8eaf2 !important; } #xr-controls .options .item:hover, #xr-controls li.item:hover { background:#20212e !important; } #xr-controls span, #xr-controls label { color:#c8cce0 !important; } .muted { color:#8888a0; font-size:13px; padding:14px 4px; text-align:center; } /* hidden click relay — kept mounted in the DOM (display:none, not unmounted) */ #layer-relay { display:none !important; } /* ---- footer ---- */ #xr-footer { text-align:center; color:#6f7590; font-size:12px; padding:14px 0 6px; margin-top:10px; border-top:1px solid #20212b; line-height:1.7; } #xr-footer b { color:#10B981; } #xr-footer .law { color:#cdd2e6; font-family:ui-monospace,Consolas,monospace; } /* ---- top-bar "?" guide button ---- */ #guide-btn, #guide-btn button { width:40px !important; min-width:40px !important; height:40px !important; border-radius:50% !important; padding:0 !important; font-size:18px !important; font-weight:800 !important; color:#10B981 !important; } /* ---- guide modal ---- */ /* No `display` here: Gradio's visible=False sets display:none; when visible the column is display:flex, so align/justify center the card. (Octopus pattern.) */ #guide-modal { position:fixed; inset:0; z-index:1000; background:rgba(8,8,12,.84); align-items:center; justify-content:center; padding:30px; } .modal-card { max-width:700px; max-height:86vh; overflow-y:auto; margin:0 auto; background:#1a1b26; border:1px solid #2a2b36; border-radius:16px; padding:26px 30px; box-shadow:0 24px 70px rgba(0,0,0,.6); } .modal-h1 { font-size:23px; font-weight:800; color:#f8f8fb; margin-bottom:4px; } .modal-sec { margin-top:16px; } .modal-h2 { display:inline-block; font-size:12px; font-weight:800; color:#10B981; letter-spacing:.08em; text-transform:uppercase; margin-bottom:4px; } .modal-sec p { color:#f8f8fb; font-size:13px; margin:4px 0 0; line-height:1.6; } .modal-sec ul { margin:7px 0 0; padding-left:18px; color:#f8f8fb; font-size:13px; line-height:1.75; } .modal-term { font-weight:800; color:#f8f8fb; font-size:13.5px; margin-top:12px; } .modal-law { font-family:ui-monospace,Consolas,monospace; color:#cdd2e6; } .modal-foot { margin-top:20px; padding-top:14px; border-top:1px solid #20212b; text-align:center; color:#8888a0; font-size:12.5px; line-height:1.7; } .modal-foot b { color:#10B981; } .modal-x, .modal-x button { position:fixed !important; top:24px; right:28px; z-index:1001; width:40px !important; min-width:40px !important; height:40px !important; flex:none !important; border-radius:10px !important; font-size:16px !important; background:#1a1b26 !important; border:1px solid #2a2b36 !important; color:#c8cce0 !important; padding:0 !important; } .modal-x:hover, .modal-x button:hover { border-color:#E24B4A !important; color:#ff8f8e !important; } """ # JS relay: clicking a risk-map cell writes the layer index into a hidden # textbox and fires its input event, which drives the Python detail handler. # Visual feedback (select highlight + flash) is applied immediately on click, # before the server round-trip, so the response always feels instant. HEAD_JS = """ """ # =========================================================================== # Guide modal content # =========================================================================== GUIDE_HTML = """
AI Model X-Ray analyzes the structural health of transformer models by examining how attention heads relate to each other. It reveals which layers are structurally redundant (safe to compress) and which are critical (removing heads would break the model).
Measures how much triangular redundancy exists in each layer's attention graph. Range 0 to 1.
Percentage of connections that have NO triangular backup. Lower is stronger. FI = 0% means every connection has a backup path.
Overall health score (0–100), computed from the global FI. 100 = fully redundant. Below 50 = structurally fragile.
Each card represents one layer of the model.
Based on the spectral simplicial hierarchy λ₂(T(G)) ≤ λ₂(G): algebraic connectivity can only decrease when moving from the edge graph to the triangle graph. Validated on 45,000+ graphs with zero violations. Formally verified in Lean 4.
In practice: if a layer's attention heads form many triangles (groups of 3 mutually correlated heads), the layer has structural backup. If they don't, each head is a single point of failure.
| Model | ρ mean | FI | Type |
|---|