| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <title>Sentence Transformers: Fact or Fiction</title> |
| <link rel="preconnect" href="https://fonts.gstatic.com" /> |
| <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;600&display=swap" rel="stylesheet"> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <style> |
| * { margin: 0; padding: 0; box-sizing: border-box; } |
| :root { |
| --bg1:#c9e8ff; --bg2:#fde2ff; --ink:#222; --ink-sub:#555; |
| --brand:#2563eb; --brand-2:#22c55e; |
| --card:#ffffffcc; |
| } |
| body { |
| font-family: 'Poppins', sans-serif; |
| background: radial-gradient(1200px 600px at 20% 0%, var(--bg1), transparent 60%), |
| radial-gradient(1200px 600px at 80% 0%, var(--bg2), transparent 60%), |
| #f6f7fb; |
| min-height: 100vh; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| justify-content: flex-start; |
| padding: 2rem 1rem; |
| color: var(--ink); |
| } |
| h1 { text-align: center; margin-bottom: .25rem; font-weight: 600; font-size: 2.2rem; } |
| #subtitle { text-align:center; margin-bottom:1rem; color: var(--ink-sub); } |
| #source-link { text-align: center; margin-bottom: 1.25rem; font-size: .95rem; } |
| #source-link a { color: var(--ink); text-decoration: underline; } |
| #game-container { |
| background: var(--card); |
| width: 100%; max-width: 860px; |
| padding: 2rem; border-radius: 16px; |
| box-shadow: 0 10px 24px rgba(0,0,0,.15); |
| display: flex; flex-direction: column; align-items: center; |
| } |
| .progress-container { |
| width: 100%; background:#ececec; border-radius: 999px; overflow: hidden; margin-bottom: 1rem; |
| } |
| .progress-bar { height: 14px; width:0%; background: linear-gradient(90deg,var(--brand),var(--brand-2)); transition: width .3s ease; } |
| #statement { |
| font-size: 1.25rem; line-height: 1.5; text-align: center; color: #333; |
| min-height: 96px; margin: .75rem 0 1rem; |
| } |
| .btn-group { display:flex; gap:.75rem; flex-wrap:wrap; justify-content:center; margin: .25rem 0 1rem; } |
| button { |
| padding: .75rem 1.25rem; border: none; border-radius: 999px; cursor: pointer; |
| background: var(--brand); color: #fff; font-weight: 600; letter-spacing:.2px; |
| transition: transform .15s ease, box-shadow .15s ease, background .2s ease; |
| } |
| button.secondary { background:#111827; } |
| button:hover { transform: translateY(-2px); box-shadow: 0 8px 18px rgba(0,0,0,.15); } |
| #result { |
| margin-top: .5rem; padding: .75rem 1rem; border-radius: 10px; font-weight: 700; text-align: center; display:none; |
| } |
| #result.correct { display:block; background:#dcfce7; color:#14532d; } |
| #result.incorrect { display:block; background:#fee2e2; color:#7f1d1d; } |
| #explanation { |
| margin-top: .75rem; padding: 1rem; background:#f9fafb; color:#374151; border-radius:12px; display:none; |
| } |
| #score { margin-top: .75rem; font-weight: 700; } |
| #controls { display:flex; gap:.5rem; margin-top:.5rem; } |
| #controls button { background:#0f766e; } |
| #restart-btn { background:#6b21a8; } |
| </style> |
| </head> |
| <body> |
| <h1>Sentence Transformers: Fact or Fiction</h1> |
| <div id="subtitle">Test your understanding of cosine similarity, vector space behavior, and why STs beat vanilla BERT for sentence similarity.</div> |
| <div id="source-link"> |
| Source: <a href="https://www.linkedin.com/pulse/bert-vs-sentence-transformers-why-semantic-similarity-michael-lively-ifw7e/" target="_blank" rel="noopener"> |
| BERT vs Sentence Transformers — Why Semantic Similarity Needs a Different Approach |
| </a> |
| </div> |
|
|
| <div id="game-container" role="region" aria-label="Fact or Fiction game"> |
| <div class="progress-container" aria-hidden="true"><div class="progress-bar" id="progress-bar"></div></div> |
| <div id="statement" aria-live="polite">Loading statement...</div> |
|
|
| <div class="btn-group"> |
| <button onclick="guess(true)" aria-label="Choose Fact">Fact</button> |
| <button class="secondary" onclick="guess(false)" aria-label="Choose Fiction">Fiction</button> |
| </div> |
|
|
| <div id="result" role="status" aria-live="polite"></div> |
| <div id="explanation"></div> |
|
|
| <div id="controls"> |
| <button id="next-btn" style="display:none;" onclick="nextStatement()">Next</button> |
| <button id="restart-btn" style="display:none;" onclick="startGame()">Restart</button> |
| </div> |
|
|
| <div id="score" aria-live="polite"></div> |
| </div> |
|
|
| <script> |
| |
| |
| const statements = [ |
| |
| { |
| text: "BERT excels at token-level understanding but was not designed to measure sentence-level similarity.", |
| isFact: true, |
| explanation: "The paper notes BERT’s strengths (NER, QA, sentiment) and its weakness for sentence similarity." |
| }, |
| { |
| text: "BERT’s sentence embeddings often exhibit anisotropy, clustering in a narrow cone that blunts cosine similarity.", |
| isFact: true, |
| explanation: "The narrative explains the cone-like collapse, making many sentences appear similarly close." |
| }, |
| { |
| text: "Sentence Transformers are fine-tuned with contrastive-style objectives to pull similar sentences together and push dissimilar ones apart.", |
| isFact: true, |
| explanation: "They learn directly from similarity tasks (contrastive/triplet losses)." |
| }, |
| { |
| text: "With Sentence Transformers, paraphrases form tight clusters while unrelated sentences separate, making cosine similarity meaningful.", |
| isFact: true, |
| explanation: "The text highlights high cosine for paraphrases and low cosine for unrelated pairs." |
| }, |
| { |
| text: "Pre-encoding large corpora with Sentence Transformers enables efficient one-to-many retrieval using cosine similarity.", |
| isFact: true, |
| explanation: "Queries are encoded once and compared against stored vectors—far faster than pairwise cross-encoders." |
| }, |
| { |
| text: "Applying clustering to Sentence Transformer embeddings reveals coherent topic groups that raw BERT embeddings fail to separate.", |
| isFact: true, |
| explanation: "The narrative describes interpretability at scale via clustering with ST embeddings." |
| }, |
| |
| |
| { |
| text: "BERT’s original training objective explicitly makes semantically similar sentences close in vector space.", |
| isFact: false, |
| explanation: "False. MLM and NSP do not enforce sentence-level proximity." |
| }, |
| { |
| text: "In practice, random sentence pairs tend to have very low cosine similarity when using BERT embeddings.", |
| isFact: false, |
| explanation: "False. The narrative states many pairs score similarly high due to anisotropy." |
| }, |
| { |
| text: "Sentence Transformers require pairwise cross-encoder inference for every query-document combination.", |
| isFact: false, |
| explanation: "False. STs produce independent embeddings so you avoid pairwise model runs." |
| }, |
| { |
| text: "Once you adopt Sentence Transformers, cosine similarity is no longer useful for retrieval.", |
| isFact: false, |
| explanation: "False. Cosine similarity becomes more meaningful and is central to retrieval efficiency." |
| }, |
| { |
| text: "Semantic search with Sentence Transformers still depends mainly on exact keyword overlap.", |
| isFact: false, |
| explanation: "False. The point is to match meaning, not just words—overcoming keyword limits." |
| }, |
| { |
| text: "BERT’s embedding space is already evenly spread (isotropic), so additional fine-tuning brings little benefit.", |
| isFact: false, |
| explanation: "False. The text explains BERT’s anisotropy and why ST fine-tuning reshapes the space." |
| } |
| ]; |
| |
| |
| let deck = []; |
| let currentIndex = 0, score = 0, answered = false; |
| |
| function shuffle(arr) { |
| for (let i = arr.length - 1; i > 0; i--) { |
| const j = Math.floor(Math.random() * (i + 1)); |
| [arr[i], arr[j]] = [arr[j], arr[i]]; |
| } |
| } |
| |
| function startGame() { |
| |
| |
| deck = [...statements]; |
| shuffle(deck); |
| currentIndex = 0; score = 0; answered = false; |
| document.getElementById('restart-btn').style.display = 'none'; |
| loadStatement(); updateScore(); updateProgress(); |
| } |
| |
| function loadStatement() { |
| if (currentIndex >= deck.length) return endGame(); |
| const s = deck[currentIndex]; |
| document.getElementById('statement').textContent = s.text; |
| |
| const resultEl = document.getElementById('result'); |
| resultEl.style.display = 'none'; |
| resultEl.textContent = ''; |
| resultEl.className = ''; |
| |
| const expEl = document.getElementById('explanation'); |
| expEl.style.display = 'none'; |
| expEl.textContent = ''; |
| |
| document.getElementById('next-btn').style.display = 'none'; |
| answered = false; |
| updateProgress(); |
| } |
| |
| function guess(isFactGuess) { |
| if (answered) return; |
| answered = true; |
| |
| const correct = deck[currentIndex].isFact; |
| const resultEl = document.getElementById('result'); |
| |
| if (isFactGuess === correct) { |
| resultEl.textContent = 'Correct!'; |
| resultEl.className = 'correct'; |
| score++; |
| } else { |
| resultEl.textContent = 'Incorrect!'; |
| resultEl.className = 'incorrect'; |
| } |
| resultEl.style.display = 'block'; |
| |
| const expEl = document.getElementById('explanation'); |
| expEl.innerHTML = deck[currentIndex].explanation + |
| ' — <a href="https://www.linkedin.com/pulse/bert-vs-sentence-transformers-why-semantic-similarity-michael-lively-ifw7e/" target="_blank" rel="noopener">link</a>'; |
| expEl.style.display = 'block'; |
| |
| document.getElementById('next-btn').style.display = 'inline-block'; |
| updateScore(); |
| } |
| |
| function nextStatement() { |
| currentIndex++; |
| if (currentIndex < deck.length) loadStatement(); |
| else endGame(); |
| } |
| |
| function updateScore() { |
| document.getElementById('score').textContent = `Score: ${score} / ${deck.length}`; |
| } |
| |
| function updateProgress() { |
| const pct = Math.round((currentIndex / deck.length) * 100); |
| document.getElementById('progress-bar').style.width = pct + '%'; |
| } |
| |
| function endGame() { |
| const pct = Math.round((score / deck.length) * 100); |
| document.getElementById('statement').textContent = |
| `Game Over! You scored ${score} of ${deck.length} (${pct}%).`; |
| document.getElementById('result').style.display = 'none'; |
| document.getElementById('explanation').style.display = 'none'; |
| document.getElementById('next-btn').style.display = 'none'; |
| document.getElementById('restart-btn').style.display = 'inline-block'; |
| document.getElementById('progress-bar').style.width = '100%'; |
| } |
| |
| startGame(); |
| </script> |
| </body> |
| </html> |
|
|