atlas / static /index.html
mdAmin313's picture
Initial commit: AI misinformation detector
5b41f5a
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Misinformation Detective β€” Demo</title>
<style>
:root {
--primary: #0066cc;
--bg: #f9fafc;
--card-bg: #fff;
--border: #ddd;
--text: #222;
--muted: #666;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.5;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 1.5rem;
}
header {
text-align: center;
margin-bottom: 1.5rem;
}
header h1 {
margin: 0;
font-size: 1.8rem;
}
header .tagline {
color: var(--muted);
font-size: 0.95rem;
}
.card {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 6px;
padding: 1rem;
margin: 1rem 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.card h3 {
margin-top: 0;
font-size: 1.1rem;
border-bottom: 1px solid var(--border);
padding-bottom: 0.25rem;
}
textarea {
width: 100%;
height: 80px;
padding: 0.5rem;
font-family: inherit;
font-size: 1rem;
border-radius: 4px;
border: 1px solid var(--border);
resize: vertical;
}
.controls {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
margin-top: 0.5rem;
}
.modes button {
margin-right: 0.5rem;
}
button {
cursor: pointer;
padding: 0.5rem 0.75rem;
border: 1px solid var(--border);
border-radius: 4px;
background: #f0f0f0;
font-size: 0.9rem;
}
button.primary {
background: var(--primary);
color: white;
border: none;
}
button.active {
background: var(--primary);
color: white;
}
.demo-buttons {
margin-top: 0.5rem;
}
.demo {
margin-right: 0.3rem;
margin-top: 0.3rem;
}
footer {
margin-top: 2rem;
text-align: center;
color: var(--muted);
font-size: 0.8rem;
}
pre {
white-space: pre-wrap;
word-wrap: break-word;
font-size: 0.85rem;
background: #f7f7f7;
padding: 0.5rem;
border-radius: 4px;
}
.loading {
text-align: center;
padding: 2rem;
font-weight: bold;
}
.error {
color: red;
font-weight: bold;
}
ul {
padding-left: 1.2rem;
}
li {
margin-bottom: 0.3rem;
}
</style>
</head>
<body>
<main class="container">
<header>
<h1>Misinformation Detective</h1>
<p class="tagline">Quick check + deep evidence-based explanation with highlighted comparisons.</p>
</header>
<section class="card input-card">
<label for="claim">Paste a claim or headline</label>
<textarea id="claim" placeholder="E.g. 'Alien is landed on earth'"></textarea>
<div class="controls">
<div class="modes">
<button id="mode-fast" class="mode active">Fast ⚑</button>
<button id="mode-deep" class="mode">Deep πŸ”</button>
<button id="mode-hybrid" class="mode">Hybrid πŸ”</button>
</div>
<div class="actions">
<button id="verify-btn" class="primary">Verify Claim</button>
<div class="demo-buttons">
<button class="demo" data-claim="Drinking lemon cures cancer">Health example</button>
<button class="demo" data-claim="Scientists confirm coffee extends life by 10 years">Study example</button>
<button class="demo" data-claim="Alien is landed on earth">UFO example</button>
</div>
</div>
</div>
</section>
<section id="pipeline" class="pipeline">
<!-- Cards injected dynamically -->
</section>
<footer>
<small>Designed for hackathon demo β€” resilient, educational, and transparent pipeline.</small>
</footer>
</main>
<script>
const claimInput = document.getElementById("claim");
const verifyBtn = document.getElementById("verify-btn");
const pipeline = document.getElementById("pipeline");
let mode = "fast";
// Mode toggle
document.querySelectorAll(".mode").forEach(btn => {
btn.addEventListener("click", () => {
document.querySelectorAll(".mode").forEach(b => b.classList.remove("active"));
btn.classList.add("active");
mode = btn.id.replace("mode-","");
});
});
// Demo claims
document.querySelectorAll(".demo").forEach(btn => {
btn.addEventListener("click", () => {
claimInput.value = btn.dataset.claim;
});
});
function addCard(title, content) {
const card = document.createElement("section");
card.className = "card";
card.innerHTML = `<h3>${title}</h3><div>${content}</div>`;
pipeline.appendChild(card);
}
function renderComparison(list) {
if (!list || !list.length) return "<em>No comparisons available</em>";
return "<ul>" + list.map(c =>
`<li><strong>${c.claim_span}</strong> ↔ <q>${c.evidence_span}</q> <em>[${c.relation}]</em></li>`
).join("") + "</ul>";
}
verifyBtn.addEventListener("click", async () => {
const text = claimInput.value.trim();
if (!text) return alert("Please enter a claim.");
pipeline.innerHTML = "<p class='loading'>Checking claim...</p>";
try {
// Gradio API call
const res = await fetch("/api/predict/", {
method: "POST",
headers: {"Content-Type":"application/json"},
body: JSON.stringify({data: [text, mode]})
});
const json = await res.json();
const data = json.data[0]; // Gradio returns data inside data[0]
pipeline.innerHTML = "";
addCard("Step 1 β€” Classification", `<p>Type: <b>${data["Text type"]}</b></p>`);
addCard("Step 2 β€” Summary", `<p>${data["User summary"]}</p>`);
addCard("Step 3 β€” Search Results", `<pre>${data["Evidence summary"]}</pre>`);
addCard("Step 4 β€” Evidence Filtered", `<p>Found ${data["Evidence count filtered"]} credible sources</p>`);
addCard("Step 5 β€” Fast Label", `<p>${data["Fast classification"]}</p>`);
addCard("Step 6 β€” Similarity Score", `<p>${data.similarity || "N/A"}</p>`);
if (data["Deep result"] && data["Deep result"] !== "N/A") {
const deep = data["Deep result"];
addCard("Step 7 β€” Deep AI Verdict",
`<p><b>Outcome:</b> ${deep.outcome}</p>
<p>${deep.explanation}</p>
<h4>Comparison</h4>${renderComparison(deep.comparison)}
<h4>Takeaways</h4><ul>${deep.takeaways.map(t=>`<li>${t}</li>`).join("")}</ul>
<p><i>Tip:</i> ${deep.tip || ""}</p>`);
}
addCard("Step 8 β€” Credibility Score",
`<p>Score: <b style="color:${data["Credibility"].color}">${data["Credibility"].score}</b>/100</p>`);
} catch (err) {
console.error(err);
pipeline.innerHTML = "<p class='error'>Error verifying claim.</p>";
}
});
</script>
</body>
</html>