Spaces:
Running on Zero
Running on Zero
Mehdi commited on
Commit Β·
fffdc96
1
Parent(s): ee14d3e
feat: serve blog at /blog from main Space + badge showcase
Browse files- Mount blog/ as FastAPI static files at /blog so the blog lives on
the same Space as the app (no separate repo needed)
- Add badges section to blog/index.html: 5 earned, 1 locked
- Add badges table to BLOG.md
- BLOG.md +15 -0
- app.py +9 -1
- blog/index.html +75 -0
BLOG.md
CHANGED
|
@@ -40,6 +40,21 @@ PDF upload
|
|
| 40 |
|
| 41 |
---
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
## The Real Story: 68 Commits of Lessons
|
| 44 |
|
| 45 |
A hackathon README tells you what was built. The git log tells you what actually happened. Ours has 68 commits, and roughly two-thirds of them start with `fix:`. Here is the honest version.
|
|
|
|
| 40 |
|
| 41 |
---
|
| 42 |
|
| 43 |
+
## Badges Earned β 5 / 6
|
| 44 |
+
|
| 45 |
+
Build Small Hackathon awards merit badges for specific technical achievements. Here's where we landed:
|
| 46 |
+
|
| 47 |
+
| Badge | Status | What it took |
|
| 48 |
+
|---|---|---|
|
| 49 |
+
| **Off the Grid** | β
Earned | Zero external APIs β everything runs via ZeroGPU, no OpenAI key, no rate limits, no data leaving the machine |
|
| 50 |
+
| **Well-Tuned** | β
Earned | QLoRA fine-tune on SQuAD, model published at `build-small-hackathon/MiniCPM4-8B-PaperProf` |
|
| 51 |
+
| **Off-Brand** | β
Earned | Hand-built HTML/CSS/JS β Gradio is invisible, the entire UI is 100% custom (see Lesson 2 below) |
|
| 52 |
+
| **Llama Champion** | β
Earned | GGUF published at `build-small-hackathon/MiniCPM4-8B-PaperProf-GGUF`, llama.cpp CPU runtime wired in via `PAPERPROF_RUNTIME=llamacpp` |
|
| 53 |
+
| **Field Notes** | β
Earned | This post, plus the interactive `blog/index.html` site |
|
| 54 |
+
| Sharing is Caring | β | Share an agent trace on the Hub for the community |
|
| 55 |
+
|
| 56 |
+
---
|
| 57 |
+
|
| 58 |
## The Real Story: 68 Commits of Lessons
|
| 59 |
|
| 60 |
A hackathon README tells you what was built. The git log tells you what actually happened. Ours has 68 commits, and roughly two-thirds of them start with `fix:`. Here is the honest version.
|
app.py
CHANGED
|
@@ -12,6 +12,9 @@ try:
|
|
| 12 |
import threading
|
| 13 |
import gradio as gr
|
| 14 |
import spaces
|
|
|
|
|
|
|
|
|
|
| 15 |
from core.parser import extract_text
|
| 16 |
from core.chunker import chunk_text
|
| 17 |
from core.questioner import generate_question, generate_mcq
|
|
@@ -1074,4 +1077,9 @@ with gr.Blocks(title="PaperProf", css=CSS) as demo:
|
|
| 1074 |
print("β
Gradio demo defined successfully")
|
| 1075 |
|
| 1076 |
print("β
Launching demo...")
|
| 1077 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
import threading
|
| 13 |
import gradio as gr
|
| 14 |
import spaces
|
| 15 |
+
import uvicorn
|
| 16 |
+
from fastapi import FastAPI
|
| 17 |
+
from fastapi.staticfiles import StaticFiles
|
| 18 |
from core.parser import extract_text
|
| 19 |
from core.chunker import chunk_text
|
| 20 |
from core.questioner import generate_question, generate_mcq
|
|
|
|
| 1077 |
print("β
Gradio demo defined successfully")
|
| 1078 |
|
| 1079 |
print("β
Launching demo...")
|
| 1080 |
+
_fastapi = FastAPI()
|
| 1081 |
+
app = gr.mount_gradio_app(_fastapi, demo, path="/")
|
| 1082 |
+
app.mount("/blog", StaticFiles(directory="blog", html=True), name="blog")
|
| 1083 |
+
|
| 1084 |
+
if __name__ == "__main__":
|
| 1085 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|
blog/index.html
CHANGED
|
@@ -358,6 +358,33 @@ td strong { color: #fff; font-weight: 600; }
|
|
| 358 |
.btn:hover span { color: #07090F; }
|
| 359 |
|
| 360 |
footer { position: relative; z-index: 1; max-width: 1060px; margin: 0 auto; padding: 70px 28px 46px; display: flex; flex-wrap: wrap; gap: 12px 40px; justify-content: space-between; font-family: var(--mono); font-size: .74rem; letter-spacing: 1px; color: var(--faint); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
</style>
|
| 362 |
</head>
|
| 363 |
<body>
|
|
@@ -397,6 +424,54 @@ footer { position: relative; z-index: 1; max-width: 1060px; margin: 0 auto; padd
|
|
| 397 |
<div class="stat reveal"><span class="stat-num" data-count="0">0</span><span class="stat-label">external APIs</span></div>
|
| 398 |
</section>
|
| 399 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
<main id="article">
|
| 401 |
|
| 402 |
<p class="lede reveal">It's 11 PM, the exam is tomorrow, and you're re-reading the same lecture PDF for the fourth time, feeling productive while learning nothing. Passive re-reading is one of the worst study techniques on record. Active recall, forcing yourself to answer questions, is one of the best.</p>
|
|
|
|
| 358 |
.btn:hover span { color: #07090F; }
|
| 359 |
|
| 360 |
footer { position: relative; z-index: 1; max-width: 1060px; margin: 0 auto; padding: 70px 28px 46px; display: flex; flex-wrap: wrap; gap: 12px 40px; justify-content: space-between; font-family: var(--mono); font-size: .74rem; letter-spacing: 1px; color: var(--faint); }
|
| 361 |
+
|
| 362 |
+
/* ============ BADGES ============ */
|
| 363 |
+
.badges-section { position: relative; z-index: 1; max-width: 1060px; margin: 72px auto 0; padding: 0 28px; }
|
| 364 |
+
.badges-header { display: flex; align-items: flex-end; gap: 28px; margin-bottom: 32px; flex-wrap: wrap; }
|
| 365 |
+
.badges-eyebrow { font-family: var(--mono); font-size: .74rem; letter-spacing: 3px; text-transform: uppercase; color: var(--cyan); display: block; margin-bottom: 10px; }
|
| 366 |
+
.badges-score { font-family: var(--display); font-weight: 700; font-size: clamp(2rem, 5vw, 3rem); letter-spacing: -2px; color: #fff; line-height: 1; }
|
| 367 |
+
.badges-score em { font-style: normal; font-size: .55em; color: var(--dim); font-weight: 400; letter-spacing: -0.5px; }
|
| 368 |
+
.badges-note { font-family: var(--mono); font-size: .76rem; color: var(--dim); max-width: 340px; line-height: 1.6; border-left: 2px solid var(--line-hot); padding-left: 16px; }
|
| 369 |
+
.badges-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 14px; }
|
| 370 |
+
.badge {
|
| 371 |
+
background: var(--bg-raise); border: 1px solid var(--line); border-radius: 18px;
|
| 372 |
+
padding: 24px 22px; display: flex; flex-direction: column; gap: 13px;
|
| 373 |
+
transition: border-color .3s, transform .3s;
|
| 374 |
+
}
|
| 375 |
+
.badge.earned { border-color: rgba(74,222,128,0.28); }
|
| 376 |
+
.badge.earned:hover { border-color: rgba(74,222,128,0.6); transform: translateY(-5px); }
|
| 377 |
+
.badge.locked { opacity: 0.42; }
|
| 378 |
+
.badge-icon { font-size: 2rem; line-height: 1; }
|
| 379 |
+
.badge-name { font-family: var(--display); font-weight: 700; font-size: 1rem; color: #fff; letter-spacing: -0.3px; }
|
| 380 |
+
.badge-desc { font-family: var(--mono); font-size: .72rem; color: var(--dim); line-height: 1.6; flex: 1; }
|
| 381 |
+
.badge-chip {
|
| 382 |
+
display: inline-block; align-self: flex-start;
|
| 383 |
+
font-family: var(--mono); font-size: .65rem; letter-spacing: 2px; text-transform: uppercase;
|
| 384 |
+
border-radius: 50px; padding: 4px 12px;
|
| 385 |
+
}
|
| 386 |
+
.badge.earned .badge-chip { color: var(--green); background: rgba(74,222,128,0.08); border: 1px solid rgba(74,222,128,0.22); }
|
| 387 |
+
.badge.locked .badge-chip { color: var(--faint); background: transparent; border: 1px solid rgba(255,255,255,0.08); }
|
| 388 |
</style>
|
| 389 |
</head>
|
| 390 |
<body>
|
|
|
|
| 424 |
<div class="stat reveal"><span class="stat-num" data-count="0">0</span><span class="stat-label">external APIs</span></div>
|
| 425 |
</section>
|
| 426 |
|
| 427 |
+
<section class="badges-section" aria-label="Hackathon badges earned">
|
| 428 |
+
<div class="badges-header reveal">
|
| 429 |
+
<div>
|
| 430 |
+
<span class="badges-eyebrow">Build Small Hackathon Β· Merit Badges</span>
|
| 431 |
+
<p class="badges-score">5 <em>/ 6 earned</em></p>
|
| 432 |
+
</div>
|
| 433 |
+
<p class="badges-note">Build Small awards badges for specific technical achievements. We collected five of six β every badge we could earn by shipping real, verifiable work.</p>
|
| 434 |
+
</div>
|
| 435 |
+
<div class="badges-grid">
|
| 436 |
+
<div class="badge earned reveal">
|
| 437 |
+
<span class="badge-icon">π</span>
|
| 438 |
+
<strong class="badge-name">Off the Grid</strong>
|
| 439 |
+
<span class="badge-desc">Zero external APIs. MiniCPM4-8B and FLUX.2-klein run entirely on ZeroGPU β no OpenAI key, no rate limits, no data leaving the machine.</span>
|
| 440 |
+
<span class="badge-chip">β Earned</span>
|
| 441 |
+
</div>
|
| 442 |
+
<div class="badge earned reveal">
|
| 443 |
+
<span class="badge-icon">π―</span>
|
| 444 |
+
<strong class="badge-name">Well-Tuned</strong>
|
| 445 |
+
<span class="badge-desc">QLoRA fine-tune on SQuAD via Modal. Model published on Hugging Face at <code>build-small-hackathon/MiniCPM4-8B-PaperProf</code>.</span>
|
| 446 |
+
<span class="badge-chip">β Earned</span>
|
| 447 |
+
</div>
|
| 448 |
+
<div class="badge earned reveal">
|
| 449 |
+
<span class="badge-icon">π¨</span>
|
| 450 |
+
<strong class="badge-name">Off-Brand</strong>
|
| 451 |
+
<span class="badge-desc">Hand-built HTML/CSS/JS over a hidden-Gradio bridge. Glassmorphism, animated score ring, dark academia palette β no default Gradio chrome visible.</span>
|
| 452 |
+
<span class="badge-chip">β Earned</span>
|
| 453 |
+
</div>
|
| 454 |
+
<div class="badge earned reveal">
|
| 455 |
+
<span class="badge-icon">π¦</span>
|
| 456 |
+
<strong class="badge-name">Llama Champion</strong>
|
| 457 |
+
<span class="badge-desc">GGUF published at <code>build-small-hackathon/MiniCPM4-8B-PaperProf-GGUF</code>. llama.cpp CPU runtime wired in via <code>PAPERPROF_RUNTIME=llamacpp</code>.</span>
|
| 458 |
+
<span class="badge-chip">β Earned</span>
|
| 459 |
+
</div>
|
| 460 |
+
<div class="badge earned reveal">
|
| 461 |
+
<span class="badge-icon">π</span>
|
| 462 |
+
<strong class="badge-name">Field Notes</strong>
|
| 463 |
+
<span class="badge-desc">This post β 68 commits, 10 days, zero sugarcoating. Honest account of what broke and what shipped.</span>
|
| 464 |
+
<span class="badge-chip">β Earned</span>
|
| 465 |
+
</div>
|
| 466 |
+
<div class="badge locked reveal">
|
| 467 |
+
<span class="badge-icon">π€</span>
|
| 468 |
+
<strong class="badge-name">Sharing is Caring</strong>
|
| 469 |
+
<span class="badge-desc">Share an agent trace on the Hub so the community can learn from your runs.</span>
|
| 470 |
+
<span class="badge-chip">Not yet</span>
|
| 471 |
+
</div>
|
| 472 |
+
</div>
|
| 473 |
+
</section>
|
| 474 |
+
|
| 475 |
<main id="article">
|
| 476 |
|
| 477 |
<p class="lede reveal">It's 11 PM, the exam is tomorrow, and you're re-reading the same lecture PDF for the fourth time, feeling productive while learning nothing. Passive re-reading is one of the worst study techniques on record. Active recall, forcing yourself to answer questions, is one of the best.</p>
|