feat: generate haiku from image

Regs: OPS-85 OPS-84
This commit is contained in:
Christoph J. Scherr 2025-03-23 18:12:19 +01:00
parent 96e081fff1
commit 2c1e1e1488
No known key found for this signature in database
GPG key ID: 9EB784BB202BB7BB
3 changed files with 87 additions and 70 deletions

View file

@ -11,6 +11,7 @@ const yesButton = document.getElementById("yes-button");
const noButton = document.getElementById("no-button"); const noButton = document.getElementById("no-button");
const generatingHaikuBox = document.getElementById("generating-haiku-box"); const generatingHaikuBox = document.getElementById("generating-haiku-box");
const generatedHaikuBox = document.getElementById("generated-haiku-box"); const generatedHaikuBox = document.getElementById("generated-haiku-box");
let haiku_prompt = "";
let imageUploaded = false; let imageUploaded = false;
function handleFileSelect(event) { function handleFileSelect(event) {
@ -80,10 +81,10 @@ function handleSubmit() {
}) })
.then((data) => { .then((data) => {
// Extract top result and display it // Extract top result and display it
if (data.results && data.results.length > 0) { if (data.description) {
const topResult = data.results[0]; haiku_prompt = data.description;
document.getElementById("ai-response").textContent = document.getElementById("ai-response").textContent =
`${topResult.label} (${Math.round(topResult.confidence * 100)}% confidence)`; `Recognized: ${haiku_prompt}`;
} else { } else {
document.getElementById("ai-response").textContent = document.getElementById("ai-response").textContent =
"Could not identify the image"; "Could not identify the image";
@ -102,23 +103,30 @@ function handleSubmit() {
}, 600); }, 600);
} }
} }
function handleYesClick() { function handleYesClick() {
// Hide response box // Hide response box
responseBox.classList.add("opacity-0"); responseBox.classList.add("opacity-0");
// Show generating haiku box first responseBox.textContent = "🤖 AI is thinking...";
setTimeout(() => { responseBox.classList.remove("opacity-0");
responseBox.classList.add("hidden");
generatingHaikuBox.classList.remove("hidden");
// After a delay, hide generating box and show result fetch("/api/v1/haiku", {
setTimeout(() => { method: "POST",
generatingHaikuBox.classList.add("hidden"); headers: {
generatedHaikuBox.classList.remove("hidden"); "Content-Type": "application/json",
}, 3000); // Show loading animation for 3 seconds before revealing the haiku },
}, 500); // Wait for response box fade out body: JSON.stringify({ prompt: haiku_prompt }),
})
.then((response) => response.text())
.then((data) => {
let id = parseInt(data, 10);
window.location.href = "/haiku/" + id;
})
.catch((error) => {
responseBox.textContent = "Error: " + error.message;
});
} }
function handleNoClick() { function handleNoClick() {
// Reset everything // Reset everything
removeImage(); removeImage();

View file

@ -1,35 +1,44 @@
{% extends "base.html" %} {% extends "base.html" %} {% block content %}
<div
{% block content %} class="flex flex-col items-center justify-center min-h-screen bg-violet-900 text-white p-6"
<div class="flex flex-col items-center justify-center min-h-screen bg-violet-900 text-white p-6"> >
<div class="bg-white text-gray-900 p-8 rounded-xl shadow-lg max-w-lg w-full text-center transform transition duration-300 hover:scale-105"> <div
<h1 class="text-3xl font-bold text-violet-700 mb-4">Very 1337 prompt input</h1> class="bg-white text-gray-900 p-8 rounded-xl shadow-lg max-w-lg w-full text-center transform transition duration-300 hover:scale-105"
<div class="flex flex-col gap-4"> >
<input <h1 class="text-3xl font-bold text-violet-700 mb-4">
type="text" Very 1337 prompt input
id="user-input" </h1>
minlength="0" <div class="flex flex-col gap-4">
maxlength="100" <input
placeholder="Type your prompt here..." type="text"
class="w-full px-4 py-3 text-lg border-2 border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-violet-600" id="user-input"
/> minlength="0"
<button maxlength="100"
id="submit-btn" placeholder="Type your prompt here..."
class="bg-violet-600 text-white font-bold py-3 px-6 rounded-lg text-lg shadow-md transition duration-300 hover:bg-violet-700 hover:scale-105" class="w-full px-4 py-3 text-lg border-2 border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-violet-600"
> />
🚀 Submit <button
</button> id="submit-btn"
</div> class="bg-violet-600 text-white font-bold py-3 px-6 rounded-lg text-lg shadow-md transition duration-300 hover:bg-violet-700 hover:scale-105"
>
🚀 Submit
</button>
</div> </div>
</div>
<div id="response-box" class="mt-8 bg-white text-gray-900 p-6 rounded-lg shadow-lg max-w-lg w-full text-center opacity-0 transition-opacity duration-500 ease-in-out"> <div
<h2 class="text-2xl font-semibold text-violet-700">Response:</h2> id="response-box"
<p id="ai-response" class="text-lg text-gray-700 mt-2 italic">Waiting for input...</p> class="mt-8 bg-white text-gray-900 p-6 rounded-lg shadow-lg max-w-lg w-full text-center opacity-0 transition-opacity duration-500 ease-in-out"
</div> >
<h2 class="text-2xl font-semibold text-violet-700">Response:</h2>
<p id="ai-response" class="text-lg text-gray-700 mt-2 italic">
Waiting for input...
</p>
</div>
</div> </div>
<script> <script>
document.getElementById("submit-btn").addEventListener("click", function() { document.getElementById("submit-btn").addEventListener("click", function () {
let userInput = document.getElementById("user-input").value; let userInput = document.getElementById("user-input").value;
let responseBox = document.getElementById("response-box"); let responseBox = document.getElementById("response-box");
let responseText = document.getElementById("ai-response"); let responseText = document.getElementById("ai-response");
@ -38,37 +47,37 @@ document.getElementById("submit-btn").addEventListener("click", function() {
responseBox.classList.add("opacity-0"); responseBox.classList.add("opacity-0");
if (userInput.trim() === "") { if (userInput.trim() === "") {
responseText.textContent = "Please enter a prompt!"; responseText.textContent = "Please enter a prompt!";
} } else if (userInput.length > 100) {
else if (userInput.trim() === "amogus") { responseText.textContent = "Input must under 100 characters long!";
responseText.textContent = "🤖 AI is thinking..."; } else if (userInput.trim() === "amogus") {
responseBox.classList.remove("opacity-0"); responseText.textContent = "🤖 AI is thinking...";
responseBox.classList.remove("opacity-0");
// Simulated AI response delay // Simulated AI response delay
setTimeout(() => { setTimeout(() => {
responseText.textContent = "Sus imposter ඞ"; responseText.textContent = "Sus imposter ඞ";
}, 1500); }, 1500);
} } else {
else { responseText.textContent = "🤖 AI is thinking...";
responseText.textContent = "🤖 AI is thinking..."; responseBox.classList.remove("opacity-0");
responseBox.classList.remove("opacity-0");
fetch('/api/v1/haiku', { fetch("/api/v1/haiku", {
method: 'POST', method: "POST",
headers: { headers: {
'Content-Type': 'application/json' "Content-Type": "application/json",
}, },
body: JSON.stringify({ 'prompt': userInput }) body: JSON.stringify({ prompt: userInput }),
})
.then((response) => response.text())
.then((data) => {
let id = parseInt(data, 10);
window.location.href = "/haiku/" + id;
}) })
.then(response => response.text()) .catch((error) => {
.then(data => { responseText.textContent = "Error: " + error.message;
let id = parseInt(data, 10);
window.location.href = "/haiku/" + id;
})
.catch(error => {
responseText.textContent = 'Error: ' + error.message;
}); });
} }
}); });
</script> </script>
{% endblock %} {% endblock %}

View file

@ -97,14 +97,14 @@
</p> </p>
<div class="flex justify-center space-x-4"> <div class="flex justify-center space-x-4">
<button <button
id="yes-button" id="yesButton"
type="button" type="button"
class="mt-6 bg-violet-600 hover:bg-violet-700 text-white font-bold py-2 px-4 rounded transition duration-300" class="mt-6 bg-violet-600 hover:bg-violet-700 text-white font-bold py-2 px-4 rounded transition duration-300"
> >
Generate Haiku Generate Haiku
</button> </button>
<button <button
id="no-button" id="noButton"
type="button" type="button"
class="mt-6 bg-violet-600 hover:bg-violet-700 text-white font-bold py-2 px-4 rounded transition duration-300" class="mt-6 bg-violet-600 hover:bg-violet-700 text-white font-bold py-2 px-4 rounded transition duration-300"
> >