ai-lab / templates /cbow.html
ClemSummer's picture
UI Enhancements
f66e5e6
raw
history blame
10.1 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<title>CBOW Vector Calculator</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: auto;
padding: 1rem;
background-color: #f8f9fa;
position: relative;
}
h2 {
text-align: center;
}
form {
margin-top: 2rem;
}
textarea {
width: 100%;
height: 80px;
padding: 0.5rem;
font-size: 1rem;
resize: vertical;
}
button {
margin-top: 1rem;
width: 100%;
padding: 0.75rem;
font-size: 1rem;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
.results {
margin-top: 2rem;
background-color: white;
padding: 1rem;
border-radius: 6px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.result-row {
margin: 0.5rem 0;
}
.result-word {
font-weight: bold;
}
.score {
color: #666;
margin-left: 0.5rem;
}
.floating-icons {
position: fixed;
bottom: 1rem;
right: 1rem;
display: flex;
gap: 1rem;
}
.icon-button {
background: white;
border: 1px solid #ccc;
border-radius: 50%;
width: 40px;
height: 40px;
font-size: 1.2rem;
text-align: center;
line-height: 40px;
cursor: pointer;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0; top: 0;
width: 100%; height: 100%;
background-color: rgba(0,0,0,0.4);
}
.use-suggestion {
margin-left: 8px;
padding: 2px 6px;
font-size: 0.8rem;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.use-suggestion:hover {
background-color: #0056b3;
}
.modal-content {
background-color: #fff;
margin: 10% auto;
padding: 2rem;
border-radius: 8px;
max-width: 400px;
position: relative;
}
.close {
position: absolute;
top: 0.5rem;
right: 0.75rem;
font-size: 1.2rem;
cursor: pointer;
}
</style>
</head>
<body>
<a href="/" class="absolute top-4 left-4 text-blue-600 hover:text-blue-800 text-sm font-semibold flex items-center">
<!-- back arrow -->
<svg class="w-5 h-5 mr-1" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7"></path>
</svg>
Back to Home
</a>
<h2>CBOW Vector Calculator</h2>
<form method="post" action="/cbow">
<label for="expression">Enter a word vector expression <small>(e.g. <code>king - man + woman</code>)</small>:</label><br>
<textarea name="expression" rows="4" style="width: 100%">{{ expression or "" }}</textarea>
<button type="submit">Calculate</button>
</form>
{% if results %}
<div class="results">
{% if results and results|length > 0 %}
<p><strong>{{ expression }}</strong><strong>{{ results[0][0] }}</strong></p>
{% endif %}
<h3>Results:</h3>
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr>
<th style="text-align: left; padding: 0.5rem; border-bottom: 1px solid #ccc;">#</th>
<th style="text-align: left; padding: 0.5rem; border-bottom: 1px solid #ccc;">Result</th>
<th style="text-align: left; padding: 0.5rem; border-bottom: 1px solid #ccc;">Score</th>
</tr>
</thead>
<tbody>
{% for word, score in results %}
<tr>
<td style="padding: 0.5rem;">{{ loop.index }}</td>
<td style="padding: 0.5rem;">{{ word }}</td>
<td style="padding: 0.5rem;">
{% if score >= 0.4 %}
{{ "%.2f"|format(score) }}
{% else %}
Irrelevant result
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<div class="floating-icons">
<div class="icon-button" onclick="openModal('suggestionsModal')">💡</div>
<div class="icon-button" onclick="openModal('aboutModal')">?</div>
</div>
<div id="suggestionsModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeModal('suggestionsModal')">&times;</span>
<h3>Suggestions</h3>
<p>What's your guess, before calculating it?</p>
<ul id="suggestions-list"></ul>
<p><strong>Tips:</strong></p>
<ul>
<li>Use <code>-</code> and <code>+</code> operators, with a space before and after each operator.</li>
<li>Link compound words with a hyphen, e.g., <code>new-york</code>.</li>
<li>Got a fun suggestion? Email: <a href="mailto:[email protected]">[email protected]</a></li>
</ul>
</div>
</div>
<div id="aboutModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeModal('aboutModal')">&times;</span>
<h3>About</h3>
<p>This tool calculates vector arithmetic of words using a pretrained CBOW model glove-twitter-200.</p>
</div>
</div>
<script>
function openModal(id) {
document.getElementById(id).style.display = 'block';
}
function closeModal(id) {
document.getElementById(id).style.display = 'none';
}
window.onclick = function(event) {
const modals = document.querySelectorAll('.modal');
modals.forEach(modal => {
if (event.target == modal) {
modal.style.display = "none";
}
});
}
</script>
<script>
document.addEventListener("DOMContentLoaded", function () {
const textarea = document.querySelector("textarea[name='expression']");
const form = document.querySelector("form");
textarea.addEventListener("keydown", function (event) {
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault(); // prevent newline
form.submit(); // trigger form submission
}
});
});
</script>
<script>
document.addEventListener("DOMContentLoaded", function () {
const form = document.querySelector("form");
const textarea = document.querySelector("textarea[name='expression']");
let resultShown = {{ 'true' if results else 'false' }};
// 1. Validate spacing between tokens
form.addEventListener("submit", function (event) {
const input = textarea.value.trim();
// Simple regex to find missing spaces (e.g., "word+word", "word-word")
const spacingIssues = input.match(/\b\w+[\+\-]\w+\b/);
if (spacingIssues) {
event.preventDefault();
const problem = spacingIssues[0];
const suggestion = problem.replace(/([\+\-])/, ' $1 ');
alert(`⚠️ It looks like you missed spacing in: "${problem}".\nDid you mean: "${suggestion}"?`);
}
});
// 2. Clear textarea when focused again, only if result was shown
if (resultShown) {
textarea.addEventListener("focus", () => {
textarea.value = "";
resultShown = false; // prevent it from clearing again on next focus
});
}
});
</script>
<script>
document.addEventListener("DOMContentLoaded", function () {
const textarea = document.querySelector("textarea[name='expression']");
const modal = document.getElementById("suggestionsModal");
const suggestions = [
"mother - woman + man",
"iphone - phone + tablet",
"hotdog - sausage + beef",
"brisbane - city + capital",
"uk - monarchy",
"kfc - chicken + pork",
"skoda - czech + germany",
"starwars - darthvader + sauron",
"callofduty - gun + knife"
];
const list = document.getElementById("suggestions-list");
// Build the list dynamically
suggestions.forEach(suggestion => {
const li = document.createElement("li");
li.innerHTML = `<code>${suggestion}</code>
<button type="button" class="use-suggestion">Use</button>`;
li.querySelector("button").addEventListener("click", function () {
textarea.value = suggestion; // fill textarea
textarea.focus(); // optional
modal.style.display = "none"; // auto close modal
});
list.appendChild(li);
});
});
</script>
</body>
</html>