Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>Teachable LLM - In-Browser Transfer Learning w/ Transformers.js</title> | |
| <meta name="description" | |
| content="Interactive demonstration of in-browser text classification using Transformers.js feature extraction and k-Nearest Neighbors with customizable model selection." /> | |
| <!-- Google Fonts: Google Sans, Google Sans Text, Roboto, Roboto Mono --> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link | |
| href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&family=Google+Sans+Text:wght@400;500;700&family=Roboto:wght@400;500;700&family=Roboto+Mono:wght@400;500&display=swap" | |
| rel="stylesheet"> | |
| <link rel="stylesheet" href="style.css" /> | |
| <!-- Importmap for @xenova/transformers browser module resolution --> | |
| <script type="importmap"> | |
| { | |
| "imports": { | |
| "@xenova/transformers": "https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.2" | |
| } | |
| } | |
| </script> | |
| </head> | |
| <body> | |
| <!-- Top Google Four-Color Accent Bar --> | |
| <div class="google-color-bar"> | |
| <div class="bar-blue"></div> | |
| <div class="bar-red"></div> | |
| <div class="bar-yellow"></div> | |
| <div class="bar-green"></div> | |
| </div> | |
| <div class="app-container"> | |
| <!-- Header --> | |
| <header class="app-header"> | |
| <div class="brand"> | |
| <div class="brand-icon"> | |
| <svg width="28" height="28" viewBox="0 0 24 24" fill="none"> | |
| <path | |
| d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" | |
| fill="#4285F4" /> | |
| <circle cx="12" cy="8" r="2.5" fill="#EA4335" /> | |
| <circle cx="8" cy="14" r="2.5" fill="#FBBC04" /> | |
| <circle cx="16" cy="14" r="2.5" fill="#34A853" /> | |
| </svg> | |
| </div> | |
| <div> | |
| <h1 class="brand-title">Teachable LLM</h1> | |
| <p class="brand-subtitle">Transfer Learning via Transformers.js & k-NN in WebAssembly</p> | |
| </div> | |
| </div> | |
| <!-- Model Selector & Status Controls --> | |
| <div class="header-controls"> | |
| <div class="model-selector-card"> | |
| <label for="model-select">Transformer Model:</label> | |
| <select id="model-select" class="model-select"> | |
| <option value="Xenova/all-MiniLM-L6-v2" selected>all-MiniLM-L6-v2 (384-d, ~23MB - Default)</option> | |
| <option value="Xenova/all-mpnet-base-v2">all-mpnet-base-v2 (768-d, ~110MB - High Accuracy)</option> | |
| <option value="Xenova/bge-small-en-v1.5">bge-small-en-v1.5 (384-d, ~67MB - BAAI BGE)</option> | |
| <option value="Xenova/gte-small">gte-small (384-d, ~67MB - General Embeddings)</option> | |
| <option value="Xenova/distilbert-base-uncased">distilbert-base-uncased (768-d, ~67MB - DistilBERT)</option> | |
| </select> | |
| </div> | |
| <!-- Model Load Status Badge --> | |
| <div class="status-card"> | |
| <div class="status-indicator"> | |
| <span id="status-dot" class="status-dot loading"></span> | |
| <span id="status-text">Initializing pipeline...</span> | |
| </div> | |
| <div id="progress-container" class="progress-container" style="display: none;"> | |
| <div id="progress-bar" class="progress-bar" style="width: 0%;"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Concept Overview Hero & Pipeline Stepper Card --> | |
| <section class="hero-card"> | |
| <div class="hero-content"> | |
| <div class="hero-header-row"> | |
| <div> | |
| <h2>Interactive Architecture Pipeline</h2> | |
| <p class="hero-subtitle">Explore how Transformers convert text into high-dimensional vectors and perform | |
| transfer learning in-browser.</p> | |
| </div> | |
| <button type="button" id="animate-pipeline-btn" class="btn btn-secondary btn-sm"> | |
| <svg width="14" height="14" viewBox="0 0 24 24" fill="none" style="margin-right:4px;"> | |
| <polygon points="5,3 19,12 5,21" fill="currentColor" /> | |
| </svg> | |
| Animate Forward Pass | |
| </button> | |
| </div> | |
| <div class="stepper-grid"> | |
| <div class="stepper-step active" data-step="1"> | |
| <div class="step-num step-blue">1</div> | |
| <div class="step-details"> | |
| <h3>Tokenization</h3> | |
| <p>Subword splitting & position IDs</p> | |
| </div> | |
| </div> | |
| <div class="stepper-step" data-step="2"> | |
| <div class="step-num step-red">2</div> | |
| <div class="step-details"> | |
| <h3>Self-Attention</h3> | |
| <p>Multi-Head token interaction</p> | |
| </div> | |
| </div> | |
| <div class="stepper-step" data-step="3"> | |
| <div class="step-num step-yellow">3</div> | |
| <div class="step-details"> | |
| <h3>Mean Pooling</h3> | |
| <p>Dense vector fingerprint</p> | |
| </div> | |
| </div> | |
| <div class="stepper-step" data-step="4"> | |
| <div class="step-num step-green">4</div> | |
| <div class="step-details"> | |
| <h3>2D Space & k-NN</h3> | |
| <p>PCA Manifold & Class Regions</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Main Content Grid --> | |
| <main class="main-grid"> | |
| <!-- Left Column: Interactive Controls --> | |
| <div class="left-column"> | |
| <!-- Training Dataset Management Card --> | |
| <section class="panel-card"> | |
| <div class="panel-header"> | |
| <h2>1. Training Dataset</h2> | |
| <span id="dataset-count" class="badge-neutral">0 examples</span> | |
| </div> | |
| <!-- Add Example Form --> | |
| <form id="add-example-form" class="add-form"> | |
| <div class="form-group"> | |
| <label for="example-text">Text Example</label> | |
| <input type="text" id="example-text" placeholder="e.g. The service was fast and super friendly!" | |
| required /> | |
| </div> | |
| <div class="form-group"> | |
| <label for="example-label">Class Label</label> | |
| <div class="label-input-group"> | |
| <input type="text" id="example-label" placeholder="e.g. positive" required /> | |
| <div class="preset-badges"> | |
| <button type="button" class="preset-badge badge-positive" | |
| data-label="positive">positive</button> | |
| <button type="button" class="preset-badge badge-negative" | |
| data-label="negative">negative</button> | |
| <button type="button" class="preset-badge badge-neutral" | |
| data-label="neutral">neutral</button> | |
| </div> | |
| </div> | |
| </div> | |
| <button type="submit" class="btn btn-secondary">+ Add Example</button> | |
| </form> | |
| <!-- Dataset Example List --> | |
| <div class="dataset-section"> | |
| <div class="dataset-actions"> | |
| <h3>Current Memory Dataset</h3> | |
| <div class="btn-group"> | |
| <button type="button" id="reset-demo-btn" class="btn btn-sm btn-outline">Reset Demo | |
| Dataset</button> | |
| <button type="button" id="clear-dataset-btn" class="btn btn-sm btn-outline-danger">Clear | |
| All</button> | |
| </div> | |
| </div> | |
| <div id="dataset-list" class="dataset-list"> | |
| <!-- Populated dynamically by demo.js --> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Inference & Prediction Card --> | |
| <section class="panel-card"> | |
| <div class="panel-header"> | |
| <h2>2. Run Inference</h2> | |
| </div> | |
| <div class="inference-form"> | |
| <div class="form-group"> | |
| <label for="test-text">Test Input Sentence</label> | |
| <textarea id="test-text" rows="2" | |
| placeholder="Type any sentence to test classification..."></textarea> | |
| </div> | |
| <div class="form-row"> | |
| <div class="form-group inline"> | |
| <label for="k-value">Neighbors (k):</label> | |
| <input type="number" id="k-value" value="3" min="1" max="10" /> | |
| </div> | |
| <button type="button" id="predict-btn" class="btn btn-primary">Classify Text</button> | |
| </div> | |
| </div> | |
| <!-- Prediction Result Display --> | |
| <div id="result-box" class="result-box" style="display: none;"> | |
| <div class="result-header"> | |
| <div class="result-main"> | |
| <span class="result-title">Predicted Class:</span> | |
| <div id="predicted-label"></div> | |
| </div> | |
| <div class="confidence-box"> | |
| <span class="confidence-label">Confidence: <strong id="confidence-val">--</strong></span> | |
| <div class="confidence-track"> | |
| <div id="confidence-fill" class="confidence-fill" style="width: 0%;"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="vector-preview" class="vector-preview"></div> | |
| <!-- Top k Neighbors Breakdown --> | |
| <div class="neighbors-section"> | |
| <h4>Nearest Neighbor Votes</h4> | |
| <div id="neighbors-list" class="neighbors-list"></div> | |
| </div> | |
| </div> | |
| </section> | |
| </div> | |
| <!-- Right Column: Architecture & Logs --> | |
| <div class="right-column"> | |
| <!-- Activity Log Card --> | |
| <section class="panel-card log-panel"> | |
| <div class="panel-header"> | |
| <h2>Activity Console</h2> | |
| <span class="live-tag">LIVE</span> | |
| </div> | |
| <div id="log-output" class="log-output"> | |
| <!-- Streamed console output --> | |
| </div> | |
| </section> | |
| <!-- Architecture Summary Card --> | |
| <section class="panel-card info-card"> | |
| <div class="panel-header"> | |
| <h2>Architecture Specs</h2> | |
| </div> | |
| <ul class="specs-list"> | |
| <li><strong>Active Model:</strong> <code id="spec-model-name">Xenova/all-MiniLM-L6-v2</code></li> | |
| <li><strong>Runtime:</strong> ONNX Runtime Web via Transformers.js</li> | |
| <li><strong>Embedding Dimension:</strong> <span id="spec-embed-dim">384</span></li> | |
| <li><strong>Pooling Strategy:</strong> Mean pooling with L2 normalization</li> | |
| <li><strong>Classifier:</strong> k-Nearest Neighbors (Euclidean Distance)</li> | |
| </ul> | |
| </section> | |
| </div> | |
| </main> | |
| <!-- Full-Width Interactive Architecture & Storytelling Visualizer Section --> | |
| <section class="viz-storytelling-section"> | |
| <div class="section-title-row"> | |
| <div> | |
| <h2>Deep Learning Visual Explorers</h2> | |
| <p>Interactive step-by-step breakdown inspired by Transformer Explainer & GAN Lab</p> | |
| </div> | |
| </div> | |
| <div class="viz-grid"> | |
| <!-- Viz 1: Subword Tokenizer --> | |
| <div class="panel-card viz-card" id="viz-step-1"> | |
| <div class="panel-header"> | |
| <h2>Stage 1: Subword Tokenization</h2> | |
| <span class="badge label-custom">WordPiece / BPE</span> | |
| </div> | |
| <p class="viz-desc">Input text is mapped into discrete subword token IDs and positional indices.</p> | |
| <div id="tokenizer-viz-container" class="viz-container"></div> | |
| </div> | |
| <!-- Viz 2: Self-Attention Matrix --> | |
| <div class="panel-card viz-card" id="viz-step-2"> | |
| <div class="panel-header"> | |
| <h2>Stage 2: Self-Attention Matrix & QKV Arcs</h2> | |
| <span class="badge badge-negative">Softmax(QK<sup>T</sup>/√d)V</span> | |
| </div> | |
| <p class="viz-desc">Tokens attend to each other across Multi-Head Self-Attention layers to capture | |
| contextual meaning.</p> | |
| <div id="attn-arcs-container" class="attn-arcs-wrapper"></div> | |
| <div id="attention-viz-container" class="viz-container"></div> | |
| </div> | |
| <!-- Viz 3: Pooling & Embedding Fingerprint Barcode --> | |
| <div class="panel-card viz-card" id="viz-step-3"> | |
| <div class="panel-header"> | |
| <h2>Stage 3: Sentence Embedding Fingerprint</h2> | |
| <span class="badge badge-neutral">Mean Pooling & L2 Norm</span> | |
| </div> | |
| <p class="viz-desc">Token vectors are collapsed into a dense 1D fingerprint representing the entire | |
| sentence's semantics.</p> | |
| <div id="pooling-viz-container" class="viz-container"></div> | |
| </div> | |
| <!-- Viz 4: 2D Embedding Space & Decision Boundary Canvas (GAN Lab style) --> | |
| <div class="panel-card viz-card full-width-viz" id="viz-step-4"> | |
| <div class="panel-header"> | |
| <div> | |
| <h2>Stage 4: 2D Embedding Space & k-NN Decision Boundaries</h2> | |
| <p class="viz-desc">High-dimensional embeddings projected to 2D via PCA. Background shows memory | |
| class zones; click canvas to query!</p> | |
| </div> | |
| <div id="pca-legend" class="pca-legend"></div> | |
| </div> | |
| <div class="canvas-wrapper"> | |
| <canvas id="pca-canvas" width="760" height="420"></canvas> | |
| <div class="canvas-hint-overlay"> | |
| <span>💡 Click anywhere on canvas to test a 2D vector coordinate query</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <footer class="app-footer"> | |
| <p>Built with <a href="https://github.com/xenova/transformers.js" target="_blank" rel="noopener">Transformers.js</a> | |
| </p> | |
| </footer> | |
| </div> | |
| <!-- Main Module Script --> | |
| <script type="module" src="demo.js"></script> | |
| </body> | |
| </html> |