Spaces:
Sleeping
Sleeping
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Continuous Thought Machine - MNIST</title> | |
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>Continuous Thought Machine - MNIST Classifier</h1> | |
<p>Upload a grayscale image of a handwritten digit (0-9) to classify it using the CTM model, or train a new model.</p> | |
<h2>Predict</h2> | |
<form action="/predict" method="post" enctype="multipart/form-data"> | |
<input type="file" name="file" accept="image/*" required> | |
<button type="submit">Predict</button> | |
</form> | |
<h2>Train Model</h2> | |
{% if training_status.status == 'running' %} | |
<p>Training in progress: {{ training_status.message }}</p> | |
<p>Progress: {{ training_status.progress | round(2) }}%</p> | |
{% elif training_status.status == 'completed' %} | |
<p>Training completed: {{ training_status.message }}</p> | |
{% elif training_status.status == 'error' %} | |
<p class="error">Training failed: {{ training_status.message }}</p> | |
{% endif %} | |
<form id="train-form" action="/train" method="post"> | |
<label for="iterations">Iterations (100-5000):</label> | |
<input type="number" name="iterations" id="iterations" value="1000" min="100" max="5000" required> | |
<label for="lr">Learning Rate (1e-6 to 1e-2):</label> | |
<input type="number" name="lr" id="lr" value="0.0001" step="0.00001" min="0.000001" max="0.01" required> | |
<button type="submit" {% if training_status.status == 'running' %}disabled{% endif %}>Start Training</button> | |
</form> | |
{% if error %} | |
<p class="error">{{ error }}</p> | |
{% endif %} | |
{% if prediction is defined %} | |
<h2>Results</h2> | |
<p><strong>Predicted Digit:</strong> {{ prediction }}</p> | |
<p><strong>Certainty:</strong> {{ certainty }}</p> | |
<h3>CTM Dynamics Visualization</h3> | |
<img src="{{ url_for('static', filename=gif_path.replace('static/', '')) }}" alt="CTM Dynamics" style="max-width: 100%;"> | |
{% endif %} | |
</div> | |
<script> | |
// Poll training status every 5 seconds | |
function checkTrainingStatus() { | |
fetch('/training_status') | |
.then(response => response.json()) | |
.then(data => { | |
if (data.status === 'running') { | |
document.querySelector('#train-form button').disabled = true; | |
document.querySelector('#train-form').insertAdjacentHTML('beforebegin', | |
`<p>Training in progress: ${data.message}</p><p>Progress: ${data.progress.toFixed(2)}%</p>`); | |
setTimeout(checkTrainingStatus, 5000); | |
} else { | |
document.querySelector('#train-form button').disabled = false; | |
if (data.status === 'completed') { | |
document.querySelector('#train-form').insertAdjacentHTML('beforebegin', | |
`<p>Training completed: ${data.message}</p>`); | |
} else if (data.status === 'error') { | |
document.querySelector('#train-form').insertAdjacentHTML('beforebegin', | |
`<p class="error">Training failed: ${data.message}</p>`); | |
} | |
} | |
}); | |
} | |
// Start polling if training is in progress | |
{% if training_status.status == 'running' %} | |
checkTrainingStatus(); | |
{% endif %} | |
// Handle form submission | |
document.getElementById('train-form').addEventListener('submit', function(e) { | |
e.preventDefault(); | |
fetch('/train', { | |
method: 'POST', | |
body: new FormData(this) | |
}) | |
.then(response => response.json()) | |
.then(data => { | |
if (data.error) { | |
alert(data.error); | |
} else { | |
alert(data.message); | |
checkTrainingStatus(); | |
} | |
}) | |
.catch(error => alert('Error starting training: ' + error)); | |
}); | |
</script> | |
</body> | |
</html> |