Prompts-Generator / index.html
AnantaXLIllustrious's picture
Update index.html
70209cd verified
Raw
History Blame Contribute Delete
13.9 kB
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Prompt Generator GPT-2</title>
<script src="https://cdn.tailwindcss.com"></script>
<script type="module">
import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.2';
window.pipeline = pipeline;
env.allowLocalModels = false;
</script>
<style>
*, *::before, *::after {
-webkit-tap-highlight-color: transparent;
}
*:focus, *:active {
outline: none !important;
box-shadow: none !important;
}
body {
background: linear-gradient(135deg, #f0f4f9 0%, #e1e9f5 100%);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.btn-silver {
background: linear-gradient(to bottom, #ffffff 0%, #dbe1e8 100%);
border: 1px solid #b0bac5;
color: #1e3a8a;
transition: all 0.15s ease-in-out;
}
.btn-silver:hover:not(:disabled) {
background: linear-gradient(to bottom, #ffffff 0%, #cbd5e1 100%);
border-color: #94a3b8;
}
.btn-silver:active:not(:disabled) {
background: linear-gradient(to bottom, #dbe1e8 0%, #ffffff 100%);
}
.btn-silver:disabled {
opacity: 0.6;
cursor: not-allowed;
background: linear-gradient(to bottom, #f1f5f9 0%, #e2e8f0 100%);
}
#sapFocusOverlay {
position: fixed;
pointer-events: none;
z-index: 9999;
transition: top 0.22s cubic-bezier(0.25, 1, 0.5, 1),
left 0.22s cubic-bezier(0.25, 1, 0.5, 1),
width 0.22s cubic-bezier(0.25, 1, 0.5, 1),
height 0.22s cubic-bezier(0.25, 1, 0.5, 1),
opacity 0.15s ease;
opacity: 0;
}
.sap-corner {
position: absolute;
width: 6px;
height: 6px;
border-color: #cc2222;
border-style: solid;
transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1);
}
.sap-tl { top: -1px; left: -2px; border-width: 2px 0 0 2px; }
.sap-tr { top: -1px; right: -2px; border-width: 2px 2px 0 0; }
.sap-bl { bottom: -1px; left: -2px; border-width: 0 0 2px 2px; }
.sap-br { bottom: -1px; right: -2px; border-width: 0 2px 2px 0; }
#sapFocusOverlay.active .sap-tl { transform: translate(0, 0); }
#sapFocusOverlay.active .sap-tr { transform: translate(0, 0); }
#sapFocusOverlay.active .sap-bl { transform: translate(0, 0); }
#sapFocusOverlay.active .sap-br { transform: translate(0, 0); }
</style>
</head>
<body class="min-h-screen flex flex-col items-center justify-start p-4 py-8 text-slate-800">
<div class="w-full max-w-4xl space-y-6">
<div class="text-center space-y-1.5">
<h1 class="text-2xl sm:text-3xl font-extrabold text-blue-600 tracking-tight">Prompt Generator</h1>
<p class="text-xs sm:text-sm text-slate-500 font-medium">
Run model <code class="bg-blue-50 px-2 py-0.5 rounded border border-blue-100 text-blue-600 font-mono text-xs">GPT-2</code> with Transformers.js
</p>
</div>
<div id="statusBox" tabindex="0" class="interactive-element bg-white/80 border border-slate-200 p-3.5 rounded-2xl text-xs flex items-center space-x-3 shadow-sm transition">
<div id="statusDot" class="relative flex h-3 w-3 ml-1">
<span id="dotPing" class="animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75"></span>
<span id="dotSolid" class="relative inline-flex rounded-full h-3 w-3 bg-amber-500"></span>
</div>
<span id="statusText" class="text-slate-600 font-semibold">Prepare AI engine...</span>
</div>
<div class="space-y-1.5">
<label class="block text-xs font-semibold text-slate-600 uppercase tracking-wider">
Initial Prompts
</label>
<div class="relative">
<textarea
id="initialPrompt"
rows="4"
placeholder="Example: A futuristic sports car driving through a cyberpunk city at night..."
class="interactive-element w-full bg-white border border-slate-300 rounded-2xl p-4 pb-6 text-xs sm:text-sm text-slate-800 shadow-sm transition resize-y block"
></textarea>
<div class="absolute bottom-2.5 right-4 pointer-events-none flex items-center gap-1 text-[10px] text-slate-400 font-mono select-none">
<span>Resizable</span>
<svg class="w-2.5 h-2.5 text-slate-400" fill="currentColor" viewBox="0 0 16 16">
<path d="M14 14H12V12H14V14ZM14 10H12V8H14V10ZM10 14H8V12H10V14Z"/>
</svg>
</div>
</div>
<div class="text-[11px] text-slate-400 px-1">
<span>Enter for next lines</span>
</div>
</div>
<div class="space-y-3">
<button
id="generateBtn"
onclick="generatePrompt()"
disabled
class="btn-silver interactive-element w-full font-bold py-3.5 rounded-2xl text-xs sm:text-sm shadow-sm transition-all duration-200 flex items-center justify-center space-x-2"
>
<span id="btnText">Loading Model...</span>
</button>
<div id="loadingBarContainer" class="hidden w-full space-y-1.5">
<div class="w-full bg-slate-200 h-2.5 rounded-full overflow-hidden border border-slate-300">
<div id="progressBar" class="bg-blue-600 h-full w-0 transition-all duration-300 ease-out"></div>
</div>
<div class="flex justify-between text-[10px] text-slate-500 font-medium">
<span>Processing...</span>
<span id="progressPercent">0%</span>
</div>
</div>
</div>
<div id="errorBox" class="hidden text-red-600 bg-red-50 border border-red-200 p-3.5 rounded-2xl text-xs sm:text-sm"></div>
<div class="space-y-1.5">
<label class="block text-xs font-semibold text-slate-600 uppercase tracking-wider">
Outputs
</label>
<div class="relative">
<div
id="outputPrompt"
tabindex="0"
class="interactive-element w-full min-h-[120px] bg-white border border-slate-300 rounded-2xl p-4 pb-6 text-sm text-slate-800 font-mono leading-relaxed flex flex-wrap content-start items-center gap-1.5 overflow-y-auto resize-y shadow-sm"
>
<span class="text-slate-400 text-xs italic font-sans select-none">Generated output will appear here...</span>
</div>
<button
onclick="copyToClipboard()"
class="btn-silver interactive-element absolute top-3 right-3 text-xs px-3.5 py-1.5 rounded-xl font-semibold shadow-sm z-20"
>
Copy
</button>
<div class="absolute bottom-2.5 right-4 pointer-events-none flex items-center gap-1 text-[10px] text-slate-400 font-mono select-none z-10">
<span>Resizable</span>
<svg class="w-2.5 h-2.5 text-slate-400" fill="currentColor" viewBox="0 0 16 16">
<path d="M14 14H12V12H14V14ZM14 10H12V8H14V10ZM10 14H8V12H10V14Z"/>
</svg>
</div>
</div>
</div>
</div>
<div id="sapFocusOverlay">
<div class="sap-corner sap-tl"></div>
<div class="sap-corner sap-tr"></div>
<div class="sap-corner sap-bl"></div>
<div class="sap-corner sap-br"></div>
</div>
<script>
const overlay = document.getElementById('sapFocusOverlay');
function attachFocusAnimator(target) {
if (!target || target === document.body) {
overlay.style.opacity = '0';
return;
}
const rect = target.getBoundingClientRect();
const padding = 3;
overlay.style.top = `${rect.top - padding}px`;
overlay.style.left = `${rect.left - padding}px`;
overlay.style.width = `${rect.width + (padding * 2)}px`;
overlay.style.height = `${rect.height + (padding * 2)}px`;
overlay.style.opacity = '1';
overlay.classList.add('active');
}
document.addEventListener('focusin', (e) => {
const target = e.target.closest('textarea, input, button, select, [tabindex], .interactive-element');
if (target) {
attachFocusAnimator(target);
}
});
document.addEventListener('click', (e) => {
const target = e.target.closest('textarea, input, button, select, [tabindex], .interactive-element');
if (target) {
attachFocusAnimator(target);
} else {
overlay.style.opacity = '0';
}
});
window.addEventListener('resize', () => {
if (document.activeElement) attachFocusAnimator(document.activeElement);
});
window.addEventListener('scroll', () => {
if (document.activeElement) attachFocusAnimator(document.activeElement);
}, true);
let generator = null;
const tokenColors = [
'bg-amber-100 text-amber-900 border border-amber-200',
'bg-emerald-100 text-emerald-900 border border-emerald-200',
'bg-blue-100 text-blue-900 border border-blue-200',
'bg-rose-100 text-rose-900 border border-rose-200',
'bg-purple-100 text-purple-900 border border-purple-200',
'bg-orange-100 text-orange-900 border border-orange-200',
'bg-cyan-100 text-cyan-900 border border-cyan-200'
];
window.addEventListener('DOMContentLoaded', async () => {
const statusText = document.getElementById('statusText');
const dotPing = document.getElementById('dotPing');
const dotSolid = document.getElementById('dotSolid');
const btn = document.getElementById('generateBtn');
const btnText = document.getElementById('btnText');
try {
while (!window.pipeline) {
await new Promise(r => setTimeout(r, 100));
}
statusText.textContent = 'Importing model GPT-2...';
generator = await window.pipeline('text-generation', 'Xenova/gpt2');
dotPing.className = "animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75";
dotSolid.className = "relative inline-flex rounded-full h-3 w-3 bg-emerald-500";
statusText.textContent = 'Model Ready';
btnText.textContent = 'Generate';
btn.disabled = false;
} catch (err) {
dotPing.className = "hidden";
dotSolid.className = "relative inline-flex rounded-full h-3 w-3 bg-red-500";
statusText.textContent = 'Failed to load model';
console.error(err);
}
});
async function generatePrompt() {
const rawInput = document.getElementById('initialPrompt').value.trim();
const initialPrompt = rawInput.replace(/[\r\n]+/g, " ");
const btn = document.getElementById('generateBtn');
const btnText = document.getElementById('btnText');
const outputContainer = document.getElementById('outputPrompt');
const errorBox = document.getElementById('errorBox');
const loadingBarContainer = document.getElementById('loadingBarContainer');
const progressBar = document.getElementById('progressBar');
const progressPercent = document.getElementById('progressPercent');
errorBox.classList.add('hidden');
if (!initialPrompt) {
showError('Please make sure you type required entries.');
return;
}
btn.disabled = true;
btnText.textContent = 'Generating...';
outputContainer.innerHTML = '';
loadingBarContainer.classList.remove('hidden');
progressBar.style.width = '10%';
progressPercent.textContent = '10%';
await new Promise(resolve => setTimeout(resolve, 50));
let progress = 10;
const progressInterval = setInterval(() => {
if (progress < 90) {
progress += Math.floor(Math.random() * 15) + 5;
if (progress > 90) progress = 90;
progressBar.style.width = `${progress}%`;
progressPercent.textContent = `${progress}%`;
}
}, 100);
try {
const formattedInput = `${initialPrompt}, dynamic lighting, highly detailed, 8k resolution, masterpiece,`;
const output = await generator(formattedInput, {
max_new_tokens: 40,
temperature: 0.7,
do_sample: true,
top_k: 40
});
clearInterval(progressInterval);
progressBar.style.width = '100%';
progressPercent.textContent = '100%';
if (output && output[0] && output[0].generated_text) {
let cleanText = output[0].generated_text.replace(/[\r\n]+/g, " ");
const tokens = cleanText.match(/[\w']+|[^\w\s]/g) || [cleanText];
outputContainer.innerHTML = '';
tokens.forEach((token, index) => {
const colorClass = tokenColors[index % tokenColors.length];
const span = document.createElement('span');
span.className = `${colorClass} px-1.5 py-0.5 rounded-md font-mono text-xs inline-block`;
span.textContent = token;
outputContainer.appendChild(span);
});
}
} catch (err) {
clearInterval(progressInterval);
showError('An error occurred during generation.');
} finally {
setTimeout(() => {
loadingBarContainer.classList.add('hidden');
progressBar.style.width = '0%';
btn.disabled = false;
btnText.textContent = 'Generate';
}, 500);
}
}
function showError(msg) {
const errorBox = document.getElementById('errorBox');
errorBox.textContent = msg;
errorBox.classList.remove('hidden');
}
function copyToClipboard() {
const outputContainer = document.getElementById('outputPrompt');
const textToCopy = Array.from(outputContainer.children)
.map(el => el.textContent)
.join(' ');
if (!textToCopy.trim()) return;
navigator.clipboard.writeText(textToCopy);
}
</script>
</body>
</html>