Jerry
feat: add 9-slide HTML presentation deck and link in README
c57da4f
Raw
History Blame Contribute Delete
17.8 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Logistics Coordinator — OpenEnv Hackathon 2026</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700;900&family=JetBrains+Mono:wght@400;600&display=swap');
:root {
--bg: #0d1117; --surface: #161b22; --border: #30363d;
--text: #e6edf3; --muted: #8b949e; --green: #3fb950;
--red: #f85149; --blue: #58a6ff; --orange: #f0883e;
--accent: #238636;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; background: var(--bg); font-family: 'Inter', sans-serif; color: var(--text); overflow: hidden; }
.deck { width: 100%; height: 100vh; position: relative; }
.slide {
display: none; position: absolute; inset: 0;
flex-direction: column; justify-content: center; align-items: center;
padding: 60px 80px; text-align: center;
background: radial-gradient(ellipse at 50% 0%, #161b22 0%, #0d1117 70%);
}
.slide.active { display: flex; }
h1 { font-size: 2.8rem; font-weight: 900; line-height: 1.15; }
h2 { font-size: 2rem; font-weight: 700; margin-bottom: 1rem; }
h3 { font-size: 1.3rem; font-weight: 600; color: var(--blue); margin-bottom: 0.5rem; }
p { font-size: 1.1rem; line-height: 1.7; color: var(--muted); max-width: 800px; }
.tag {
display: inline-block; padding: 4px 12px; border-radius: 20px;
font-size: 0.8rem; font-weight: 600; margin: 4px;
background: rgba(88,166,255,0.1); border: 1px solid var(--blue); color: var(--blue);
}
.tag.green { background: rgba(63,185,80,0.1); border-color: var(--green); color: var(--green); }
.tag.orange { background: rgba(240,136,62,0.1); border-color: var(--orange); color: var(--orange); }
.highlight {
font-size: 4rem; font-weight: 900;
background: linear-gradient(135deg, var(--green), var(--blue));
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
}
.sub { font-size: 1rem; color: var(--muted); margin-top: 0.25rem; }
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; width: 100%; max-width: 1000px; margin-top: 1.5rem; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.card {
background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
padding: 20px; text-align: left;
}
.card .icon { font-size: 1.8rem; margin-bottom: 8px; }
.card h4 { font-size: 1rem; font-weight: 600; margin-bottom: 6px; }
.card p { font-size: 0.85rem; color: var(--muted); max-width: none; }
.metric { display: flex; flex-direction: column; align-items: center; padding: 24px 12px; }
.metric .num { font-size: 2.4rem; font-weight: 900; color: var(--green); }
.metric .label { font-size: 0.8rem; color: var(--muted); text-align: center; margin-top: 4px; }
.badge {
display: inline-block; padding: 6px 16px; border-radius: 6px;
background: var(--accent); color: #fff; font-weight: 700;
font-size: 0.9rem; margin: 6px;
}
.badge.red { background: #6e1d1a; }
.badge.blue { background: #0c2d6b; }
table { width: 100%; border-collapse: collapse; font-size: 0.9rem; margin-top: 1rem; }
th { background: var(--surface); color: var(--blue); padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--border); }
td { padding: 10px 14px; border-bottom: 1px solid var(--border); color: var(--muted); }
td strong { color: var(--text); }
.reward-bar { display: flex; align-items: center; gap: 12px; margin: 6px 0; }
.reward-bar .label { width: 160px; text-align: right; font-size: 0.85rem; color: var(--muted); flex-shrink: 0; }
.reward-bar .bar-wrap { flex: 1; background: var(--border); border-radius: 4px; height: 16px; }
.reward-bar .bar { height: 16px; border-radius: 4px; transition: width 0.6s ease; }
.reward-bar .val { font-size: 0.85rem; font-weight: 700; flex-shrink: 0; width: 55px; }
.code {
font-family: 'JetBrains Mono', monospace; font-size: 0.85rem;
background: var(--surface); border: 1px solid var(--border);
border-radius: 8px; padding: 16px; text-align: left;
color: var(--green); width: 100%; max-width: 700px; margin-top: 1rem;
}
.code .comment { color: var(--muted); }
.penalty { color: var(--red); font-weight: 700; }
.bonus { color: var(--green); font-weight: 700; }
/* Nav */
.nav {
position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%);
display: flex; gap: 12px; align-items: center; z-index: 100;
background: rgba(22,27,34,0.9); border: 1px solid var(--border);
border-radius: 40px; padding: 10px 20px; backdrop-filter: blur(10px);
}
.nav button {
background: none; border: none; color: var(--muted); cursor: pointer;
font-size: 1.1rem; padding: 4px 10px; border-radius: 20px; transition: all 0.2s;
}
.nav button:hover { background: var(--surface); color: var(--text); }
.nav .counter { color: var(--muted); font-size: 0.85rem; min-width: 50px; text-align: center; }
.slide-num {
position: fixed; top: 20px; right: 30px;
font-size: 0.8rem; color: var(--border);
}
.logo { font-size: 3.5rem; margin-bottom: 16px; }
.subtitle { font-size: 1.2rem; color: var(--muted); margin-top: 12px; }
.spacer { margin-top: 1.5rem; }
.link { color: var(--blue); text-decoration: none; font-size: 0.85rem; }
.link:hover { text-decoration: underline; }
/* Animate in */
.slide.active .card, .slide.active .metric {
animation: fadeUp 0.4s ease both;
}
.slide.active .card:nth-child(2) { animation-delay: 0.08s; }
.slide.active .card:nth-child(3) { animation-delay: 0.16s; }
.slide.active .card:nth-child(4) { animation-delay: 0.24s; }
@keyframes fadeUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.arrow { font-size: 1.4rem; color: var(--border); margin: 0 8px; }
.flow { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; margin-top: 1.5rem; gap: 4px; }
.flow-step {
background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
padding: 10px 18px; font-size: 0.9rem; font-weight: 600;
}
</style>
</head>
<body>
<div class="deck">
<!-- SLIDE 1: TITLE -->
<div class="slide active">
<div class="logo">🚛</div>
<h1>AI Logistics Coordinator</h1>
<p class="subtitle">Teaching an LLM to manage freight crises using GRPO reinforcement learning</p>
<div class="spacer"></div>
<div>
<span class="tag green">OpenEnv Compatible</span>
<span class="tag">GRPO + TRL + Unsloth</span>
<span class="tag orange">Qwen2.5-1.5B</span>
<span class="tag">Meta PyTorch Hackathon 2026</span>
</div>
<div class="spacer"></div>
<p>
<a class="link" href="https://huggingface.co/spaces/Leavin1611/logistics-hackathon-env">🤗 Live Space</a> &nbsp;·&nbsp;
<a class="link" href="https://huggingface.co/Leavin1611/logistics-hackathon-model">🧠 Trained Model</a> &nbsp;·&nbsp;
<a class="link" href="https://colab.research.google.com/drive/1fRfheRZd1tffKjXKZkW72ffl9JPxDpL8">📓 Colab Notebook</a>
</p>
</div>
<!-- SLIDE 2: THE PROBLEM -->
<div class="slide">
<h2>It's 3 AM. A port strike just shut down Mumbai.</h2>
<p>COVID vaccines are stranded on Route R1. Election ballots are stuck at Delhi. ₹1.8 crore of server hardware is 7 hours late. A human dispatcher needs 30 minutes to triage this. We built an agent that does it in seconds.</p>
<div class="grid grid-2" style="margin-top: 2rem; max-width: 800px;">
<div class="card">
<div class="icon"></div>
<h4>Current Systems</h4>
<p>Rule-based optimizers. Great at routine scheduling. Fail completely when disruptions cascade. Cannot reason, cannot prioritize, cannot communicate.</p>
</div>
<div class="card">
<div class="icon"></div>
<h4>Our Agent</h4>
<p>Reasons about network congestion, triages by urgency, reroutes strategically, and sends empathetic messages to customers — all in a single turn.</p>
</div>
</div>
</div>
<!-- SLIDE 3: ENVIRONMENT -->
<div class="slide">
<h2>🌍 The Environment</h2>
<p>A real-time Indian freight network crisis simulator. The agent plays a centralized logistics coordinator managing cascading disruptions across JNPT, Delhi, and Mundra.</p>
<div class="grid" style="margin-top: 1.5rem;">
<div class="card">
<div class="icon">👁️</div>
<h4>What Agent Sees</h4>
<p>Shipment states, route congestion (0–100%), active disruptions, SLA time remaining, carrier availability</p>
</div>
<div class="card">
<div class="icon">🎮</div>
<h4>What Agent Does</h4>
<p><code>get_network_status</code> · <code>reroute_shipment</code> · <code>set_priority</code> · <code>communicate_eta</code> · <code>end_turn</code></p>
</div>
<div class="card">
<div class="icon">🏆</div>
<h4>Three Task Tiers</h4>
<p>EASY (2 ships, 1 disruption) → MEDIUM (4 ships, 3 disruptions) → HARD (7 ships, 4 failures)</p>
</div>
</div>
</div>
<!-- SLIDE 4: WHAT MAKES IT NOVEL -->
<div class="slide">
<h2>🔬 What Makes This Novel</h2>
<div class="grid grid-2" style="max-width: 900px; margin-top: 1.5rem;">
<div class="card">
<div class="icon">🌐</div>
<h4>Multi-Agent Pressure</h4>
<p>Background agents compete for the same limited route capacity every turn. The agent must model the network — not just react to individual shipments.</p>
</div>
<div class="card">
<div class="icon"></div>
<h4>Long-Horizon Planning</h4>
<p>5–7 turn episodes. Early decisions cascade. Saving the pharmaceutical shipment on turn 1 changes which routes are available on turn 4.</p>
</div>
<div class="card">
<div class="icon">🧠</div>
<h4>World Modeling Required</h4>
<p>Partially observable. The agent must call tools to see the network. It cannot assume anything — it must build its own world model each turn.</p>
</div>
<div class="card">
<div class="icon">💬</div>
<h4>NLP-Graded Communication</h4>
<p>ETA messages are scored for empathy, specificity, and cause explanation. A unique test of "soft skills" that no other logistics env tests.</p>
</div>
</div>
</div>
<!-- SLIDE 5: REWARD DESIGN -->
<div class="slide">
<h2>🎯 Anti-Gameable Reward Design</h2>
<p>Three independent reward functions. Each has explicit negative penalties to prevent exploitation.</p>
<div class="grid" style="margin-top: 1.5rem;">
<div class="card">
<h4>🏗️ Structure Reward</h4>
<p><span class="bonus">+0.4</span> Start with status check<br><span class="bonus">+0.3</span> End with end_turn<br><span class="penalty">-0.5</span> Duplicate end_turn (spam)<br><span class="penalty">-0.3</span> Repeated status calls</p>
</div>
<div class="card">
<h4>🛣️ Routing Reward</h4>
<p><span class="bonus">+0.9</span> Clear route chosen<br><span class="bonus">+0.5</span> All ships rerouted<br><span class="penalty">-0.6</span> Congested route<br><span class="penalty">-0.8</span> Empty route ID (loophole)</p>
</div>
<div class="card">
<h4>📢 Communication Reward</h4>
<p><span class="bonus">+0.4</span> Message to delayed ship<br><span class="bonus">+0.2</span> Empathy keywords<br><span class="bonus">+0.1</span> Specific ETA given<br><span class="penalty">-0.3</span> Duplicate message (spam)</p>
</div>
</div>
</div>
<!-- SLIDE 6: TRAINING PIPELINE -->
<div class="slide">
<h2>🏋️ 4-Phase GRPO Curriculum</h2>
<p>Group Relative Policy Optimization — the same algorithm behind DeepSeek-R1 — on a free Colab T4 GPU.</p>
<div class="flow">
<div class="flow-step">🟢 Phase 1<br><small>TASK-EASY<br>lr=2e-5</small></div>
<span class="arrow"></span>
<div class="flow-step">🟡 Phase 2<br><small>TASK-MEDIUM<br>lr=1e-5</small></div>
<span class="arrow"></span>
<div class="flow-step">🔥 Phase 3<br><small>Mixed Hardening<br>6 rollouts</small></div>
<span class="arrow"></span>
<div class="flow-step">🚨 Phase 4<br><small>Correction Cycle<br>Loophole patch</small></div>
</div>
<div class="grid grid-4" style="margin-top: 1.5rem; max-width: 900px;">
<div class="metric"><div class="num">1.5B</div><div class="label">Model size<br>(Qwen2.5)</div></div>
<div class="metric"><div class="num">4-bit</div><div class="label">QLoRA quantization<br>(Unsloth)</div></div>
<div class="metric"><div class="num">150+</div><div class="label">Training<br>episodes</div></div>
<div class="metric"><div class="num">Free</div><div class="label">Colab T4<br>GPU</div></div>
</div>
</div>
<!-- SLIDE 7: RESULTS -->
<div class="slide">
<h2>📈 Results: Observable Evidence</h2>
<div class="highlight">+327%</div>
<div class="sub">Live environment reward improvement (0.18 baseline → 0.7683 trained)</div>
<div style="width: 100%; max-width: 700px; margin-top: 2rem;">
<div class="reward-bar">
<div class="label">Untrained Baseline</div>
<div class="bar-wrap"><div class="bar" style="width:23.4%;background:var(--red)"></div></div>
<div class="val" style="color:var(--red)">0.18</div>
</div>
<div class="reward-bar">
<div class="label">After Phase 1 (Easy)</div>
<div class="bar-wrap"><div class="bar" style="width:54.7%;background:var(--muted)"></div></div>
<div class="val" style="color:var(--muted)">0.42</div>
</div>
<div class="reward-bar">
<div class="label">After Phase 2 (Medium)</div>
<div class="bar-wrap"><div class="bar" style="width:79.4%;background:var(--orange)"></div></div>
<div class="val" style="color:var(--orange)">0.61</div>
</div>
<div class="reward-bar">
<div class="label">Final (lora-final-perfect)</div>
<div class="bar-wrap"><div class="bar" style="width:100%;background:var(--green)"></div></div>
<div class="val" style="color:var(--green)">0.7683</div>
</div>
</div>
</div>
<!-- SLIDE 8: WHAT THE AGENT LEARNED -->
<div class="slide">
<h2>🤖 What the Agent Actually Learned</h2>
<div class="grid grid-2" style="max-width: 900px; margin-top: 1.5rem;">
<div class="card">
<div class="icon">🔍</div>
<h4>World Modeling</h4>
<p>Always calls <code>get_network_status</code> first. Builds a mental model of the entire network before acting — not guessing.</p>
</div>
<div class="card">
<div class="icon">🛣️</div>
<h4>Strategic Routing</h4>
<p>Checks route congestion before rerouting. Avoids the -0.6 penalty for choosing overloaded routes. 3+ reroutes per episode vs 1 before training.</p>
</div>
<div class="card">
<div class="icon">💬</div>
<h4>Empathetic Communication</h4>
<p>Sends well-formed apologies with specific ETAs and causes. "We sincerely apologise — your shipment will arrive by 6PM due to port congestion."</p>
</div>
<div class="card">
<div class="icon">🚫</div>
<h4>Stopped Hacking</h4>
<p>Stopped spamming messages and empty routes after Phase 4 correction. Learned that strategic play earns more reward than loopholes.</p>
</div>
</div>
</div>
<!-- SLIDE 9: LINKS & RESOURCES -->
<div class="slide">
<h2>🔗 All Submission Links</h2>
<table style="max-width: 700px; margin-top: 1rem;">
<tr><th>Resource</th><th>Link</th></tr>
<tr><td>🤗 Live HF Space</td><td><a class="link" href="https://huggingface.co/spaces/Leavin1611/logistics-hackathon-env">spaces/Leavin1611/logistics-hackathon-env</a></td></tr>
<tr><td>🧠 Trained Model</td><td><a class="link" href="https://huggingface.co/Leavin1611/logistics-hackathon-model">Leavin1611/logistics-hackathon-model</a></td></tr>
<tr><td>📓 Training Notebook</td><td><a class="link" href="https://colab.research.google.com/drive/1fRfheRZd1tffKjXKZkW72ffl9JPxDpL8">Open in Colab</a></td></tr>
<tr><td>📝 Mini-Blog</td><td><a class="link" href="https://huggingface.co/spaces/Leavin1611/logistics-hackathon-env/blob/main/HF_BLOG_POST.md">HF_BLOG_POST.md</a></td></tr>
<tr><td>🏗️ Environment Code</td><td><a class="link" href="https://huggingface.co/spaces/Leavin1611/logistics-hackathon-env/blob/main/server/environment.py">server/environment.py</a></td></tr>
</table>
<div class="spacer"></div>
<p><em>Stack: OpenEnv · FastAPI · TRL · GRPO · Unsloth · Qwen2.5-1.5B · Google Colab T4</em></p>
</div>
</div>
<!-- Nav -->
<div class="nav">
<button onclick="prev()"></button>
<span class="counter" id="counter">1 / 9</span>
<button onclick="next()"></button>
</div>
<script>
let current = 0;
const slides = document.querySelectorAll('.slide');
function show(n) {
slides[current].classList.remove('active');
current = (n + slides.length) % slides.length;
slides[current].classList.add('active');
document.getElementById('counter').textContent = `${current+1} / ${slides.length}`;
}
function next() { show(current + 1); }
function prev() { show(current - 1); }
document.addEventListener('keydown', e => {
if (e.key === 'ArrowRight' || e.key === ' ') next();
if (e.key === 'ArrowLeft') prev();
});
</script>
</body>
</html>