tokenprob / static /script.js
PhilippSpohn's picture
Initial commit for HF Spaces deployment
3bd5de9
document.getElementById("analyze-button").addEventListener("click", async () => {
const text = document.getElementById("input-text").value;
const model = document.getElementById("model-select").value;
// Show loading state
const analyzeButton = document.getElementById("analyze-button");
const buttonSpinner = analyzeButton.querySelector(".button-spinner");
analyzeButton.classList.add("loading");
buttonSpinner.classList.add("visible");
analyzeButton.disabled = true;
try {
const response = await fetch("/analyze", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ text, model })
});
const data = await response.json();
const coloredTextDiv = document.getElementById("colored-text");
coloredTextDiv.innerHTML = "";
// Always add the first token
const firstToken = data.tokens[0];
const firstTokenSpan = document.createElement("span");
firstTokenSpan.classList.add("token");
// Handle special tokens and regular tokens differently
if (firstToken === "<s>" || firstToken === "<|endoftext|>") {
firstTokenSpan.style.backgroundColor = "#808080"; // Gray for special tokens
firstTokenSpan.textContent = "■";
tippy(firstTokenSpan, {
content: "<div><strong>Beginning of Sequence</strong></div>",
allowHTML: true,
theme: 'custom',
placement: 'top',
interactive: true
});
} else {
// Handle regular first token
firstTokenSpan.style.backgroundColor = "#808080"; // or any other color you prefer
firstTokenSpan.textContent = firstToken;
tippy(firstTokenSpan, {
content: `<div><strong>First Token</strong></div>`,
allowHTML: true,
theme: 'custom',
placement: 'top',
interactive: true
});
}
coloredTextDiv.appendChild(firstTokenSpan);
for (let index = 0; index < data.log_probs.length; index++) {
const token = data.tokens[index + 1];
const percentile = data.percentiles[index];
const logProb = data.log_probs[index];
const topKPredictions = data.top_k_predictions[index];
const color = getColor(data.log_probs, logProb);
const tokenSpan = document.createElement("span");
tokenSpan.classList.add("token");
tokenSpan.style.backgroundColor = color;
let displayToken = token;
let specialTokenDescription = "";
// Enhanced special token handling
if (token === "<s>" || token === "<|endoftext|>") {
displayToken = "■";
specialTokenDescription = "Beginning of Sequence";
} else if (token === "</s>" || token === "<|endoftext|>") {
displayToken = "■";
specialTokenDescription = "End of Sequence";
} else if (token === "<0x0A>") {
displayToken = "■";
specialTokenDescription = "Newline";
} else if (token.startsWith("<") && token.endsWith(">")) {
displayToken = "■";
specialTokenDescription = "Special Token: " + token;
} else {
// Clean up GPT-2 style tokens (Ġ and Ċ)
displayToken = displayToken
.replace(/\u2581/g, " ") // Replace underscore token
.replace(/Ġ/g, " ") // Replace GPT-2 space token
.replace(/Ċ/g, "\n"); // Replace GPT-2 newline token
}
tokenSpan.textContent = displayToken;
let tooltipContent = "";
if (specialTokenDescription) {
tooltipContent += `<div style="font-weight: bold; margin-bottom: 8px;">${specialTokenDescription}</div>`;
}
tooltipContent += `<div style="font-weight: bold; margin-bottom: 4px;">Top 5 Predictions:</div>`;
topKPredictions.forEach(pred => {
let predToken = pred.token;
if (predToken === "<0x0A>") {
predToken = "\\n";
} else if (predToken.startsWith("<") && predToken.endsWith(">")) {
predToken = "[SPECIAL]";
} else {
predToken = predToken
.replace(/\u2581/g, " ")
.replace(/Ġ/g, " ")
.replace(/Ċ/g, "\n");
}
tooltipContent += `<div style="padding-left: 8px;">${predToken}: ${pred.log_prob.toFixed(4)}</div>`;
});
tooltipContent += `<div style="margin-top: 8px; border-top: 1px solid #555; padding-top: 8px;">
<div><strong>Stats:</strong></div>
<div style="padding-left: 8px;">Percentile: ${percentile.toFixed(2)}</div>
<div style="padding-left: 8px;">Log-Likelihood: ${logProb.toFixed(4)}</div>
</div>`;
tippy(tokenSpan, {
content: tooltipContent,
allowHTML: true,
theme: 'custom',
placement: 'top',
interactive: true
});
coloredTextDiv.appendChild(tokenSpan);
if (token === "<0x0A>") {
coloredTextDiv.appendChild(document.createElement("br"));
}
}
document.getElementById("joint-log-likelihood").textContent = data.joint_log_likelihood.toFixed(4);
document.getElementById("average-log-likelihood").textContent = data.average_log_likelihood.toFixed(4);
} catch (error) {
console.error("Error during analysis:", error);
alert("An error occurred during analysis. Please try again.");
} finally {
// Hide loading state
analyzeButton.classList.remove("loading");
buttonSpinner.classList.remove("visible");
analyzeButton.disabled = false;
}
});
function getColor(allLogProbs, currentLogProb) {
const minLogProb = Math.min(...allLogProbs);
const maxLogProb = Math.max(...allLogProbs);
// Normalize to 0-1 range
let normalizedLogProb = (currentLogProb - minLogProb) / (maxLogProb - minLogProb);
normalizedLogProb = Math.max(0, Math.min(1, normalizedLogProb)); // Clamp
// Optional: Apply a power transformation (adjust the exponent as needed)
const power = 0.7; // Example: Less than 1 emphasizes differences at lower end
normalizedLogProb = Math.pow(normalizedLogProb, power);
const hue = normalizedLogProb * 120; // 0 (red) to 120 (green)
return `hsl(${hue}, 100%, 50%)`;
}