noding / templates /inference.html
broadfield-dev's picture
Update templates/inference.html
05bad08 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Summarizer</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background-color: #f8f9fa; padding-top: 50px; }
.container { max-width: 900px; }
.card { box-shadow: 0 4px 6px rgba(0,0,0,0.1); border: none; }
.loader { display: none; }
</style>
</head>
<body>
<div class="container">
<div class="text-center mb-5">
<h1 class="display-5 fw-bold text-primary">Summarization Inference</h1>
<p class="lead">Running via Flask Blueprint & HuggingFace Transformers</p>
</div>
<div class="row">
<!-- Input Column -->
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-header bg-primary text-white">Input Text</div>
<div class="card-body">
<div class="mb-3">
<input class="form-control" type="password" id="hfToken" rows="10" placeholder="Huggingface Token or .env">
</div>
<div class="mb-3">
<label for="modelSelect" class="form-label">Choose Model</label>
<select class="form-select" id="modelSelect">
<option value="custom" selected>Custom</option>
<option value="facebook/bart-large-cnn">facebook/bart-large-cnn</option>
<option value="google/pegasus-xsum">google/pegasus-xsum</option>
<option value="sshleifer/distilbart-cnn-12-6">sshleifer/distilbart-cnn-12-6 (Faster)</option>
</select>
<input class="form-control" id="inputModel" rows="10" placeholder="custom HF model id user/model">
</div>
<div class="mb-3">
<label class="small">Temperature: <span id="temp-val" class="fw-bold">0.7</span></label>
<input type="range" class="form-range" id="temperature" min="0.1" max="1.5" value="0.7" step="0.1" oninput="document.getElementById('temp-val').innerText = this.value">
<label class="small">Top K: <span id="topk-val" class="fw-bold">50</span></label>
<input type="range" class="form-range" id="topk" min="1" max="100" value="50" step="1" oninput="document.getElementById('topk-val').innerText = this.value">
</div>
<div class="mb-3">
<label for="inputText" class="form-label">Text to Summarize</label>
<textarea class="form-control" id="inputText" rows="10" placeholder="Paste your long text here..."></textarea>
</div>
<button id="submitBtn" class="btn btn-primary w-100">Summarize</button>
</div>
</div>
</div>
<!-- Output Column -->
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-header bg-success text-white">Summary Result</div>
<div class="card-body position-relative">
<!-- Loading Spinner -->
<div id="loader" class="loader position-absolute top-50 start-50 translate-middle text-center">
<div class="spinner-border text-primary" role="status"></div>
<p class="mt-2">Loading model &<br>generating...</p>
</div>
<!-- Output Text -->
<div id="resultContainer">
<p class="text-muted" id="placeholderText">The summary will appear here.</p>
<p id="outputText" class="fw-medium"></p>
</div>
<!-- Error Alert -->
<div id="errorAlert" class="alert alert-danger d-none mt-3"></div>
</div>
</div>
</div>
</div>
</div>
<script>
document.getElementById('submitBtn').addEventListener('click', async () => {
const text = document.getElementById('inputText').value;
const model = document.getElementById('modelSelect').value;
const outputText = document.getElementById('outputText');
const placeholder = document.getElementById('placeholderText');
const loader = document.getElementById('loader');
const resultContainer = document.getElementById('resultContainer');
const errorAlert = document.getElementById('errorAlert');
const inputModel = document.getElementById('inputModel').value;
const hfToken = document.getElementById('hfToken');
const temperature = document.getElementById('temperature').value;
const topk = document.getElementById('topk').value;
console.log(model)
if (model === 'custom') {
modelOut = inputModel;
} else {
modelOut = model;
}
if (!text.trim()) {
alert("Please enter some text!");
return;
}
// UI Updates
loader.style.display = 'block';
resultContainer.style.opacity = '0.3';
errorAlert.classList.add('d-none');
document.getElementById('submitBtn').disabled = true;
try {
const response = await fetch('/summarize/api/summarize', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: text, model_name: modelOut, hf_token: hfToken, temp: temperature, topk: topk })
});
const data = await response.json();
loader.style.display = 'none';
resultContainer.style.opacity = '1';
document.getElementById('submitBtn').disabled = false;
if (response.ok) {
placeholder.style.display = 'none';
outputText.innerText = data.output;
} else {
errorAlert.innerText = "Error: " + (data.error || "Unknown error");
errorAlert.classList.remove('d-none');
}
} catch (err) {
console.error(err);
loader.style.display = 'none';
resultContainer.style.opacity = '1';
document.getElementById('submitBtn').disabled = false;
errorAlert.innerText = "Network Error or Server Timeout";
errorAlert.classList.remove('d-none');
}
});
</script>
</body>
</html>