eaglelandsonce's picture
Update index.html
c769b22 verified
Raw
History Blame Contribute Delete
11.3 kB
<!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>
// ==== Content-derived statements (12 total: 6 Fact, 6 Fiction) ====
// Drawn from your narrative; negatives are crafted as clear counterclaims.
const statements = [
// ---------- FACTS (6) ----------
{
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."
},
// ---------- FICTIONS (6) ----------
{
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."
}
];
// ---- Game state ----
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() {
// Ensure even distribution by construction (6 true, 6 false).
// Then randomize order each run.
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>