Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| <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')">×</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')">×</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> |