moody-lyrics / frontend /index.html
dhruthick's picture
added feedback option to frontend
2c18e92
raw
history blame
13.2 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Moody Lyrics</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Lora:wght@400;700&family=Playfair+Display:wght@400;700&display=swap');
body {
font-family: 'Lora', serif;
background: linear-gradient(135deg, #f3ec78, #af4261);
color: #333;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
transition: background 1s ease-in-out; /* Smooth gradient transition */
}
.container {
background: rgba(255, 255, 255, 0.9);
padding: 30px;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
max-width: 700px;
width: 100%;
text-align: center;
overflow-y: auto;
max-height: 90vh;
transition: background-color 0.5s ease-in-out;
display: flex;
flex-direction: column;
gap: 20px;
}
h1 {
color: #2c3e50;
font-size: 2.5em;
margin-bottom: 20px;
font-family: 'Playfair Display', serif;
}
form {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
input[type="text"] {
padding: 15px;
width: 80%;
border: 2px solid #2c3e50;
border-radius: 10px;
font-size: 1em;
transition: border-color 0.3s;
font-family: 'Lora', serif;
}
input[type="text"]:focus {
border-color: #2980b9;
outline: none;
}
button {
padding: 15px 40px;
background-color: #af4261;
color: #fff;
border: none;
border-radius: 10px;
font-size: 1.2em;
cursor: pointer;
transition: background-color 0.3s, transform 0.3s;
font-family: 'Lora', serif;
}
button:hover {
background-color: #f3ec78;
color: #af4261;
transform: translateY(-2px);
}
#mood-result {
margin-top: 20px;
font-size: 1.5em;
color: #2980b9;
}
#mood-chart {
max-width: 100%;
height: 300px;
}
pre {
background: rgba(244, 244, 249, 0.9);
padding: 20px;
border-radius: 10px;
white-space: pre-wrap;
word-wrap: break-word;
margin-top: 20px;
font-family: 'Courier New', Courier, monospace;
text-align: left;
transition: background-color 0.5s ease-in-out;
}
#results-container {
margin-top: 20px;
padding: 20px;
border-radius: 10px;
transition: background-color 0.5s ease-in-out;
}
.footer {
margin-top: 20px;
font-size: 0.9em;
color: #555;
text-align: center;
}
#more-info {
display: none;
max-height: 0;
overflow: hidden;
transition: max-height 0.5s ease-out, opacity 0.5s ease-out;
opacity: 0;
text-align: left;
font-size: 0.9em;
color: #333;
padding: 20px;
border-radius: 10px;
background: rgba(244, 244, 249, 0.9);
}
#more-info.show {
display: block;
max-height: 500px; /* Adjust as needed */
opacity: 1;
}
#more-info-link {
color: #333; /* Match the rest of the text color */
cursor: pointer;
text-decoration: underline;
}
.spinner {
display: flex;
justify-content: center;
align-items: center;
height: 100px;
margin-top: 20px;
}
.spinner-border {
width: 3rem;
height: 3rem;
border: 0.3em solid rgba(0, 0, 0, 0.1);
border-radius: 50%;
border-top-color: #af4261;
animation: spin 0.75s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
#accuracy-test {
display: none;
margin-top: 20px;
text-align: center;
}
#accuracy-test button {
padding: 10px 20px;
margin: 0 10px;
font-size: 1em;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<h1>Moody Lyrics</h1>
<form id="mood-form">
<input type="text" id="title" placeholder="Song Title" required>
<input type="text" id="artist" placeholder="Artist" required>
<button type="submit">Predict Mood</button>
</form>
<div id="results-container">
<h2 id="mood-result"></h2>
<div id="spinner" class="spinner" style="display: none;">
<div class="spinner-border" role="status"></div>
</div>
<canvas id="mood-chart"></canvas>
<pre id="lyrics"></pre>
<!-- Feedback and Accuracy Test -->
<div id="accuracy-test">
<p>Did the model get the mood right?</p>
<button id="correct" title="Yes">Yes</button>
<button id="incorrect" title="No">No</button>
</div>
</div>
<div class="footer">
This app analyzes song lyrics to predict their mood. Enter a song title and artist, and get mood predictions along with the lyrics. Deployed using Hugging Face Spaces. The model may be inaccurate in some cases.
<br><br>
<a href="#" id="more-info-link">Learn more.</a>
<div id="more-info">
<p><strong>How it Works:</strong></p>
<p>This web app utilizes a fine-tuned BERT model to analyze the mood of song lyrics. Upon entering a song title and artist, the app retrieves the song's lyrics from Genius, processes them through the BERT model, and predicts the mood. The model's accuracy is 93% on its test set.</p>
<p><strong>Technology:</strong></p>
<ul>
<li><strong>Model:</strong> BERT (Bidirectional Encoder Representations from Transformers) fine-tuned on song lyrics to classify moods.</li>
<li><strong>Framework:</strong> PyTorch and Hugging Face Transformers library for model training and prediction.</li>
<li><strong>Frontend:</strong> HTML, CSS, and JavaScript.</li>
<li><strong>Backend:</strong> Flask.</li>
<li><strong>Deployment:</strong> The web app is hosted and deployed using Hugging Face Spaces, which provides a simple interface for serving machine learning models.</li>
</ul>
<p>For the source code, visit: <a href="https://github.com/ggopalai/moody-lyrics/tree/master" target="_blank">GitHub Repository</a></p>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// Initialize the chart with zero probabilities
const ctx = document.getElementById('mood-chart').getContext('2d');
let moodChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Angry', 'Happy', 'Relaxed', 'Sad'],
datasets: [{
label: 'Mood Probabilities',
data: [0, 0, 0, 0], // Initial data
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(255, 159, 64, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true,
min: 0,
max: 1,
ticks: {
stepSize: 0.1,
callback: function(value) { return value.toFixed(1); } // Format y-axis labels
}
}
}
}
});
document.getElementById('mood-form').addEventListener('submit', async function(event) {
event.preventDefault();
const title = document.getElementById('title').value;
const artist = document.getElementById('artist').value;
// Show the spinner
document.getElementById('spinner').style.display = 'flex';
const response = await fetch('/predict', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ title, artist }),
});
const data = await response.json();
document.getElementById('mood-result').innerText = `Predicted Mood: ${data.mood}`;
document.getElementById('lyrics').innerText = data.lyrics;
// Hide the spinner
document.getElementById('spinner').style.display = 'none';
// Scroll to the top of the container to ensure the form remains visible
document.querySelector('.container').scrollTop = 0;
// Change background color based on the predicted mood
const resultsContainer = document.getElementById('results-container');
const body = document.body;
switch (data.mood.toLowerCase()) {
case 'happy':
resultsContainer.style.backgroundColor = '#fff9c4'; // light yellow
body.style.background = 'linear-gradient(135deg, #fff9c4, #f39c12)'; // gradient for happy
break;
case 'angry':
resultsContainer.style.backgroundColor = '#ffcdd2'; // light red
body.style.background = 'linear-gradient(135deg, #ffcdd2, #e74c3c)'; // gradient for angry
break;
case 'relaxed':
resultsContainer.style.backgroundColor = '#c8e6c9'; // light green
body.style.background = 'linear-gradient(135deg, #c8e6c9, #27ae60)'; // gradient for relaxed
break;
case 'sad':
resultsContainer.style.backgroundColor = '#bbdefb'; // light blue
body.style.background = 'linear-gradient(135deg, #bbdefb, #3498db)'; // gradient for sad
break;
default:
resultsContainer.style.backgroundColor = 'rgba(244, 244, 249, 0.9)'; // default background color
body.style.background = 'linear-gradient(135deg, #f3ec78, #af4261)'; // default gradient
}
// Update chart with new data
moodChart.data.datasets[0].data = data.probabilities || [0, 0, 0, 0];
moodChart.update();
// Show feedback section
document.getElementById('accuracy-test').style.display = 'block';
});
// Toggle detailed description with smooth effect and scroll to it
document.getElementById('more-info-link').addEventListener('click', function(event) {
event.preventDefault();
const moreInfo = document.getElementById('more-info');
if (moreInfo.style.display === 'none' || !moreInfo.style.display) {
moreInfo.style.display = 'block';
setTimeout(() => {
moreInfo.classList.add('show');
// Scroll to the more-info section smoothly
moreInfo.scrollIntoView({ behavior: 'smooth', block: 'start' });
}, 10);
} else {
moreInfo.classList.remove('show');
setTimeout(() => moreInfo.style.display = 'none', 500);
}
});
// Handle accuracy test
document.getElementById('correct').addEventListener('click', function() {
alert('Thank you for the feedback!');
// Send correct feedback to the server if needed
});
document.getElementById('incorrect').addEventListener('click', function() {
alert('Thank you for the feedback!');
// Send incorrect feedback to the server if needed
});
</script>
</body>
</html>