Spaces:
Runtime error
A newer version of the Gradio SDK is available: 6.20.0
title: Recall — AI Study Partner
emoji: 📚
colorFrom: indigo
colorTo: green
sdk: gradio
sdk_version: 6.17.3
app_file: server.py
pinned: false
license: mit
📚 Recall — an AI study partner that gets smarter about what you get wrong
Upload your study material → Recall generates a quiz deck → you answer → a small model grades and explains each answer → it generates new questions targeting exactly what you missed → end-of-session recap. Built for the Build Small Hackathon (Backyard AI track).
- Model: openbmb/MiniCPM4.1-8B (fallback: MiniCPM5-1B)
- Platform: Gradio app, hosted as a Hugging Face Space
Run it (stub mode — no GPU, no model download)
pip install -r requirements.txt
python server.py # http://127.0.0.1:7860 ← polished custom frontend
Everything works end-to-end on canned data, so anyone can clone and click through the full loop in minute one.
server.py serves the Recall design (frontend/index.html) and a thin JSON
API over the existing backend — the learning/content logic and the schema.py
data contract are treated as an API and are never modified. The original Gradio
form is still available as a fallback at /gradio (and standalone via
python app.py).
Run with the real model
The heavy model deps (torch/transformers/…) are kept out of requirements.txt so
the Space build stays fast in stub mode. Install them with the model requirements:
pip install -r requirements-model.txt
RECALL_STUB=0 python server.py
Dependency pins (why they're tight). MiniCPM4.1-8B's
trust_remote_codeimports symbols removed in transformers 5.x, so the real model needstransformers >=4.55,<5.0. That in turn requireshuggingface-hub <1.0, which gradio 6.18 forbids (it needshub >=1.2) — sorequirements.txtand the Spacesdk_versionare pinned to gradio 6.17.3 (the newest gradio that still allowshub <1.0). Because a gradio-SDK Space force-installs one gradio for the whole Space, stub and real-model share it; 6.17.3 keeps both working without a Docker Space. The 1B fallback has no such constraint.
On Apple Silicon (M1/M2/…), the default bf16 + MPS combo produces garbage output (a known MPS bf16 instability — not present on the Space's CUDA GPU). For a clean local real-model smoke test, force CPU/float32:
RECALL_STUB=0 RECALL_MODEL=1b RECALL_DTYPE=float32 RECALL_DEVICE=cpu python server.py
The model
Recall runs on openbmb/MiniCPM4.1-8B, an 8B open model from OpenBMB chosen for the Backyard AI track: small enough to serve on a single Hugging Face ZeroGPU Space, capable enough to grade free-text answers and write grounded follow-up questions.
Where the model is load-bearing. Two user-visible features are pure model work, not templated strings:
- Grading — it compares your free-text answer to the reference answer and returns a 0–5 score, a plain-language explanation, and the specific concept you missed.
- Adaptive follow-ups — from that missed concept it writes brand-new questions that drill exactly what you got wrong.
How inference is served. Everything model-related goes through a single chat(messages, max_tokens) wrapper in llm.py; no other module imports transformers directly. The model is loaded once (lazily, via AutoModelForCausalLM in bf16 with device_map="auto") on the Space's ZeroGPU, with the GPU entrypoint wrapped in @spaces.GPU. max_tokens is kept tight (256–512) because latency is the demo-killer. Model output is never trusted: replies expected to be JSON are parsed defensively, with one repair retry and a safe fallback so a malformed generation can never crash the study loop.
Stub mode. With RECALL_STUB=1 (the default) chat() returns canned replies, so the whole app runs and demos end-to-end with no GPU and no model download. Flip RECALL_STUB=0 to use the real model.
Fallback (config flip, no code change). If the Space is too slow or runs out of memory, swap to a smaller model by setting RECALL_MODEL — the rest of the pipeline is unchanged:
# fast fallback
RECALL_MODEL=openbmb/MiniCPM5-1B RECALL_STUB=0 python app.py
# mid fallback (also earns the Tiny Titan badge)
RECALL_MODEL=openbmb/MiniCPM3-4B RECALL_STUB=0 python app.py
Project layout
| File | Owner | What it is |
|---|---|---|
schema.py |
shared | The data contract (Card, CardState, GradeResult, Session). Don't change without a sync. |
llm.py |
Nikolai | Shared MiniCPM inference wrapper + defensive JSON parsing. |
learning_engine.py |
Nikolai | Scheduling (SM-2-lite), grading, adaptation, follow-ups, recap. |
content_pipeline.py |
Frank | PDF/text → chunks → question cards. |
app.py |
Arturo | Gradio UI (Upload / Study / Recap) over gr.State — fallback at /gradio. |
server.py |
— | FastAPI server: serves the custom frontend + JSON API over the backend. |
frontend/index.html |
— | The polished Recall design (Upload / Study / Recap), vanilla HTML/CSS/JS. |
How to work in parallel
- At kickoff, lock
schema.pytogether. - Each module already ships working stubs — build your real logic behind the
same function signatures, flip
RECALL_STUB=0to test for real. - Don't change public function signatures without telling the team.
The judging hook
The small model is load-bearing in two visible places: grading free-text answers with explanations, and generating follow-up questions that drill the exact concept you missed. Make sure the demo shows both.