Always-Generative Bytes
A build retrospective on the adaptive knowledge graph behind Amal, a kids' Arabic-learning app used by 95,000+ families. • Day 6 fills in the last engine stage: generating the actual lesson from a concept on demand, instead of hand-authoring every lesson in advance.
From a concept to a playable lesson
Day 5 handed us a per-child subject tree whose nodes are still just concept references — "the sound /b/", "count to 5". A child cannot play a concept reference; they need an actual lesson: something to look at, something to answer, something to say out loud. In Amal a single playable lesson is called a byte, and the component that turns a concept into a byte is GraphByteGenerator (which wraps an existing lesson-builder called TCBG, the ConceptByteGenerator).
The defining choice here is in the word generator. Rather than storing a finished, hand-made lesson for every concept, the byte is generated from the concept on demand — assembled at the moment the child is about to play it, from the concept's data and assets. This is the "always-generative bytes" idea, and it is what makes the one-graph model pay off.
The diagram shows the last hop of the engine: a concept goes in, GraphByteGenerator runs, and a playable byte comes out — created at play time, not pulled from a shelf of pre-written lessons.
ONE CONCEPT -> ONE GENERATED BYTE (on demand)
concept: sound /b/
│ GraphByteGenerator
▼
┌───────────────────────────────┐
│ BYTE (a playable lesson) │
│ built now, from the concept │
│ + its assets (Day 2) │
└───────────────────────────────┘A byte is made of bits
A byte is not one screen; it is a short sequence of smaller steps called bits. A bit is a single interaction — show something, ask something, have the child say something. Stringing a few bits together into one byte is what takes a child from "seeing" a concept to "using" it in the space of a minute or two.
The reason to have several bits per byte is pedagogical: really learning a concept means meeting it in more than one way. You see it, you are tested on recognizing it, you produce it yourself. A byte walks the child through that arc in order, and — crucially for the next few days — only some of those bits are scored (they judge a right/wrong answer), while others are just exposure.
The diagram shows the shape of an Arabic byte: an expose bit that simply shows the concept, a scored recognize bit that tests whether the child can pick it out, and a speak bit that has the child produce it. That "only the scored bit judges" detail looks minor now; Day 9 shows it is the hinge the entire adaptivity signal turns on.
ONE BYTE = A SEQUENCE OF BITS
┌────────┐ ┌────────────────────┐ ┌────────┐
│ expose │──►│ recognize (SCORED) │──►│ speak │
└────────┘ └────────────────────┘ └────────┘
show it test recall produce it
only the SCORED bit judges right/wrong; the others build exposureThe bit recipe differs by domain
Different subjects need different practice shapes, so GraphByteGenerator uses a different bit recipe per domain — the ordered list of bit types that make up a byte for that kind of concept. The recipe is a small piece of configuration, not a hand-written lesson, so one recipe generates bytes for every concept in its domain.
Two real recipes from Amal, side by side:
| Domain | Bits per byte | The recipe (in order) |
|---|---|---|
| Arabic | 3 | expose → recognize (scored, e.g. letter_recognize) → speak |
| Math | 4 | fragment → select-sum (scored, e.g. addition_select_sum) → word-build → speak |
Reading the table: an Arabic byte is a three-bit arc (show, scored recognize, speak); a math byte is a four-bit arc (break the problem into a fragment, scored pick-the-sum, build the word for the number, speak it). In both, exactly one bit is the scored one that judges correctness — the rest are exposure and production. Change a recipe once and every byte in that domain changes; that is the leverage of generating instead of authoring.
Key takeaways
- A byte is a single playable lesson; GraphByteGenerator (wrapping the TCBG ConceptByteGenerator) builds it from a concept on demand rather than pulling a pre-authored lesson off a shelf.
- A byte is a short sequence of bits (single interactions) that walk a child from seeing a concept to producing it; only some bits are scored (judge right/wrong) while others build exposure.
- The bit sequence is set by a per-domain recipe — Arabic: expose → scored recognize → speak (3 bits); Math: fragment → scored select-sum → word-build → speak (4 bits) — so one recipe generates bytes for every concept in the domain.
- Generating beats hand-authoring because the marginal cost of a new concept's lesson is ~0, structure stays consistent, practice stays fresh, and it is the join that makes the one-graph model actually reach the child.
- With this stage the engine is complete end-to-end: graph + overlay → frontier → tree → generated byte, with nothing hand-authored per concept.
Checklist
- [ ] I can explain what a byte is and what "generated on demand" means versus a pre-authored lesson.
- [ ] I can explain what a bit is and why a byte strings several bits together.
- [ ] I can give the Arabic and Math recipes and point out which single bit in each is the scored one.
- [ ] I can give at least three reasons to generate bytes instead of hand-authoring lessons.
- [ ] I can trace the full engine pipeline from graph + overlay to a playable byte.