Inspiration
Every teacher rehearses what they'll say. Almost none of them get to rehearse how a room full of different minds will receive it — until the lesson is live, a six-year-old is staring back blankly, and it's too late to change course.
We kept coming back to one moment every teacher knows: you give the explanation you were sure would work, and half the class still doesn't get it. The gap isn't in the content — it's in the delivery, and today the only place to discover that gap is in front of real children.
So we asked: what if a teacher could get a flight simulator for teaching — rehearse a real lesson with a class of students who each start with their own knowledge, confidence, and misconceptions, and who actually learn (or stay stuck) based on how you teach them?
What it does
AI Classroom Simulator turns any lesson into a live rehearsal with five simulated students.
- Upload a lesson (PDF, PPTX, DOCX, or TXT). We extract the text and build a structured Lesson Model — the concepts, prerequisites, and the misconceptions students typically bring.
- Generate a class. In a single call we create five age-authentic students with deliberately different starting points — a bold blurt-er, a quiet struggler, a distracted joker, a careful worker, a strong-but-subtly-gapped thinker. Each gets a photorealistic portrait and a distinct child's voice. Their personalities are visible; their understanding is hidden, exactly like a real classroom.
- Teach, out loud. You share your slides and just talk. Your speech is transcribed in real time, and the students respond to what you said — raising hands, answering in character, or honestly saying "I don't know" when you haven't taught it yet.
- See the learning. When you finish, the Classroom X-Ray shows what happened to each mind: who moved from confused to partial understanding, at exactly which moment, with the real transcript line that caused the change linked as evidence.
The core magic is a loop you can watch happen: a shy student can't answer → you give a specific explanation → the same student, in the same voice, answers correctly a minute later — because their internal state actually changed.
How we built it
The whole thing is a modular monolith — one Next.js (App Router) + TypeScript app, no database, session state held in memory. We deliberately avoided "five persistent chatbots."
The heart of the system is that a student is structured state, not a conversation:
$$\text{StudentState} = {\, \text{mastery} \in {0,1,2,3,4},\ \text{misconceptions} \in {0,1,2,3},\ \text{confusion},\ \text{engagement} \in [0,1] \,}$$
For each meaningful teacher utterance, one GPT-5.6 orchestrator call classifies the utterance, picks at most one speaker, and proposes bounded state patches. Then deterministic code — not the model — validates and commits them: a patch is rejected unless it cites real evidence, references a known concept ID, and moves any value by at most one step:
$$\Delta_{\text{mastery}} \in {-1, 0, +1} \quad\text{per teacher event}$$
This keeps learning explicit, inspectable, and replayable. The report generator reads the same event log, so every claim in the X-Ray is backed by a real event ID and an exact transcript quote.
Model split:
- GPT-5.6 Terra (quality-sensitive, off the live path): lesson analysis, class generation, X-Ray.
- GPT-5.6 Luna (latency-sensitive): live orchestration and student responses.
- OpenAI Realtime API over WebRTC: continuous teacher transcription.
- OpenAI Speech (TTS): a distinct child voice per student, steered by per-student instructions.
- gpt-image-1: the fictional student portraits.
- Zod + Structured Outputs everywhere the model returns data.
We used Codex heavily to derive the schemas, the orchestration contract, the deterministic reducer, and the test fixtures — and kept a fully deterministic fallback orchestrator so the core loop runs even when the live API is unavailable.
Challenges we ran into
- The students were too smart. Early on, everyone answered correctly — including questions we hadn't taught yet. We fixed this in two layers: deterministic post-processing that guarantees a genuine spread of ability (one student is forced to $\text{mastery}=0$ everywhere), and non-negotiable prompt rules that tie answer quality to mastery, so a student who doesn't know something says "I don't know" instead of quietly acing it.
- Silent failures hiding real bugs. Our orchestrator was wrapped in a fallback, so when the OpenAI call actually failed (an unsupported
.optional()in a Structured-Outputs schema, and a request timeout on large lessons), it silently degraded to canned responses and looked like it was working. Making failures loud was half the battle. - Age authenticity. A "smart" seven-year-old shouldn't talk like a textbook. We made every layer age-aware — deriving age from the lesson's grade band and feeding it into generation, orchestration, and the TTS voice instructions — so high mastery means confidently doing the age-level skill, not sounding older.
- Making learning provable, not vibes. It's easy to have a model say a student improved. Tying every X-Ray claim to a real event ID and an exact-substring transcript quote — and rejecting anything invented — took real discipline in the reducer and validator.
Accomplishments that we're proud of
- The magic loop works reliably: shy student can't answer → targeted explanation → same student answers correctly, generated from the post-explanation state.
- Evidence-linked, not hallucinated. Every insight in the Classroom X-Ray points back to a real moment in the session.
- Genuinely different students — in ability, personality, voice, and face — that behave like six-year-olds, not seminar attendees.
- A clean, debuggable architecture: one orchestration call per turn, deterministic validation, replayable event log — with a deterministic fallback that keeps the demo alive under any API hiccup.
What we learned
- Persistence belongs in structured state, not in an opaque conversation. Modeling a learner as data made the whole system cheaper, more consistent, and — crucially — inspectable.
- Let the model propose; let code decide. Bounded patches + a deterministic reducer gave us believable learning without ungrounded jumps.
- Constraints make characters. The students only became believable once we restricted them — capping mastery, forcing "I don't know," and matching language to age.
- Loud failures beat clever fallbacks. A good fallback almost cost us the whole feature by hiding that the real path was broken.
What's next for AI Classroom Simulator for K12 STEM Teachers
- Barge-in and pacing: let students interrupt and let the teacher cut them off naturally, for a more realistic room.
- Bigger, configurable classes and lesson-length rehearsals, not just five students.
- A model-authored, still-evidence-validated X-Ray for richer narrative feedback while keeping the no-hallucination guarantee.
- A library of saved rehearsals so teachers can compare two ways of explaining the same idea and see which one reached more students.
- Curriculum-aligned lesson packs (starting with UK KS1 maths and US NGSS science) so teachers can rehearse the exact lesson they're about to give tomorrow.
Built With
- codex
- gpt-4o-transcribe
- gpt-5.6
- gpt-image-1
- mammoth.js
- next.js
- node.js
- openai-api
- openai-realtime-api
- openai-tts
- pdf.js
- react
- structured-outputs
- typescript
- vitest
- webrtc
- zod
Log in or sign up for Devpost to join the conversation.