roglag / web /slides.html
AI Bot
redesign: radar logo + production copy (no emoji) + layered responsive (320/768/1024/1440) + a11y
e07688f
Raw
History Blame Contribute Delete
16.2 kB
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ROGLAG — Project Presentation</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans+Thai:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root{--bg:#070b12;--panel:#111826;--line:#1f2a3d;--txt:#eaf1fa;--muted:#aab8cc;
--accent:#4da3ff;--accent2:#b8a6ff;--teal:#5eead4;--ok:#34d399;--warn:#fbbf24;--crit:#f87171;--code:#0a0e16;
--hair:rgba(148,163,184,0.18);}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{background:var(--bg);color:var(--txt);font-family:"IBM Plex Sans Thai",-apple-system,"Segoe UI",sans-serif;font-size:18px;line-height:1.5;overflow:hidden}
.deck{height:100vh;width:100vw;position:relative}
.slide{position:absolute;inset:0;display:none;flex-direction:column;justify-content:center;
padding:7vh 9vw;opacity:0;transition:opacity .35s ease;
background:radial-gradient(1100px 560px at 82% -8%,#16223c 0%,var(--bg) 58%)}
.slide.active{display:flex;opacity:1}
.kicker{color:var(--teal);font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:14px;
line-height:1.5;letter-spacing:.5px;margin-bottom:14px}
h1{font-size:clamp(47px,6vw,90px);line-height:1.05;letter-spacing:.5px}
h1 .grad{color:#eaf1fa}
h2{font-size:clamp(29px,3.6vw,47px);line-height:1.3;margin-bottom:24px;display:flex;align-items:center;gap:14px}
p.lead{font-size:clamp(23px,2vw,29px);color:var(--muted);max-width:60ch;line-height:1.6;margin-top:10px}
ul{list-style:none;margin-top:10px}
li{font-size:clamp(23px,1.7vw,29px);margin:13px 0;padding-left:30px;position:relative;color:#dbe6f3;line-height:1.6}
li::before{content:"▸";position:absolute;left:0;color:var(--teal)}
li small{color:var(--muted);font-size:14px;line-height:1.5}
code{background:var(--code);border:1px solid var(--line);border-radius:6px;padding:1px 7px;font-size:14px;line-height:1.5;color:#cfe3ff;font-family:"IBM Plex Mono",ui-monospace,monospace}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:16px;margin-top:18px;max-width:1000px}
.card{border:1px solid var(--hair);border-radius:14px;padding:18px 20px;background:linear-gradient(160deg,#121a2b,#0d1320)}
.card h3{font-size:clamp(23px,1.9vw,29px);line-height:1.3;margin-bottom:8px}
.card p{color:var(--muted);font-size:14px;line-height:1.5}
.chips{display:flex;gap:9px;flex-wrap:wrap;margin-top:22px}
.chip{font-size:14px;line-height:1.5;padding:7px 14px;border:1px solid var(--hair);border-radius:999px;background:#16203250;color:var(--teal)}
.flow{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-top:22px;font-size:18px;line-height:1.5}
.node{border:1px solid var(--line);background:var(--panel);border-radius:11px;padding:11px 16px}
.arrow{color:var(--accent2);font-weight:800}
.two{display:grid;grid-template-columns:1fr 1fr;gap:40px;margin-top:10px}
@media(max-width:760px){.two{grid-template-columns:1fr}}
.big{font-size:clamp(60px,7vw,90px);font-weight:800;color:var(--teal);line-height:1}
.statline{display:flex;gap:40px;flex-wrap:wrap;margin-top:26px}
.stat .l{color:var(--muted);font-size:14px;line-height:1.5;letter-spacing:.5px;margin-top:6px}
.badge{display:inline-block;font-size:14px;line-height:1.5;padding:3px 10px;border-radius:999px;vertical-align:middle;margin-left:10px}
.b-done{background:#0e2a1e;color:var(--ok);border:1px solid #1c4b36}
/* chrome */
.bar{position:fixed;top:0;left:0;width:100%;height:3px;background:linear-gradient(90deg,var(--accent),var(--accent2));transform:scaleX(0);transform-origin:left;transition:transform .3s;z-index:10}
.hud{position:fixed;bottom:18px;right:24px;color:var(--muted);font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:14px;line-height:1.5;z-index:10}
.hint{position:fixed;bottom:18px;left:24px;color:#aab8cc;font-size:14px;line-height:1.5;z-index:10}
.nav{position:fixed;bottom:14px;left:50%;transform:translateX(-50%);display:flex;gap:8px;z-index:10}
.nav button{background:var(--panel);border:1px solid var(--line);color:var(--txt);border-radius:8px;padding:6px 14px;cursor:pointer;font-size:18px;line-height:1.5}
.nav button:hover{border-color:var(--accent)}
.logo{display:inline-grid;place-items:center;width:64px;height:64px;border-radius:16px;margin-bottom:24px;
background:radial-gradient(120% 120% at 30% 20%,rgba(94,234,212,.18),transparent 60%),linear-gradient(150deg,#0c2034,#0a3140);border:1px solid rgba(94,234,212,.32)}
.logo svg{width:40px;height:40px}
</style>
</head>
<body>
<div class="bar" id="bar"></div>
<div class="deck" id="deck">
<!-- 1 TITLE -->
<section class="slide active">
<span class="logo"><svg viewBox="0 0 64 64">
<defs>
<linearGradient id="rgRing" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#5eead4"/>
<stop offset="1" stop-color="#0d9488"/>
</linearGradient>
<linearGradient id="rgSweep" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#5eead4" stop-opacity=".55"/>
<stop offset="1" stop-color="#5eead4" stop-opacity="0"/>
</linearGradient>
</defs>
<circle cx="32" cy="32" r="21" fill="none" stroke="url(#rgRing)" stroke-width="3.2"/>
<circle cx="32" cy="32" r="11.5" fill="none" stroke="#5eead4" stroke-width="1.6" opacity=".38"/>
<path d="M32 32 L32 11 A21 21 0 0 1 50.2 21.5 Z" fill="url(#rgSweep)"/>
<circle cx="32" cy="32" r="2.4" fill="#5eead4"/>
<circle cx="43.5" cy="22.5" r="3.1" fill="#7dd3fc"/>
</svg></span>
<div class="kicker">AI RAG · Security Log Analytics</div>
<h1>ROGLAG<br><span class="grad">Threat Intelligence Console</span></h1>
<p class="lead">ระบบตรวจจับความเสี่ยงจาก security log แบบเรียลไทม์ ด้วย rule-based detection + RAG + vector search — รันได้ตั้งแต่ออฟไลน์จนถึง production</p>
<div class="chips">
<span class="chip">Realtime</span><span class="chip">RAG</span><span class="chip">Qdrant</span>
<span class="chip">Self-host</span><span class="chip">Docker</span>
</div>
</section>
<!-- 2 CAPABILITIES -->
<section class="slide">
<div class="kicker">ความสามารถ</div>
<h2>ทำอะไรได้บ้าง</h2>
<ul>
<li><b>ตรวจจับภัยอัตโนมัติ</b> จาก log เช่น brute force, port scan, web attack, C2 beacon ฯลฯ พร้อม MITRE + risk score</li>
<li><b>ค้นหาเชิงความหมาย (RAG):</b> ถามเป็นภาษาไทย แล้วดึงหลักฐานที่เกี่ยวข้องมาให้</li>
<li><b>สรุป + แนะนำ next action</b> เป็นภาษาคน จากหลักฐานจริง</li>
<li><b>มอนิเตอร์เรียลไทม์:</b> ดู log ไหลเข้าสด + กราฟ/incident/critical อัปเดตทันที</li>
<li><b>จำลอง / อัปโหลด log</b> เพื่อทดสอบระบบตรวจจับได้ทันที</li>
</ul>
</section>
<!-- 3 WHAT WE BUILT -->
<section class="slide">
<div class="kicker">ภาพรวมสิ่งที่ทำ</div>
<h2>สรุปสิ่งที่สร้าง</h2>
<div class="grid">
<div class="card"><h3>🛡️ Console + Detection</h3><p>Dashboard ภาษาไทย + rule classifier 7 ภัย + MITRE ATT&CK</p></div>
<div class="card"><h3>💬 RAG Q&A</h3><p>ถามไทย → ดึงหลักฐาน → สรุป + next action</p></div>
<div class="card"><h3>⚡ Realtime + Generator</h3><p>จำลอง log สด, live monitor, สร้าง/อัปโหลด CSV</p></div>
<div class="card"><h3>🌐 Qdrant + Docker</h3><p>vector RAG จริง + self-host รันคำสั่งเดียว</p></div>
</div>
</section>
<!-- 4 ARCHITECTURE -->
<section class="slide">
<div class="kicker">สถาปัตยกรรม</div>
<h2>Data flow (โดยสรุป)</h2>
<div class="flow">
<span class="node">Log / CSV / Mock</span><span class="arrow"></span>
<span class="node">Classify</span><span class="arrow"></span>
<span class="node">Qdrant<br><small>semantic search</small></span><span class="arrow"></span>
<span class="node">RAG + API</span><span class="arrow"></span>
<span class="node">Dashboard</span>
</div>
<p class="lead" style="margin-top:28px">มี fallback ทุกชั้น: <b>Qdrant → SQLite vector → keyword → rule-based</b>. ระบบไม่ล่มแม้ไม่มี key หรือเน็ต</p>
</section>
<!-- 5 DETECTION -->
<section class="slide">
<div class="kicker">Detection layer</div>
<h2>Rule-based classifier</h2>
<div class="two">
<ul>
<li><b>brute_force</b> <small>T1110</small></li>
<li><b>port_scan</b> <small>T1046</small></li>
<li><b>web_attack</b> <small>T1190 · SQLi/XSS</small></li>
<li><b>priv_esc</b> <small>T1068/T1548</small></li>
</ul>
<ul>
<li><b>data_exfil</b> <small>T1041</small></li>
<li><b>c2_beacon</b> <small>T1071</small></li>
<li><b>benign</b> <small>baseline</small></li>
<li>แต่ละหมวด → risk score + runbook แนะนำ</li>
</ul>
</div>
<p class="lead" style="margin-top:20px">ทำงานออฟไลน์ 100% ไม่ต้องพึ่งโมเดล จึงเร็วและอธิบายผลได้</p>
</section>
<!-- 6 REALTIME -->
<section class="slide">
<div class="kicker">Realtime features</div>
<h2>Generator &amp; Live monitor</h2>
<ul>
<li><b>Live stream:</b> ยิง log จำลองหลากหลายไม่ซ้ำเข้าระบบจริง ปุ่มเดียวจบ</li>
<li><b>Realtime monitor:</b> ดู log ไหลเข้าสดเหมือน <code>tail -f</code> + sort by time</li>
<li><b>Generate CSV:</b> สร้างไฟล์สุ่มใหม่ทุกครั้ง เอาไปทดสอบได้</li>
<li><b>Upload CSV:</b> classify ทุกแถว + วัด % ความแม่นยำเทียบ label เดิม</li>
<li>Dashboard (กราฟ/incident/critical) <b>อัปเดตสด</b> ตามข้อมูลที่เข้ามา</li>
</ul>
</section>
<!-- 7 QDRANT -->
<section class="slide">
<div class="kicker">Production vector RAG</div>
<h2>Qdrant <span class="badge b-done">ใช้งานจริงแล้ว</span></h2>
<ul>
<li>เปลี่ยนจาก keyword/SQLite มาใช้ <b>Qdrant vector DB จริง</b> (self-host ผ่าน Docker)</li>
<li>Query → embed ด้วย OpenRouter (2048-dim) → ANN search บน Qdrant</li>
<li>Collection <code>roglag_logs</code> · Cosine · index logs จริง</li>
<li>สลับเป็น <b>Qdrant Cloud</b> ได้ทันทีแค่เปลี่ยน env โดยไม่ต้องแก้โค้ด</li>
</ul>
<div class="statline">
<div class="stat"><div class="big">2048</div><div class="l">vector dims</div></div>
<div class="stat"><div class="big">Cosine</div><div class="l">distance</div></div>
<div class="stat"><div class="big">~0.58</div><div class="l">semantic score</div></div>
</div>
</section>
<!-- 8 TECH STACK -->
<section class="slide">
<div class="kicker">Tech stack</div>
<h2>เทคโนโลยีที่ใช้</h2>
<div class="two">
<div>
<p class="lead" style="margin:0 0 8px;color:var(--accent)">เดโม่ (รันทันที)</p>
<ul>
<li>Python 3.12 · <code>http.server</code> stdlib</li>
<li>Vanilla JS + Three.js (globe)</li>
<li>Rule classifier + TF-IDF</li>
<li>In-memory + SQLite</li>
</ul>
</div>
<div>
<p class="lead" style="margin:0 0 8px;color:var(--accent2)">Production</p>
<ul>
<li>FastAPI + Uvicorn</li>
<li>SQLAlchemy + PostgreSQL</li>
<li>Qdrant + OpenRouter</li>
<li>Docker + docker-compose</li>
</ul>
</div>
</div>
</section>
<!-- 9 SELF-HOST -->
<section class="slide">
<div class="kicker">Deploy / Self-host</div>
<h2>รันได้จริง ทุกระดับ</h2>
<ul>
<li><b>เดโม่:</b> <code>python3 server.py</code> → เปิด <code>localhost:8000</code> ได้เลย</li>
<li><b>Self-host เต็ม:</b> <code>docker compose up</code> (API + PostgreSQL + Qdrant)</li>
<li><b>Cloud:</b> deploy บน Vercel (static + Python serverless)</li>
<li>เอกสารครบ: <code>/plan</code> · <code>/docs-html</code> · <code>/techstack.html</code></li>
</ul>
</section>
<!-- 10 NEXT -->
<section class="slide">
<div class="kicker">ก้าวต่อไป</div>
<h2>Roadmap</h2>
<div class="grid">
<div class="card"><h3>Ingestion จริง</h3><p>Vector/Fluent Bit → queue → worker classify+embed</p></div>
<div class="card"><h3>Automation</h3><p>n8n: alert → enrich (threat intel) → ticket/notify <small>(optional)</small></p></div>
<div class="card"><h3>Auth & Scale</h3><p>API auth, Redis pub/sub สำหรับ realtime หลาย worker</p></div>
<div class="card"><h3>Observability</h3><p>Prometheus + Grafana, retention/partition</p></div>
</div>
</section>
<!-- 11 CLOSING -->
<section class="slide">
<div class="kicker">สรุป</div>
<h1>จาก demo สู่<br><span class="grad">production-ready</span></h1>
<p class="lead">ตรวจจับ → ค้นหาเชิงความหมาย (Qdrant) → สรุปด้วย RAG → เห็นผลแบบเรียลไทม์ ทั้งหมดใน console เดียว self-host ได้จริง</p>
<div class="chips">
<span class="chip">localhost:8000</span><span class="chip">/techstack.html</span><span class="chip">/plan</span>
</div>
<p class="lead" style="margin-top:26px;font-size:18px;line-height:1.6">ขอบคุณครับ 🙏</p>
</section>
</div>
<div class="nav"><button onclick="go(-1)"></button><button onclick="go(1)"></button></div>
<div class="hud" id="hud">1 / 11</div>
<div class="hint">← → / Space เลื่อน · F fullscreen</div>
<script>
const slides = [...document.querySelectorAll(".slide")];
let i = 0;
function show(n){
i = Math.max(0, Math.min(slides.length - 1, n));
slides.forEach((s, k) => s.classList.toggle("active", k === i));
document.getElementById("hud").textContent = `${i + 1} / ${slides.length}`;
document.getElementById("bar").style.transform = `scaleX(${(i + 1) / slides.length})`;
}
function go(d){ show(i + d); }
document.addEventListener("keydown", (e) => {
if (["ArrowRight", " ", "PageDown"].includes(e.key)) { e.preventDefault(); go(1); }
else if (["ArrowLeft", "PageUp"].includes(e.key)) { e.preventDefault(); go(-1); }
else if (e.key === "Home") show(0);
else if (e.key === "End") show(slides.length - 1);
else if (e.key.toLowerCase() === "f") { document.fullscreenElement ? document.exitFullscreen() : document.documentElement.requestFullscreen(); }
});
document.getElementById("deck").addEventListener("click", (e) => { if (!e.target.closest(".nav")) go(1); });
show(0);
</script>
</body>
</html>