# About
> The history and foundations of LLMs Unplugged, from CS Unplugged to Shannon's information theory.
# About

_LLMs Unplugged_ is a
[Cybernetic Studio](https://cybernetics.anu.edu.au/cybernetic-studio/) project
created by [Dr. Ben Swift](https://benswift.me) at the
[ANU School of Cybernetics](https://cybernetics.anu.edu.au). If you've got
questions, suggestions, or _LLMs Unplugged_ success stories then
[send Ben an email](mailto:ben.swift@anu.edu.au).
These resources build on a rich history of unplugged computing education (and
hands-on education in general). If you're interested in where these ideas came
from---or where to go next---this is the reading list.
## CS Unplugged
For over two decades, [CS Unplugged](https://csunplugged.org) has demonstrated
that core computing concepts can be taught effectively without computers.
Through carefully designed hands-on activities, learners from primary school
through to adult education have explored algorithms, data structures, and
computational thinking. The approach strips away the distractions of syntax and
tooling, allowing learners to focus on underlying principles.
More importantly: it works (the
[literature](https://scholar.google.com/scholar?q=cs%20unplugged) has receipts).
Making learning these concepts both effective and fun is possible, and CS
Unplugged has proven that at scale.
_LLMs Unplugged_ applies this same philosophy to language models. Rather than
explaining transformers through mathematics or implementing neural networks in
code, participants count word patterns in a text, record them as tally marks on
grid paper or physical piles of paper cutouts, then roll dice to generate new
text from those patterns. This hands-on approach makes sophisticated AI concepts
accessible to anyone, regardless of technical background.
## AI Unplugged resources
As machine learning and artificial intelligence became more prominent in public
discourse, educators naturally extended the unplugged approach to these fields,
for example:
- [AI Unplugged](https://www.aiunplugged.org) by Lindner, Seegerer and Romeike
- Northwestern University's
[AI Unplugged Resources](https://sites.northwestern.edu/aiunplugged/)
- [CS In Schools](https://csinschools.io/) by Toan Huynh and Hugh Williams has
some material on AI Unplugged1
These collections cover classification, clustering, computer vision, and
artificial neural network concepts. However, they contain limited material
specifically about language models and especially text generation---a gap that
became particularly acute after ChatGPT's November 2022 release shifted what
"AI" means to most people. _LLMs Unplugged_ aims to fill that gap.

## Historical foundations
The [n-gram language models](https://en.wikipedia.org/wiki/N-gram) participants
build in these workshops have a lineage stretching back over a century. This
isn't new theory---it's well-established mathematics applied by hand.
### Markov's stochastic processes (1913)
Andrey Markov introduced the mathematics of what we now call "Markov chains"
while analysing letter sequences in Pushkin's _Eugene Onegin_. His work
established that language has statistical structure you can quantify through
counting patterns and calculating probabilities. Though Markov's interest was
purely mathematical, his framework for modelling sequences of dependent random
variables became foundational to computational linguistics.
### Shannon's information theory (1948–1951)
Claude Shannon built directly on Markov's foundation, applying his new
information theory to written English. Shannon used n-gram models to measure
entropy and redundancy in language, connecting statistical patterns to
fundamental limits on compression.
Crucially, Shannon was the first to systematically generate synthetic text using
these models---starting with random letters (0-gram), then letter frequencies
(1-gram), then letter pairs (2-gram), and progressively higher orders. This
generative approach revealed how increasing context length produces increasingly
realistic text, a finding that remains central to modern language models.
Here's the thing: Shannon's work was itself "unplugged". He counted transitions
by hand, calculated probabilities manually, and generated synthetic text using
hand-drawn tables and selection based on frequencies. Modern LLMs use the same
fundamental approach but at vastly greater scale and with learned rather than
hand-crafted statistics.
### Connection to modern LLMs
The activities in _LLMs Unplugged_ demonstrate the same operations used in
current language models. The differences are mostly about scale:
- **parameters**: hand-built models have dozens to hundreds versus billions in
modern LLMs, but the core concepts remain identical
- **training**: manual counting versus automated pattern detection, but both
processes learn probability distributions from text
- **generation**: dice rolls versus GPU-accelerated sampling, but both use
weighted randomness to select the next token
- **context windows**: bigrams and trigrams versus 128,000+ token windows, but
longer context always enables better prediction
Modern advances come from doing these same operations at massive scale with
neural networks that learn patterns automatically. But the fundamental
insight---that language structure can be captured through statistical
dependencies and revealed through synthetic generation---comes directly from
Shannon's mid-twentieth-century work and the unplugged methods he used to
explore these ideas.
Which is to say: when you're rolling dice and generating sentences in an _LLMs
Unplugged_ workshop, you're not just learning about modern AI. You're also
participating in a tradition of hands-on exploration that goes back to the
origins of information theory itself.

## About the ANU School of Cybernetics
The [School of Cybernetics](https://cybernetics.anu.edu.au) at the Australian
National University takes a systems-oriented approach to understanding and
shaping technology in society. The School's
[Cybernetic Studio](https://cybernetics.anu.edu.au/cybernetic-studio/) develops
hands-on resources and runs workshops exploring the social, technical, and
political dimensions of emerging technologies.

_LLMs Unplugged_ reflects the School's commitment to making sophisticated
technical concepts accessible to diverse audiences and fostering critical
engagement with AI systems that increasingly mediate how we work, learn, and
communicate. Understanding how these systems actually work---not through
metaphor or handwaving but through direct experience---is what we're all about.
## Acknowledgements
This work has benefited enormously from the input and facilitation help of Eddie
Aloise King and Cole Cooney and other SoCy staff, plus feedback from hundreds of
participants across diverse audiences---school students through to senior
executives in the Australian Public Service. Iterating on these materials with
real learners has been invaluable.
## Get in touch
We encourage educators to use, adapt, and improve these resources. If you have
questions, success stories about using them in your classroom, or would like to
discuss adaptations or improvements you've made, get in touch at
[ben.swift@anu.edu.au](mailto:ben.swift@anu.edu.au)---we'd
love2 to hear from you. And if you'd like to
be informed of more cool stuff coming out of the School of Cybernetics, then
sign up for the
[mailing list](https://cybernetics.anu.edu.au/#subscribe-to-our-mailing-list-1).
## Citation
If you use these materials in your teaching or research, please cite them as:
### APA
> Swift, B. (2025). _LLMs Unplugged: Understand how AI language models work by
> building one yourself_. Zenodo.
> [https://doi.org/10.5281/zenodo.17403824](https://doi.org/10.5281/zenodo.17403824)
### BibTeX
```bibtex
@misc{swift2025llmsunplugged,
author = {Swift, Ben},
title = {{LLMs Unplugged: Understand how AI language models work by building one yourself}},
year = 2025,
publisher = {Zenodo},
doi = {10.5281/zenodo.17403824},
url = {https://doi.org/10.5281/zenodo.17403824}
}
```
---
---
# Workshop blurbs
> Standard descriptions of the LLMs Unplugged workshop at various lengths, for hosts, event organisers, and conference programs.
# Workshop blurbs
Standard descriptions of the _LLMs Unplugged_ workshop at different lengths, for
hosts, event organisers, and conference programs. Pick whichever fits the
space---and if you need something different, or a venue-specific variation,
[get in touch](mailto:ben.swift@anu.edu.au).
## Title
> LLMs Unplugged: A tech-free guide to understanding (and teaching) AI
## One-liner (≈15 words)
> Hands-on workshop that demonstrates how large language models work---no
> computers or coding required.
## One paragraph (≈80 words)
> Build your own language model with pen, paper and dice. In two hours you'll go
> from counting word patterns in a short text to generating new sentences with a
> few rolls of a dice---no screens, no coding, no maths beyond basic counting
> and percentages. You'll walk away with a concrete understanding of how ChatGPT,
> Claude, Gemini and the rest actually work under the hood: the probabilistic
> nature of LLMs, the importance of training data, and how bias and design
> decisions show up in the output.
## Medium (≈150 words)
> Despite the rapid uptake of AI around the globe, most people have no real
> mental model of what's actually happening under the hood of our most popular
> AI tools. Rather than accepting the hand-wave-y and mystical-sounding
> explanations, join us in this fun and informative workshop where you'll learn
> about Large Language Models (LLMs)---the technology behind ChatGPT, Claude,
> Gemini and Copilot---without actually touching any tech.
>
> Through hands-on activities and discussion, you'll learn the basic principles
> and language of LLMs: the probabilistic nature of these models, the importance
> of training data, and the ways that bias and engineered decisions in the
> models may present themselves. No coding background required, and no maths
> beyond basic counting and percentages. Suitable for educators, professionals,
> policymakers, and anyone curious about how AI actually works.
## Long (≈260 words)
> Despite the rapid uptake of AI around the globe (including right here in
> Australia), most people have no real mental model of what's actually happening
> under the hood of our most popular AI tools.
>
> Rather than accepting the hand-wave-y and mystical-sounding explanations, join
> us in this fun and informative workshop where you'll learn about Large
> Language Models (LLMs)---the technology behind the mind-boggling abilities of
> ChatGPT, Claude, Gemini and Copilot---without actually touching any tech.
> Through hands-on activities and discussion, you'll learn the basic principles
> and language of LLMs.
>
> ### Why you should attend
>
> Having a better understanding of how large language models work will help to
> demystify AI and provide a shared understanding and vocabulary for framing AI
> systems. These foundations will help you better understand the probabilistic
> nature of LLMs, the importance of data, and the ways that bias and engineered
> decisions in the models may present themselves.
>
> ### A note for educators
>
> If you're a high school or upper primary teacher and find yourself having
> conversations with your students about AI, this workshop is for you. Our
> activities can be easily replicated in the classroom with readily available
> materials and are supported by a range of open-access online resources. The
> workshop relates to core curriculum outcomes in maths, technologies, HASS and
> literacy and requires zero coding background and no maths beyond basic
> counting and percentages.
---
# FAQ
> Frequently asked questions about using LLMs Unplugged resources, materials needed, and how the activities relate to modern AI.
# Frequently asked questions

## Why do you keep saying LLMs---this is AI, right?
Honestly, the short answer (these days) is yes. The long answer is more
complicated---AI is a term that has been applied to many different algorithmic
techniques and systems over the years. But today (in the mid-2020s) Large
Language Models have kindof sucked all the air out of the room when it comes to
AI, so that's mostly what we're talking about here. I (Ben) do like to use the
term LLM rather than AI whenever I can, because I think it's more specific and
accurate.
## You mention ChatGPT and Claude a lot, but Gemini/DeepSeek/etc. is more my jam
None of these resources are specific to any particular LLM product. We
sometimes use "ChatGPT" or "Claude" as shorthand because they're the names
most people recognise, but the concepts apply equally to any modern LLM.
## Who is this for?
Anyone curious about how language models work. The activities suit learners
from primary school age through to adults, with no technical background
required. We've delivered them to hundreds of participants---primary and high
school students, undergraduate students, and senior executives from industry
and government---and the hands-on approach lands in all of those contexts.
## Did some of this stuff used to be called "My First Language Model"?
Yep, it sure did... and it still is: [My First Language
Model](https://www.llmsunplugged.org/lessons/my-first-language-model/) is the classic LLMs Unplugged lesson.
But this website hosts _all_ the LLMs Unplugged resources---other
[lessons](https://www.llmsunplugged.org/lessons/), the [modules](https://www.llmsunplugged.org/modules/) they're built from, and the
[printable materials](https://www.llmsunplugged.org/tools/)---not just that one workshop.
## Do I need any special materials?
Nope, it's all stuff you'll have around the office/house/classroom. Each lesson
has a "you will need" section.
## Are there any video resources to accompany the lessons?
Not yet, but we're working on it---stay tuned.
## Are there printable versions of the lessons?
Not any more---the lessons are now maintained as web pages only, and they print
reasonably well straight from your browser if you need hard copies. The
printable artefacts for the hands-on activities (pre-generated booklets and
cutout sheets) are on the [tools page](https://www.llmsunplugged.org/tools/).
## Can I use these materials in my school classroom?
Yes. All materials are released under [CC BY-NC-SA
4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/), so you can use,
adapt, and share them for non-commercial educational purposes with attribution.
## Can I use these materials in a paid workshop?
The NC (Non-Commercial) clause in our licence has [some
ambiguity](https://www.artslaw.com.au/information-sheet/creative-commons) around
paid educational activities. Our intention is that educators at schools,
universities, and non-profit organisations can use these materials in workshops
that charge cost-recovery fees (the [lessons](https://www.llmsunplugged.org/lessons/) each come with
suggested session structures and timings). However, for-profit companies cannot
run paid workshops using these materials under the [CC BY-NC-SA
4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) license. If you're a
commercial training provider interested in using these resources, please
[contact us](https://www.llmsunplugged.org/about/#get-in-touch)---we're happy to discuss alternative licensing
arrangements.
## I'm a corporate client, and I'd love to have some experts come and deliver this workshop for us
Good news---that's one of the things we do here at the [School of
Cybernetics](https://cybernetics.anu.edu.au). [Drop us a
line](mailto:lxconvenor.cybernetics@anu.edu.au) to discuss how we can make it
happen.
Honestly, this stuff is just as fun as a Christmas party/team bonding activity,
but the learning is very real. Learning _can_ be fun.
## Why dice and cutouts instead of computers?
Using physical randomness makes the probabilistic nature of text generation
tangible. When you roll dice and look up words in a table, or pick matching
cutouts from a spread on the table, you're doing exactly what a computer
does---just slower. This builds genuine understanding rather than treating AI
as a black box.

## How do these activities relate to ChatGPT, Claude, and other LLMs?
Modern LLMs use the same fundamental principle: predict the next token based on
context. The differences are scale (billions of parameters vs dozens) and learned
vs hand-counted statistics. The core mechanism---weighted random selection based
on patterns in training data---is identical.
## Can I generate my own booklets from custom text?
Yes. You can [generate booklets online](https://www.llmsunplugged.org/tools/) directly in your
browser---no installation required. Just upload or paste your text, choose your
options, and download a PDF. Your text is processed entirely in your browser and
never sent to any server.
If you prefer working offline or want to modify the tools, the [source
code](https://github.com/ANUcybernetics/llms-unplugged) includes a command-line
tool that provides the same functionality.
## Is there a research paper about LLMs Unplugged?
Yes. LLMs Unplugged was presented at the [28th Australasian Computing Education
Conference (ACE 2026)](https://aceconference2026.github.io/) in Melbourne,
Australia. [Download the paper here](https://pdf.llmsunplugged.org/ace2026-llms-unplugged.pdf).
### BibTeX
```bibtex
@inproceedings{swift2026llmsunplugged,
author = {Swift, Ben},
title = {{LLMs Unplugged: Teaching Resources for a ChatGPT World}},
booktitle = {28th Australasian Computing Education Conference (ACE 2026)},
year = 2026,
month = feb,
address = {Melbourne, VIC, Australia},
publisher = {ACM},
doi = {10.1145/3786228.3786237},
url = {https://doi.org/10.1145/3786228.3786237}
}
```
## I found an error in the materials.
Please [open an
issue](https://github.com/ANUcybernetics/llms-unplugged/issues) on GitHub or
[contact us](https://www.llmsunplugged.org/about/#get-in-touch). We appreciate corrections and suggestions.

---
# Build, break, extend
> An extended cutouts workshop. Build paper language models from scratch, combine them, break them (sycophancy), extend them with tools, and finish with a poetry slam.
A half-day deep dive using the paper cutout models. Participants build their
own language models, pool them into bigger ones, deliberately break them
(training in sycophancy), extend them with tools, and put everything together
in a closing poetry slam where each group designs a model to perform its own
generated verse.
We've delivered this lesson once and it worked, but it hasn't had the polish
of the others yet---timings and materials may shift as we road-test it. If
you're thinking of running it, [get in touch](https://www.llmsunplugged.org/about/#get-in-touch) and we'll
share what we've learned.
## Run of show
| Section | Time |
| ---------------------------------- | ------ |
| Icebreaker and intro | 20 min |
| [Training](https://www.llmsunplugged.org/modules/training/) | 20 min |
| [Generation](https://www.llmsunplugged.org/modules/generation/) | 20 min |
| Combining models | 25 min |
| _Break_ | 10 min |
| [Sycophancy](https://www.llmsunplugged.org/modules/sycophancy/) | 20 min |
| [Agentic AI](https://www.llmsunplugged.org/modules/agentic-ai/) | 20 min |
| Poetry slam | 45 min |
Combining models and the poetry slam are deck-only sections (they don't have
standalone module pages yet): combining models pools two groups' cutout
spreads to show what more training data buys you, and the poetry slam has
each group design a model---choosing training data and sampling rules---to
generate and perform a poem.
## You will need
- printed token cutouts for several texts (bigram, `-n 2`)---see the
[Tools](https://www.llmsunplugged.org/tools/#cutouts) page for ready-to-print packs, and the sycophancy
section needs the sycophancy corpus cutouts
- clear table space per group of 2-4, plus room to pool spreads when groups
combine models
- pen and paper per group
- a projector for the slides
---
# How AI writes stories
> A 90-minute primary-school lesson where students discover what AI is, then build their own paper language models and use them to generate stories.
Students start by asking a real AI to write a story about their teacher, then
spend the rest of the lesson finding out how it did it---by building their own
language models out of paper cutouts and generating brand-new stories from the
patterns in their favourite picture books. No computers (except yours, for the
slides), no maths beyond matching colours.
We most recently ran this lesson at [Duffy Primary
School](https://www.llmsunplugged.org/news/2026-06-02-how-ai-writes-stories-at-duffy/) with three year 5-6
classes.
## Lesson plan
Allow five minutes for arrival and settling before part 1. If you're running
over time, part 4 is designed to be dropped---parts 1-3 and 5 are the core of
the lesson.
| Part | What happens | Time |
| ---- | ------------------------------------------------------------------- | ------ |
| 1 | **What is AI?** --- discussion, plus an AI writes the class a story | 15 min |
| 2 | **Training** --- pattern warm-up, key words, then the training game | 20 min |
| 3 | **Generation** --- generate new stories from the trained cutouts | 25 min |
| 4 | **One story, all together** --- whole-class story (optional) | 15 min |
| 5 | **Wrap-up** --- what did we learn? Q&A | 10 min |
**Part 1** opens with think-pair-share ("when you hear _artificial
intelligence_, what comes to mind?"), then the fun bit: the class supplies
three words, and a slide builds a story prompt starring their teacher that you
paste into ChatGPT, Claude, or whichever chatbot you have access to. A
dramatic reading later, you have the hook for the whole lesson: _that was a
language model, and today we're going to build one_.
**Part 2** warms up with predict-the-next-word prompts on the whiteboard
(humans are pattern-spotters too), introduces four key words (AI, language
model, training, training data), then runs the
[Training](https://www.llmsunplugged.org/modules/training/) module in its cutouts flavour: students spread
out printed token cutouts from a picture book and discover the patterns.
**Part 3** runs the [Generation](https://www.llmsunplugged.org/modules/generation/) module: starting from a
single word, students play the colour-matching game to generate new
stories---and read them out loud.
**Part 4** (optional) generates one story as a whole class: everyone hunts for
the current word in their own cutouts, hands go up, and the story grows one
word at a time on butchers paper.
**Part 5** wraps up with discussion questions---would you get the same story
twice? is the model _thinking_?---and open Q&A.
## You will need
- printed token cutouts (bigram, i.e. `-n 2`) from two or three picture
books---the [Tools](https://www.llmsunplugged.org/tools/#cutouts) page has ready-to-print packs for
_Green Eggs and Ham_, _Where Is the Green Sheep?_, and _We're Going on a
Bear Hunt_, or you can [generate your own](https://www.llmsunplugged.org/tools/#generate-your-own)
- a clear table per group of 2-4 students to spread the cutouts on
- pen and paper per group for writing down generated stories
- a whiteboard for the predict-the-next-word warm-up
- butchers paper and a marker for the class story (part 4)
- a projector for the slides, and access to ChatGPT/Claude/etc. for the
story-writing demo in part 1
## Before you deliver
- print the cutouts and (ideally) pre-cut them into strips---scissor time is
the biggest schedule risk with this age group
- have a few predict-the-next-word prompts ready for the whiteboard; ones the
class will finish instantly work best (the school's own values, or "yer a
wizard..." minus the famous last word)
- the story slide in part 1 has fill-in boxes for the teacher's name and the
three class words, and builds a copy-paste-ready prompt---check you can log
in to a chatbot on the room's computer beforehand
- the prompt is tuned for year 5 students in Canberra; if your class is
elsewhere (or another year level), tweak the wording after you paste it
---
# My First Language Model
> The classic LLMs Unplugged workshop. Train a language model on grid paper, then roll dice to generate new text---and see why ChatGPT works the same way. Comes in lengths from 60 minutes to two hours.
This is the original LLMs Unplugged workshop, and still the best place to
start. Participants count word patterns in a real text, record them as tally
marks on grid paper, then roll a d10 to generate brand-new text from those
patterns. Somewhere between the tallying and the dramatic readings, the
penny drops: this is what ChatGPT does, just vastly scaled up.
We've delivered it to school students, undergraduates, teachers, and senior
executives in industry and government. It needs no coding and no maths beyond
counting and percentages.
## Choose your length
One lesson, three lengths. Each length keeps everything from the one before
it and adds a module:
| Length | Modules | Adds |
| ---------- | ------------------------------------------------------------------- | ---------------------------------------------- |
| 60 minutes | [Training](https://www.llmsunplugged.org/modules/training/) + [Generation](https://www.llmsunplugged.org/modules/generation/) | the core train-then-generate loop |
| 90 minutes | + [Pre-trained Model Generation](https://www.llmsunplugged.org/modules/pretrained-generation/) | what happens with a bigger model and more data |
| 2 hours | + [Agentic AI](https://www.llmsunplugged.org/modules/agentic-ai/) | how models use tools to act on the world |
Every length opens with a quick icebreaker and scene-setting (who's used
ChatGPT? how do you think it works?) and closes with a "scaling up"
discussion connecting the paper model to modern LLMs, then Q&A.
## Suggested timing (90-minute version)
- **0:00 kick-off** --- icebreaker, then: today we build our own AI, small
and simple, but using the exact same approach as the big ones
- **0:20 [Training](https://www.llmsunplugged.org/modules/training/)** --- tally word patterns from a text
into the grid
- **0:40 [Generation](https://www.llmsunplugged.org/modules/generation/)** --- roll dice to generate new
text from the grid; share back with dramatic readings
- **1:00 [Pre-trained Model Generation](https://www.llmsunplugged.org/modules/pretrained-generation/)** ---
same dice game, but with a printed booklet trained on a whole book
- **1:20 close** --- scaling up: how does this connect to ChatGPT? how has
this changed how you'll _use_ these tools?
For the 60-minute version, drop the pre-trained booklet section and tighten
the close. For the 2-hour version, add
[Agentic AI](https://www.llmsunplugged.org/modules/agentic-ai/) after the pre-trained section (about 20
minutes) and give every discussion a little more room to breathe.
## You will need
For each pair (or small group) of participants:
- pen or pencil
- a printed [grid template](https://pdf.llmsunplugged.org/worksheets/grid.pdf) (or any grid
paper)
- a d10 die (any die works with a little improvisation)
- some training text: a few pages of a kids' book is ideal, but anything
works
- **90 minutes and up:** a pre-trained model booklet---the
[Tools](https://www.llmsunplugged.org/tools/#booklets-for-dice-generation) page has ready-to-print
booklets for several texts, or you can
[generate your own](https://www.llmsunplugged.org/tools/#generate-your-own)
Plus a projector for the slides.
## Before you deliver
- print the grid templates, and the booklets if you're running 90 minutes or
longer (one per pair; a mix of different texts makes the share-backs more
fun)
- if your group isn't yet comfortable with dice-based weighted sampling, run
the [Weighted Randomness](https://www.llmsunplugged.org/modules/weighted-randomness/) module first as a
warm-up (add about 30 minutes)
- got extra time, or a group that wants more? the
[Sampling](https://www.llmsunplugged.org/modules/sampling/) module makes a great add-on after
generation---it shows how temperature changes the character of the output
without changing the model
---
# Agentic AI
> Turn your model into an agent by teaching it to call external tools when it needs information it doesn't have.
Turn your language model into
an agent by giving it access to external
tools---people, objects, or resources in the room---that it can call when it
needs information beyond what's in the grid.

## You will need
- a completed model from [Training](https://www.llmsunplugged.org/modules/training/)
- pen, paper, and dice as per [Generation](https://www.llmsunplugged.org/modules/generation/)
- people or things to serve as "tools" (see examples below)
## Your goal
Generate text where the model acts as an agent. Stretch goal: design your own
tool and integrate it into your model.
## Key idea
What makes a language model an "agent"? In practice, it comes down to
tool use---a model that can recognise
special tokens triggering external actions, pause generation, call a tool, and
incorporate the result before continuing. That loop of _generate → call tool →
incorporate result → keep generating_ is the core of agentic AI.
## Setting up tools
Before generation, choose a person or object who gets to role-play as the
"tool". Each tool has:
- a **trigger word** that appears in your model's vocabulary
- a **capability** (what it can do)
- a **return format** (what it gives back)
### Example tools
| Trigger word | Tool | Capability | Returns |
| ------------ | ----------------------- | --------------------------------- | ---------------------------- |
| `ACTION` | a chosen person | perform a small physical action | a word for what they did |
| `GOOGLE` | someone with a phone | search the web for a continuation | one word from the top result |
| `FRIEND` | everyone texts a friend | ask them what comes next | first reply wins |
These three cover the main flavours of real-world tool use: `ACTION` reaches
into the room (physical, immediate), `GOOGLE` reaches out to the web
(informational, distant), and `FRIEND` reaches a specific human (escalation).
## Algorithm
1. Add trigger words to your model's vocabulary (new rows and columns).
2. Train or manually add counts so trigger words can appear in generation. Each
tool-trigger cutout ends with a closing token (e.g., `.`) on the same cutout,
so the chain resumes cleanly once the tool returns.
3. During generation, when you sample a trigger word:
- pause generation
- formulate a question or request based on context
- the tool "executes" and returns a result
- write the result down in the output text
- write the closing token from the same cutout and continue generation from
there
This is the agentic loop: your model generates until it hits a trigger, hands
off to a tool, gets a result, and keeps going. Real AI agents do exactly the
same thing---just faster and with more tools.
## Example session
Suppose your model has `ACTION` and `GOOGLE` added as trigger tokens, each
followed by a closing `.` on the same cutout.
1. Start with "We"
2. Sample → "should"
3. Sample → `GOOGLE` (trigger!)
- Pause. Operator googles "what should we do today"
- Picks a word from the top result: "exercise"
- Write down "exercise"
- Write down "." (the closing token on the `GOOGLE` cutout)
4. Sample → "I"
5. Sample → `ACTION` (trigger!)
- Pause. Operator picks a student, who claps
- Write down "clapped"
- Write down "." (the closing token on the `ACTION` cutout)
**Generated text:** "We should exercise. I clapped."
The operator's words ("exercise", "clapped") get written into the output, but
the next cutout picks up from the _closing token_ on the trigger's cutout, not
from the result. This means tools can return literally anything---out-of-vocab
words, phrases, even sounds---without breaking the generation loop.
## Instructor notes
### Designing good tool triggers
For the activity to work well:
- add trigger words to cutouts where they fit contextually (e.g., `GOOGLE` after
"a" or "the", `ACTION` after "we" or "I")
- every trigger cutout closes with a common token like `.` on the same
cutout---this silently bridges the tool's result back into the model's
vocabulary
- the operator's return can be _anything_: an out-of-vocab word, a phrase, even
a noise. Continuation is keyed on the closing token, not the result
- have tool operators ready (and phones charged) before you start generating
### Other tools to try
If you want to extend the activity, design more tools using the same pattern:
- `LOOK` --- a physical object in the room returns a word for what it is
- `NAME` --- the room points at someone, returns their name
- `TIME` --- a clock or watch returns the current time
- `ASK` --- a designated expert returns a short phrase
The shape is always: something outside the model returns a word, the closing
token on the trigger's cutout brings you back.
### Discussion questions
- when should an agent use a tool vs try to answer itself?
- what happens if a tool returns something unexpected?
- how does the model "know" to call a tool? (it doesn't---it just samples the
trigger word)
- what tools would be most useful for different kinds of text?
- could a tool's response change what the agent generates next?
### Classroom variations
**Simple version:** use just one tool (FRIEND) and have the whole class
participate. The model generates until it hits FRIEND, then everyone texts a
friend `What comes next? "[sentence so far]..."`---the first reply wins.
**Advanced version:** set up multiple tools around the room. Different students
operate different tools. The agent doesn't know which tool will be called next.
**Multi-step version:** chain tool calls together---the result of one tool
becomes the context for calling another. This is closer to how real AI agents
plan and execute multi-step tasks.
### Connection to current LLMs
"Agentic AI" has become a buzzword, but in practice it really just means tool
use in a loop. As Simon Willison
[puts it](https://simonwillison.net/2025/Sep/30/designing-agentic-loops/), an
LLM agent is something that "runs tools in
a loop to achieve a goal"---and that's exactly what your model is doing.
Tool use (also called "function
calling") is how modern AI assistants perform actions in the world:
- **the agentic loop**: generate → detect tool call → execute tool → feed result
back → continue generating, exactly like your trigger-word cycle
- **examples**: web search, code execution, API calls, database queries, image
generation
- **structured calls**: modern models output JSON-formatted tool calls (function
name, parameters) rather than just trigger words, but the mechanism is the
same
- **chaining**: real agents chain multiple tool calls to complete complex
tasks---planning, executing, observing results, and adjusting
The key insight: the model doesn't "know" anything the tool returns---it just
learns when to ask. Your classroom tools demonstrate this perfectly: the model
samples GOOGLE not because it knows the answer, but because the training data
included GOOGLE in that context. The actual knowledge comes from outside the
model.
This is why tool-using AI agents can do things like search the web for current
information, run calculations they couldn't do in their head, or control robots
and software. The model's job is to know _when_ to call a tool and _how_ to use
the result---not to contain all knowledge itself.
---
# Generation
> Use your hand-built bigram model to generate new text through weighted random sampling.
This lesson involves rolling dice to sample from weighted probability
distributions. If your students need extra support with this concept, consider
running the [Weighted Randomness](https://www.llmsunplugged.org/modules/weighted-randomness/) lesson first.
Use a pre-trained (hand-built) bigram model to generate new text through
weighted random sampling
.


## You will need
- your completed bigram model from [Training](https://www.llmsunplugged.org/modules/training/)
- a d10 (or similar) for weighted sampling
- pen and paper for jotting down the generated text
For each pair (or group) of students:
- the trained cutouts spread from [Training](https://www.llmsunplugged.org/modules/training/) (already laid
out on a table)
- pen and paper for writing down the generated text
The [Tools](https://www.llmsunplugged.org/tools/#cutouts) page has ready-to-print token cutouts for several
texts if you haven't done the Training lesson yet. Each PDF starts with a
student-facing instructions page that walks groups through the matching game.
## Your goal
Generate new text from your bigram language model. Stretch goal: keep going and
write a whole story.
Generate new text by walking the spread: pick a starting word, find the
cutouts whose previous-word box colour matches, choose one visually, and
repeat using the next word you picked as your new starting point. Stretch
goal: keep going and write a whole story.
## Key idea
A language model proposes several possible next words along with how likely each
is. Dice rolls pick among those options, and repeating the process word by word
yields fluent text.
The chain grows like dominoes: write a word, find a cutout whose previous-word
box matches it, write that cutout's next word, then hunt for the next match.
The spread already encodes the weights---common previous words appear on more
cutouts, and your eye naturally lands on next words that appear more often. So
scanning for matching cutouts and picking one visually _is_ weighted random
sampling---no dice required.
## Algorithm
1. Choose a starting word from the first column of your grid.
2. Look at that word's row to find all possible next words and their counts.
3. Roll dice weighted by the counts (see
[Weighted Randomness](https://www.llmsunplugged.org/modules/weighted-randomness/)).
4. Write down the chosen word and make it your new starting word.
5. Repeat from step 2 until you hit a natural stopping point (e.g., `.`) or your
desired length.
It's a colour-matching game: the colour of the word you just wrote is the
colour of the previous-word box you look for next.
1. **Pick a starting word**---choose any word that appears as a previous word
on at least one cutout
2. **Find candidates**---scan the spread for cutouts whose previous-word box
matches your current word's colour, then verify the word itself matches
before committing (two unrelated words can occasionally share a colour)
3. **Pick one cutout**---visually pick any matching cutout (your eye will tend
to land on cutouts whose next words are common, because there are more of
them---that's weighted sampling for free)
4. **Write down the next word** from the cutout you picked
5. **Put the cutout back** in the spread (this matters: removing it would
change the model's distribution for next time)
6. The word you just wrote becomes your new current word---go back to step 2
7. **Keep going** as long as you like---if no cutouts match your current
word, just pick a new starting word and carry on. Stop when you've
generated enough text
## Example
Before you try generating text yourself, work through this example to see the
algorithm in action.
Using the same bigram model from the example in [Training](https://www.llmsunplugged.org/modules/training/):
- choose (for example) `see` as your starting word
- `see` (row) → `spot` (column); it's the only option, so write down `spot` as
next word
- `spot` → `run` (25%), `jump` (25%) or `,` (50%); roll dice to choose
- let's say dice picks `run`; write it down
- `run` → `.` (67%) or `,` (33%); roll dice to choose
- let's say dice picks `.`; write it down
- `.` → `see` (33%), `run` (33%) or `jump` (33%); roll dice to choose
- let's say dice picks `see`; write it down
- `see` → `spot`; it's the only option, so write down `spot`... and so on
After the above steps, the generated text is _"see spot run. see spot"_
Using the cutouts spread from the example in [Training](https://www.llmsunplugged.org/modules/training/):
- start with `see`---write it down
- scan for cutouts with `see` as the previous word (look for boxes in `see`'s
colour)---both have `spot` as the next word, so pick one and write down `spot`
- scan for `spot` cutouts---4 matches (1 `run`, 1 `jump`, 2 `,`). Pick
visually. Your eye is more likely to land on a comma because there are two
of them, but for variety let's say `run`---write it down
- scan for `run` cutouts---3 matches (2 `.`, 1 `,`). Two-thirds chance of
`.`---let's say `.`---write it down
- scan for `.` cutouts---3 matches (one each of `see`, `run`, `jump`). Let's
say `see`---write it down
- back to scanning for `see` cutouts---both are `spot`, so write down `spot`... and so on
After the above steps, the generated text is _"see spot run. see spot"_
Notice how the randomness comes from your eye landing somewhere on the
spread---you don't need dice. Previous words with more cutouts of the same
next word are more likely to produce that word: both `see` cutouts have
`spot` as the next word, so generation from `see` always produces `spot`.
## Optional extension: pre-grouped piles
If you grouped the cutouts into piles during training (see the Training
lesson's optional extension), generation becomes faster: step 2 is now "find
the pile labelled with my current word" instead of scanning the whole table.
The behaviour and the resulting output distribution are unchanged.
## Instructor notes
### Icebreaker question
Before walking students through the algorithm, ask:
- in as much detail as you can, explain what happens after typing something into the ChatGPT or Claude prompt box to produce the answer you get back
This surfaces students' existing mental model of generation before they
perform it by hand.
### Discussion questions
- how does the starting word affect your generated text?
- why does the text sometimes get stuck in loops?
- if this is a _bigram_ (i.e. 2-gram) model, how would a unigram (1-gram) model
work?
- how could you make generation less repetitive?
- does the generated text capture the style of your training text?
- how does the starting word affect your generated text?
- why might the text sometimes get stuck repeating the same pattern?
- what happens when only one cutout matches your current word?
- why do we leave the cutouts on the table after picking one?
- does the generated text sound like the original training text?
### Troubleshooting
- **"Every row only has one tally mark---there's nothing to roll for."** If the
group didn't get very far in [Training](https://www.llmsunplugged.org/modules/training/) and no row has more
than one tally mark, the generation algorithm won't be very
interesting---there will only ever be one option for the next word and they'll
be stuck on rails. In this case, either encourage them to go back and do a bit
more training, or just have them add some extra tally marks to the grid
wherever they like. This isn't as much like cheating as it might seem---it's
really just an example of using [Synthetic Data](https://www.llmsunplugged.org/modules/synthetic-data/).
- **"I landed on a word that doesn't have its own row."** This can happen if a
word only ever appeared as the _last_ word in the training text---it has a
column (other words lead to it) but no row (it never leads to anything). Just
pick any other word that does have a row and continue from there.
- **"We're stuck in a loop."** With small models it's common to bounce between
two words that only point at each other (e.g. `,` → `spot` → `,` → `spot` →
...). Try picking a different starting word, or just choose any other valid
next word to break out of the cycle.
- **"Every previous word only has one matching cutout---there's nothing
random about this."** If the spread is small and each previous word only
matches a single cutout, generation will feel deterministic. Either go back
and train on more text, or add a few extra cutouts (writing them out by
hand is fine). This isn't really cheating---it's an example of
[Synthetic Data](https://www.llmsunplugged.org/modules/synthetic-data/).
- **"I picked a next word that doesn't appear as a previous word anywhere on
the table."** This can happen if a word only ever appeared as the _last_
word in the training text---it shows up as a next word but never as a
previous one. Just pick a different starting word that does appear on the
spread and continue from there.
- **"We keep going back and forth between the same two words."** With small
spreads it's common to get stuck in a loop where two words keep pointing to
each other. Try starting from a different word, or just pick any other
matching cutout to break the cycle.
### Connection to current LLMs
This generation process is identical to how current LLMs produce text:
- **sequential generation**: both generate one word at a time
- **probabilistic sampling**: both use weighted random selection (exactly like
your dice or cutouts spread)
- **probability distribution**: neural network outputs probabilities for all
50,000+ possible next tokens
- **no planning**: neither looks ahead---just picks the next word
- **variability**: same prompt can produce different outputs due to randomness
The fact: sophisticated AI responses emerge from this simple process repeated
thousands of times. Your paper model demonstrates that language generation is
fundamentally about sampling from learned probability distributions. The
randomness is why LLMs give different responses to the same prompt and why
language models can be creative rather than repetitive. These physical sampling
methods demonstrate the exact mathematical operation happening billions of times
per second inside modern language models.
Note: in AI/ML more broadly, this process of using a trained model to produce
outputs is commonly called "inference"---you may encounter this term in other
contexts. In these teaching resources we use "generation" specifically because
it more clearly describes what language models do: they generate text.
### Comparison to dice method
The cutouts spread and the dice method produce equivalent results:
- dice rolls with weighted probabilities select from options based on counts
- visual selection from the spread selects from options where counts are
represented by multiple physical cutouts
- the spread makes the probability tangible---if three of the cutouts with
`the` as the previous word have `cat` as their next word and one has `dog`,
you'll land on `cat` about 75% of the time, just like weighted dice would
The cutouts method avoids the need to calculate percentages or understand dice
mechanics, making it more accessible for younger learners.
## Interactive widget
Step through the generation process at your own pace. Click on a row to select a
starting word, then press Play or Step to watch the dice roll and text being
generated. You can also edit the training text to create your own model.
Step through the generation process at your own pace. Click on a cutout to
select a starting word, then press Play or Step to watch matching cutouts being
picked and text being generated. You can also edit the training text to create
your own model.
---
# In-context Memory
> Add a short-term memory that nudges generation toward recently-used words, keeping text on topic---a hands-on model of attention and in-context learning.
Give your model a short-term memory. By nudging generation toward words you've
used recently, the text stays on topic---a tabletop version of how real models
pay attention to their own
context.

## You will need
- any model you can already generate from: your [bigram grid](https://www.llmsunplugged.org/modules/training/),
a [cutouts spread](https://www.llmsunplugged.org/modules/generation/), or a
[pre-trained booklet](https://www.llmsunplugged.org/modules/pretrained-generation/)
- pen and paper for your generated text
- dice (or a coin) as per [Generation](https://www.llmsunplugged.org/modules/generation/)
This lesson adds a procedure on top of a model you already have---there's
nothing new to print or build.
## Your goal
Generate text twice from the same model---once plain, once with a short-term
memory---and compare. The memory version should stay on topic for longer.
Stretch goal: find the setting where the memory helps without making the text
repetitive.
## Key idea
A bigram only ever looks at the single word before. It has no idea what the text
has been _about_---mention a dog, and two words later the model has already
forgotten. Real language reuses what came before: once a story is about a dog,
it keeps being about the dog.
We can capture that with a **short-term memory**: a running list of the words
you've written recently. When you pick the next word, you give a small boost to
any candidate that's on that list. Recently-used words become a little more
likely, so topics and characters persist.
The model itself never changes---you're not retraining it. The extra context
lives in the text you've already generated. That's exactly what makes this a
model of in-context learning:
the behaviour shifts based on the context in front of it, with no change to the
underlying model.
## The one rule that matters: reweight, don't override
There's a tempting shortcut: each turn, just grab a recent word from memory and
write it down. **Don't.** That gets stuck on rails fast, for two reasons:
- it ignores the current word, so it can drop in a word that doesn't follow at
all---ungrammatical nonsense
- every word you emit goes back _into_ memory, so emitting "dog" makes "dog"
more likely next turn, which puts another "dog" in memory… and the text
collapses into repeating a handful of words
The fix is to keep the model in charge of _what's allowed_. The memory only ever
adds a boost to words the model **already offers** as possible next words. It
re-ranks the model's candidates; it never invents one.
This "boost what's allowed" rule is how real cache/memory models work: they
_blend_ a recency signal with the base model's distribution rather than
replacing it. Because the base model still gates every choice, you only ever
pick a real continuation, and its variety stops the memory from spiralling into
a loop.
## Algorithm
1. **Start a memory list.** As you generate, keep the last ~8 words you've
written (just underline them in your output, or jot them on a sticky note).
2. **Find the model's candidates** for the next word exactly as you normally
would---the row in your grid, the matching cutouts, or the entry in your
booklet.
3. **Boost the ones in memory.** Any candidate that also appears in your memory
list gets a bonus (see "Applying it to your model" for how, per base).
4. **Pick** from the boosted candidates, **write the word down**, **add it to
memory**, and drop the oldest word so the list stays short.
5. Repeat.
### Worked example
Suppose you're generating and your current word is `the`. Your model offers:
- `cat`: 3
- `dog`: 1
- `sun`: 1
A moment ago the text mentioned a dog, so `dog` is in your memory list. Give it
a bonus of, say, +3:
- `cat`: 3
- `dog`: 1 + 3 = 4
- `sun`: 1
Now roll on the new totals (1-3 → `cat`, 4-7 → `dog`, 8 → `sun`). `dog` has gone
from unlikely to favourite---so the story is more likely to stay about the dog.
Crucially, `cat` and `sun` are still possible: the memory tilted the odds, it
didn't override them.
## Applying it to your model
The boost is the same idea everywhere---it only differs in _how_ you apply it,
because each base stores its probabilities differently.
### On a grid
Add the bonus straight to the counts in the current word's row, then roll on the
new totals (as in the worked example). The grid makes the reweighting visible.
### On a cutouts spread
When you've gathered the cutouts that match your current word, check their next
words against your memory list. For any match, grab one extra copy of that
cutout (write a duplicate) before you pick. More copies means more likely---the
spread does the reweighting for you, no arithmetic.
### On a pre-trained booklet
The booklet's dice thresholds are pre-printed, so you can't re-weight them by
hand. Use the blend form instead:
1. roll a small "memory die" first (e.g. a d10: 1-3 is a hit)
2. on a hit, scan the current entry's options---if one of them is in your memory
list, pick it
3. on a miss, or if no option is in memory, roll the booklet exactly as normal
This keeps the booklet frozen while still tilting toward recent words---and
because you only ever pick from _this entry's_ options, you never leave what the
model allows.
The memory shines on a larger model like the booklet: a rich vocabulary gives it
room to stay on topic without repeating. On a very small hand-built grid, be
gentle with the bonus---boosting recent words can amplify the short loops small
models already fall into (the `,→spot→,→spot` trap from
[Generation](https://www.llmsunplugged.org/modules/generation/)).
## Instructor notes
### Discussion questions
- with the memory on, does the text hold a topic or a character for longer?
- what happens as you turn the bonus up? Where does "on topic" tip over into
"stuck repeating"?
- why does the memory only boost words the model already offers? What goes wrong
if you let it pick _any_ recent word?
- the model never changed---so where did the extra "knowledge" come from?
- how is this different from the [trigram](https://www.llmsunplugged.org/modules/more-context/), which also
uses more than one word?
### Connection to current LLMs
This is a hands-on model of two of the most important things modern LLMs do.
**Attention over the whole context.** A bigram looks back one word; the memory
looks back over everything you've generated and lets it influence the next
choice. That's the heart of the
attention mechanism: when
predicting the next word, the model reaches back across the whole context and
weights what it finds. Your memory is a crude, fixed version (boost recent
words); attention is learned and content-sensitive.
**In-context learning.** Notice that the model never retrained---the behaviour
changed purely because of what was already in the text. This is why you can give
an LLM a few examples or a topic in your prompt and it picks up the pattern with
no change to its weights. The "learning" happens in the context, not the model.
**Repetition is a real failure mode.** The "stuck on rails" trap you avoided is
not hypothetical: real models can loop too, which is why generation settings
include repetition penalties---a deliberate _down_-weighting of recent words,
the exact opposite tuning of the boost you just added. Topic-stickiness and
repetition are two ends of the same dial.
---
# Induction Heads
> Add a rule that completes patterns from the text itself---find the last time the current word appeared and copy what followed it---the circuit behind in-context learning.
Teach your model to finish a pattern it has only just seen. By looking back
through the text for the last time the current word appeared and copying what
came next, the model can complete sequences it never trained on---the same trick
that lets a real LLM follow a pattern you put in its prompt.

## You will need
- any model you can already generate from: your [bigram grid](https://www.llmsunplugged.org/modules/training/),
a [cutouts spread](https://www.llmsunplugged.org/modules/generation/), or a
[pre-trained booklet](https://www.llmsunplugged.org/modules/pretrained-generation/)
- pen and paper for your generated text (you'll be reading back over it, so keep
it tidy)
- dice as per [Generation](https://www.llmsunplugged.org/modules/generation/)
Like [In-context Memory](https://www.llmsunplugged.org/modules/in-context-memory/), this is a procedure laid
over a model you already have. Nothing new to print.
## Your goal
Make the model complete a made-up pattern that it could not possibly have
learned during training---purely from a pattern you write into the text first.
Stretch goal: match on the last _two_ words instead of one and see the
completion get sharper.
## Key idea
The [In-context Memory](https://www.llmsunplugged.org/modules/in-context-memory/) lesson boosted _recently
used_ words. Induction is the sharper version: instead of "what have I seen
recently?", it asks **"the last time I was at this exact word, what came next?"**
So when the current word is `cat`, you scan back through what you've already
written to the most recent earlier `cat`, read the word that followed it, and
treat that as a strong suggestion for the next word. In effect you're building a
bigram out of the text in front
of you, on the fly---and using it to finish patterns the base model has never
seen.
## Algorithm
1. Look at your **current word**.
2. **Scan back** up your written output to the most recent earlier time that
same word appeared.
3. If you find one, the word that **followed** it is your _induction
candidate_---a strong suggestion for what comes next.
4. **Combine with the base model:** strongly prefer the induction candidate, but
keep some chance of consulting the model normally (roll a die: mostly copy,
occasionally generate). If there's no earlier occurrence, there's no
candidate---just generate from the base model as usual.
5. Write the word down and repeat.
If you _always_ copy the induction candidate, the model just replays whatever
pattern it's in---its own kind of being stuck on rails. Keeping a chance of
falling back to the base model lets it break out and start new patterns. As with
the memory lesson: blend, don't override.
## The pattern-completion demo
This is where it earns its keep. Seed your output with a short made-up sequence,
repeated, using words your model never saw together---then let induction take
over.
Write down: `moon` `five` `apple` `moon` `five` `apple` `moon` `five`
Now generate the next word. Your current word is `five`:
1. scan back for the last `five`---it was followed by `apple`
2. copy `apple`
You've completed the pattern---`moon five apple`---even though "moon five apple"
appears nowhere in the training text and the base model has no idea about it. Run
it again from `apple` and you'll get `moon`, then `five`, then `apple`… the model
has picked up your invented rule from a single example, with no retraining at
all.
Turn induction off (generate from the base model alone) and the pattern
evaporates---the model reverts to its trained habits and can't continue your
sequence. That contrast _is_ the lesson.
## Applying it to your model
The induction step is the same on every base, because it reads your _written
output_, not the model: scan back, find the last occurrence of the current word,
copy what followed. Only the fall-back differs:
- **grid:** when there's no in-context match (or your die says "generate"), roll
on the current word's row as usual
- **cutouts:** fall back to picking from the matching cutouts in the spread
- **booklet:** fall back to the booklet's lookup-and-roll
Because the lookup happens on your pad, induction needs no special materials and
works identically whichever base you started from.
## Instructor notes
### Discussion questions
- the model completed a sequence it never trained on. Where was that "knowledge"
stored?
- why does the demo use made-up or random words rather than ordinary sentences?
- what happens if you only ever copy, and never fall back to the base model?
- how is induction different from the [recency memory](https://www.llmsunplugged.org/modules/in-context-memory/)?
When would each one help?
- (stretch) if you match on the last _two_ words instead of one, why is the
completion more reliable?
### Connection to current LLMs
Induction heads are a real, identified circuit inside transformers---and they
turn out to be one of the main mechanisms behind
in-context learning, the
ability to pick up a pattern from the prompt without any change to the model's
weights.
- **the rule is the same**: a transformer's induction head finds an earlier
place where the current token appeared and copies what came after it---exactly
your scan-back-and-copy procedure
- **it's how few-shot prompting works**: give an LLM a few "input → output"
examples and it continues the pattern, because induction-style circuits match
your current position against the examples above
- **how it's measured**: researchers detect these circuits by feeding the model
a random sequence repeated twice and checking that it predicts the second copy
far better than the first---the machine version of your `moon five apple` demo
Your version is exact-match and hard (the word matches or it doesn't); real
induction heads match softer, richer patterns and blend smoothly with everything
else the model knows. But the behaviour---_find where this happened before, do
what came next_---is the same idea you can run by hand.
---
# LoRA
> Add a lightweight adaptation layer to retarget a trained model without retraining everything.
Efficiently adapt a trained language model to a new domain or style without
retraining the whole thing.

## You will need
- a completed bigram model from an earlier lesson (your base model)
- pen or pencil, and a printed
[grid template](https://pdf.llmsunplugged.org/worksheets/grid.pdf) (or any grid paper)
- new domain- or style-specific text
## Your goal
Create a lightweight adaptation layer that shifts your base model toward a new
domain. Stretch goal: experiment with mixing ratios between base and LoRA
layers.
## Key idea
Low-Rank Adaptation (LoRA) stores only
the _changes_ from the base model, so it can be much smaller. During generation
you add LoRA counts to the base counts (optionally scaled) and sample as normal.
## Algorithm
1. Choose an existing bigram grid as your base model.
2. Train a LoRA grid:
- Start with a new grid using the same columns as the base.
- Run [Training](https://www.llmsunplugged.org/modules/training/) (grid method) on your new domain text,
but only keep rows for words that appear in that text.
3. Apply the adaptation:
- When sampling, add the LoRA counts to the base counts for the current word
(if that row exists).
- Optionally scale the LoRA counts up or down to control how strongly the
adaptation influences the output.
## Example
- Base model (general text) has a `saw` row with counts toward `they`, `the`,
`a`, `red`.
- LoRA trained on "I saw a red cat. I saw the red dog." adds only a `saw` row
with extra counts toward `the`, `a`, `red`.
- Combined sampling uses base + LoRA counts, making `red` more likely after
`saw` while leaving other rows unchanged.
## Instructor notes
### Discussion questions
- how much training data do you need for the LoRA layer compared to training
from scratch?
- what happens if you scale the LoRA values by 2 or 0.5 before adding them?
- can you create multiple LoRA layers for different domains?
- which words change most between base and adapted models?
- when would you want a separate LoRA layer vs retraining the whole model?
### Connection to current LLMs
Low-Rank Adaptation revolutionised how modern LLMs are customised:
- **efficiency**: training a LoRA layer requires 100-1000x less computation than
full fine-tuning
- **modularity**: you can have one base model plus many LoRA layers for
different tasks (medical, legal, creative writing)
- **preservation**: the base model stays unchanged, so it retains its general
capabilities
- **combination**: multiple LoRA layers can be combined or switched on-the-fly
- **distribution**: LoRA layers are small (megabytes vs gigabytes), making them
easy to share
The key insight: most model adaptation happens in a small subspace of all
possible changes. Instead of adjusting billions of parameters, LoRA identifies
and modifies only the dimensions that matter for the new domain. Your paper
implementation makes this concrete: rather than recreating the entire grid, you
only track the changes needed for the new text style. When you add the base and
LoRA counts together, you're doing exactly what neural networks do when they
apply LoRA layers during inference. This is why organisations can maintain one
large foundation model and create thousands of specialised versions through
lightweight LoRA layers.
---
# More Context
> Extend the bigram model to two words of context with a trigram, see why that gets expensive, then add cheap extra context with a skip grid.
Extend the bigram model to use more than one word of context. First the
trigram---two words, considered together---then a cheaper trick, the _skip
grid_, that pulls in an earlier word without the trigram's cost.

## You will need
- the same materials as [Training](https://www.llmsunplugged.org/modules/training/)
- extra paper for a three-column table (trigram) and a second grid (skip grid)
- pen, paper, and dice as per [Generation](https://www.llmsunplugged.org/modules/generation/)
For each pair (or group) of students:
- printed trigram token cutouts (each one shows two previous words as
coloured boxes followed by a single next word, all colour-coded by word)
- a clear table or flat surface to spread the cutouts out on
- scissors
The [Tools](https://www.llmsunplugged.org/tools/#cutouts) page has ready-to-print trigram token cutouts, or
you can [generate your own](https://www.llmsunplugged.org/tools/#generate-your-own) from any text. Each PDF
starts with a student-facing instructions page (anatomy of a cutout, worked
example, tips), so you can hand the printed pack straight to a group. The CLI
also supports a `--duplex` flag that prints the same cards on both faces, so
students never have to flip a face-down card.
## Your goal
Build a trigram language model, watch it run into a wall, then build a _skip
grid_ that recovers some of the benefit for far less cost. Stretch goal: train
on more data, or invent your own way of mixing in earlier context.
## Key idea
A bigram only knows the word immediately before. The obvious fix is to look back
further---and the obvious way to do that, the trigram, works but gets expensive
fast. So this lesson has an arc: **more context helps (trigram) → but the full
version blows up → so here's a cheaper way to get some of it (skip grid)**. That
last move---pulling in earlier context without paying the full cost---is the
same problem modern models solve with attention.
## Part 1: the trigram
Instead of asking "what follows this word?", we ask "what follows these _two_
words?". The two previous words are considered _together_, as a pair.
### Training
1. Draw a four-column table: `word1 | word2 | word3 | count`.
2. Slide a window over your text, collecting every overlapping triple of words.
3. For each triple, increment its count (or add a new row starting at 1).
After the full text (`see` `spot` `run` `.` `see` `spot` `jump` `.`) the model
is:
| word 1 | word 2 | word 3 | count |
| ------ | ------ | ------ | ----- |
| `see` | `spot` | `run` | 1 |
| `spot` | `run` | `.` | 1 |
| `run` | `.` | `see` | 1 |
| `.` | `see` | `spot` | 1 |
| `see` | `spot` | `jump` | 1 |
| `spot` | `jump` | `.` | 1 |
The order of the rows doesn't matter, so you can group them by _word 1_ if that
helps.
1. **Cut out the trigram tokens** from your printed sheets
- each cutout shows two previous words as coloured boxes, followed by the
next word; every word has its own colour, so the boxed and free-standing
forms of the same word match
2. **Spread the cutouts out** on a table, face up, no overlap if you can manage
it---that's your trained trigram model
Original text: _"See Spot run. See Spot jump."_ contains these (two previous
words → next word) triples:
- `see spot → run`
- `spot run → .`
- `run . → see`
- `. see → spot`
- `see spot → jump`
- `spot jump → .`
Each triple becomes one cutout on your table:
Notice that `see spot` shows up twice, once with `run` and once with `jump`.
Compared to the bigram spread (which would just have two `see→spot` cutouts),
the trigram spread captures more specific patterns about which word follows
which _pair_ of words.
### Generation
1. Pick any row and write down `word1` and `word2` as your starting words.
2. Find all rows where `word1` and `word2` match your current context; note
their counts.
3. Roll weighted by those counts to pick a row; take its `word3` as the next
word.
4. Shift the window by one word (new context is old `word2` + chosen `word3`)
and repeat from step 2.
1. **Pick two starting words** that appear together as previous words on at
least one cutout, and write both down
2. **Find candidates**---scan for cutouts whose two previous-word boxes match
your last two words (match the rightmost box to your most recent word, then
check the box to its left). Verify the words, not just the colours
3. **Pick one cutout** visually, **write down its next word**, and **put the
cutout back**
4. Your last two words are now the previous-rightmost word plus the word you
just wrote---go back to step 2
## The catch: the spread explodes (and the model just parrots)
Try generating from the example above and watch what happens. From `see spot`
you can branch to `run` or `jump`---but after that, every two-word context has
exactly _one_ matching row. `spot run` only ever leads to `.`; `run .` only ever
leads to `see`. So the model has no real choice to make: it replays the training
text almost verbatim.
That isn't a bug in the example---it's what trigrams do at this scale. Each extra
word of context multiplies the number of possible contexts, so with a small
amount of text almost every two-word context is seen exactly once. The model
becomes a tape player with the occasional fork.
- a bigram of this text needs a row per _word_ (a handful)
- the trigram needs a row per _word pair_---many more, and most with a count of
just 1
- the bigram spread has one pile per _previous word_ (a handful)
- the trigram spread has one pile per _pair_ of previous words---many more, and
most piles holding a single cutout
This is the central trade-off of n-grams: **more context sharpens predictions,
but you need exponentially more data to fill in all those contexts.** Push to
four or five words and you'd need a library to see each context even once. So
rather than keep extending the window, we look for a cheaper way to bring in
earlier words.
## Part 2: a cheaper way---the skip grid
Here's the trick. The trigram is expensive because it tracks the two previous
words _jointly_---one table indexed by the whole pair. What if we tracked them
_separately_ and added the evidence together?
You keep two bigram-sized grids:
- the **previous-word grid**: your ordinary bigram (the word one back → the next
word)
- the **skip grid**: the same shape, but for the word _two_ back (the word two
back → the next word)
Two single-word grids cost far less than one word-pair table: each has a row per
_word_, not per _pair_. That's the whole point---you reach back two words without
the combinatorial blow-up.
A trigram table can have up to (vocabulary size)² rows---one per possible word
pair. The two skip-grid tables have at most (vocabulary size) rows _each_. You
trade the ability to track exact pairs for two cheap tables you can actually
fill in.
### Training the skip grid
For every triple `word1 word2 word3` in your text:
1. tally `word2 → word3` in the **previous-word grid** (this is just your normal
bigram)
2. tally `word1 → word3` in the **skip grid**
That's it---two tally marks per triple, each in a plain two-word grid.
#### Example
Text: `the cat sat . the dog ran .`
The **previous-word grid** (word one back → next) gets the usual bigram counts:
`the→cat`, `cat→sat`, `the→dog`, `dog→ran`, and so on.
The **skip grid** (word two back → next) records what tends to appear two words
after each word:
| two back | next | count |
| -------- | ----- | ----- |
| `the` | `sat` | 1 |
| `the` | `ran` | 1 |
| `cat` | `.` | 1 |
| `dog` | `.` | 1 |
Notice the skip grid has learnt that `the` is often followed---two words
later---by a verb (`sat` or `ran`), regardless of which animal came in between.
On the table, the skip idea is most natural to _read_ in the grid method (toggle
to it above), but here's how it maps to cutouts if you want to try it:
- keep your ordinary bigram spread (previous word → next word)
- lay out a second spread keyed on the word _two_ back → next word (you'll need
to write these out by hand, or generate them---the standard packs only print
the previous-word spread)
Two spreads, each the size of an ordinary bigram spread, rather than one much
larger trigram spread.
### Generating with the skip grid
To pick the word after a two-word context `word1 word2`:
1. read `word2`'s row in the **previous-word grid**
2. read `word1`'s row in the **skip grid**
3. **add the two rows together**, cell by cell, to get combined counts
4. roll weighted by the combined counts, write the word down, shift the window,
and repeat
#### Example
Continuing the text above, suppose your context is `the cat` and you want the
next word.
- previous-word grid, `cat`'s row: `sat` 1
- skip grid, `the`'s row: `sat` 1, `ran` 1
- combined: `sat` 2, `ran` 1
Roll on those four (1-2 → `sat`, 3 → `ran`). The plain bigram would have forced
`sat` every time; the skip grid lets `the cat` sometimes go to `ran`---a verb
that followed `the …` elsewhere in the text. The model has generalised beyond
the exact pairs it saw, and it stays genuinely random instead of parroting.
To pick the word after a two-word context `word1 word2`:
1. gather the cutouts whose previous word matches `word2` (from the bigram
spread)
2. gather the cutouts whose two-back word matches `word1` (from the skip spread)
3. pool them into one heap and pick visually
Because you're picking from the combined heap, words with more cutouts across
the two spreads are more likely---the spread is doing the addition for you, just
as it did the weighting in [Generation](https://www.llmsunplugged.org/modules/generation/).
## What the skip grid can't do
The skip grid is cheaper than the trigram, but it's also weaker, and the
difference is worth naming. It treats the two earlier positions as if they
contribute _independently_: it adds "what follows `cat`" to "what tends to come
two words after `the`". It can never capture the cases where it's the _pair_
that matters---where `new york` predicts something that neither `new` alone nor
`york` alone would.
That gap is exactly the problem modern models solve with the
attention mechanism. The
skip grid mixes in earlier context with _fixed_ weights (always the word two
back, always added in the same way). Attention _learns_ which earlier words
matter for each prediction, and how much---so it can decide, on the fly, when
the combination matters and when it doesn't.
## Instructor notes
### Discussion questions
- how does the trigram output compare to the basic (bigram) model output?
- why does the trigram spread/table tend to have so many single-count entries?
- what's the trade-off between context length and data requirements?
- the skip grid lets `the cat` sometimes continue like `the dog` did. When is
that helpful? When might it produce nonsense?
- can you think of a two-word phrase where the _pair_ matters more than either
word on its own? (this is what the skip grid misses)
### Connection to current LLMs
This lesson bridges simple word-pair models and modern transformers along two
threads.
The trigram shows the **context-length trade-off**: longer context sharpens
predictions, but the number of possible contexts---and the data you need to
cover them---grows exponentially. Current models use context windows of hundreds
of thousands of tokens, which is only possible because they don't store an
explicit count for every possible context the way an n-gram table does.
The skip grid shows the first step _beyond_ counting exact contexts: mixing in
earlier positions with fixed weights. Real models generalise this into
attention---instead of
"always add the word two back", the model _learns_ which previous words to pull
in for each prediction. Your hand-built skip grid is fixed and additive;
attention is learned, weighted, and dynamic. Both share the core insight: you
don't have to see the _exact_ context before to make a good guess.
---
# Pre-trained Model Generation
> Use a provided pre-trained booklet to generate text without training your own model.
Use a (slightly larger) pre-trained model booklet to generate new text through
weighted random sampling.

## You will need
- a pre-trained model booklet
- a d10 for weighted sampling
- pen and paper for your generated text
The [Tools](https://www.llmsunplugged.org/tools/#booklets-for-dice-generation) page has ready-to-print
booklets for several texts, or you can
[generate your own](https://www.llmsunplugged.org/tools/#generate-your-own) from any text.
## Your goal
Generate text from a pre-trained language model without training it yourself.
Stretch goal: try to guess the training text before checking the booklet title.
## Key idea
Pre-trained models capture patterns from larger datasets. You can use them just
like your hand-built bigram model: look up the current word, roll dice, choose
the next word, and repeat.
## Algorithm (quick recap)
1. Choose a starting word---any bold word in the booklet---and write it down.
2. Look up that word's entry to see possible next words and their thresholds.
3. Roll your d10(s):
- If there's an indicator (e.g., a small box with `2`), roll that many d10s
and treat the digits as one number.
- Otherwise, roll one d10.
4. Scan down the options; the first threshold greater than or equal to your roll
gives the next word. Write it down.
5. Repeat from step 2 using the new word until you reach a natural stopping
point or your desired length.
## Example
Before you try generating text yourself with a booklet, work through these
examples to see the algorithm in action.
- **Single d10:** Current word `cat` with options `4|sat`, `7|ran`, `10|slept`.
Roll once; a 6 lands you on `ran`.
- **Multiple d10s:** Current word `the` with a `2` indicator and options
`33|cat`, `66|dog`, `99|end`. Roll twice; a 5 and 8 combine to 58, so you
choose `dog`.
## Instructor notes
### Discussion questions
- can you guess what text the model was trained on from the generated output?
- how does using a pre-trained model differ from training your own?
- what vocabulary size does the booklet model have compared to your hand-built
model?
- why might some word combinations feel more natural than others?
- without looking at the title: can you identify the training text's genre or
style?
### Troubleshooting
- **"Which die is the tens digit?"** When rolling multiple d10s (i.e. in the
"multiple diamond" case), it doesn't really matter which die you read
first---as long as you decide before you roll and stay consistent. One easy
convention: use different-coloured dice and always read them in the same order
(e.g. red first, then blue). But really, don't stress too much about it. The
activity will still work fine if you mix them up.
### Connection to current LLMs
This lesson demonstrates the foundation of how people interact with modern AI:
- **pre-training**: companies train massive models on huge text corpora (like
your booklet model, but with trillions of words)
- **LLM-as-a-service**: users generate text without seeing or modifying the
underlying model (just like using the booklet)
- **model distribution**: the booklet format shows how models can be packaged
and shared---current LLMs are distributed as parameter files
- **deterministic generation**: given the same starting word and dice rolls, you
get the same output (though randomness creates variety between runs)
The key insight: training and text generation are separate processes. Most AI
users never train models---they use pre-trained ones through APIs or interfaces.
Your hand-built model from [Training](https://www.llmsunplugged.org/modules/training/) gives you insight into
what's inside the booklet, but you don't need that knowledge to generate text.
This separation is why companies like OpenAI can provide AI services: they do
the expensive training once, then millions of users perform text generation. The
booklet captures thousands of training examples in a portable format, just as
neural networks compress training data into billions of parameters.
## Interactive widget
Step through the booklet lookup process at your own pace. The model is displayed
in the same format as the printed booklets: each entry shows a bold previous
word, diamond symbols indicating how many d10s to roll, and the possible next
words with their thresholds.
---
# RLHF
> Use human preferences to adjust your model's weights, making it generate text people prefer.
Adjust your language model based on human preferences, reinforcing outputs
people like and discouraging ones they don't.

## You will need
- a completed model from an earlier lesson
- pen, paper, and dice as per [Generation](https://www.llmsunplugged.org/modules/generation/) (grid method)
- a group of people to provide preferences (the "humans" in RLHF)
## Your goal
Generate multiple candidate outputs, collect human preferences, and update your
model's counts accordingly. Stretch goal: run multiple rounds of feedback and
observe how the model changes.
## Key idea
Reinforcement Learning from Human Feedback (RLHF)
adjusts model probabilities based on what people prefer. Instead of training on
more text, you train on human judgements about which outputs are better.
## Algorithm
### Phase 1: generate candidates
1. Choose a starting word.
2. Generate 2--3 different completions (5--10 words each) by running generation
multiple times from the same starting point.
3. Write each candidate on a separate piece of paper.
### Phase 2: collect preferences
1. Show all candidates to your human judges (the class, a small group, or
individuals).
2. Have them vote on which completion they prefer.
3. Record the ranking: best, middle, worst.
### Phase 3: update the model
For each word transition in the **preferred** output:
- add +1 to that cell in your grid
For each word transition in the **rejected** output:
- subtract 1 from that cell (minimum 0)
Middle-ranked outputs: no change (or +0.5/−0.5 if you want finer adjustments).
### Phase 4: generate again
Use the updated model to generate new text. The adjustments should make
preferred patterns more likely.
## Example
**Starting word:** "the"
**Candidate A:** "the cat sat on the mat."
**Candidate B:** "the dog ran to the park."
**Candidate C:** "the the the the the the."
**Human preference:** B > A > C
**Updates:**
- B's transitions get +1 each: (the→dog), (dog→ran), (ran→to), (to→the),
(the→park), (park→.)
- C's transitions get −1 each: (the→the) loses 5 counts
- A stays unchanged (middle rank)
After updates, "the→dog" and "the→park" become more likely, while "the→the"
becomes much less likely.
## Running multiple rounds
For deeper learning, repeat the process:
1. Generate new candidates from the updated model
2. Collect fresh preferences
3. Update again
4. Observe how the model's behaviour shifts
After several rounds, the model should consistently produce outputs more aligned
with human preferences.
## Instructor notes
### Discussion questions
- what makes one output "better" than another? can people agree?
- what happens if different people prefer different things?
- how many rounds of feedback does it take to noticeably change the model?
- could you "break" the model with bad feedback?
- what biases might creep in through human preferences?
- is the model learning to be "good" or learning to match what judges prefer?
### Classroom variations
**Simple version:** just pick best vs worst (ignore middle). Easier to run, same
core concept.
**Split judges:** divide the class into groups with different preferences (e.g.,
"team poetry" vs "team clarity"). Train separate models and compare results.
**Blind feedback:** judges don't know which outputs came from which version of
the model. Reduces bias toward "improvement."
**Adversarial feedback:** one judge deliberately gives bad feedback. How robust
is the process?
### Connection to current LLMs
RLHF is how modern AI assistants learn to be helpful, harmless, and honest:
- **Claude, ChatGPT, and others**: all use RLHF to align model outputs with human values
- **the process**: human raters compare model outputs and rank them, exactly
like your classroom judges
- **reward models**: at scale, a separate AI learns to predict human
preferences, then guides the main model
- **safety**: RLHF teaches models to refuse harmful requests by having humans
prefer refusals over compliance
- **instruction following**: models learn to actually answer questions (rather
than just predict text) through RLHF
The key insight: RLHF shifts what "good" means from "matches training data" to
"matches human preferences." Your grid updates demonstrate this
directly---you're changing probabilities not based on what appeared in text, but
based on what people preferred. This is why RLHF-trained models can be more
helpful than models trained only on internet text: they've learned to optimise
for human approval, not just pattern matching.
The limitation is also visible: RLHF captures the preferences of whoever
provides feedback. Different judges produce different models. This is why AI
companies carefully select and train their human raters---the model will learn
whatever biases and preferences those humans have.
---
# Sampling
> Same model, different output---experiment with temperature and truncation strategies to shape how your model picks the next word.
When generating text, your model offers several options for the next word.
Sampling strategies decide which one to pick---and the strategy you choose can
change the character of the output dramatically, without changing the
underlying model at all. The same grid or cutouts spread can produce flat prose,
structured poetry, or pure nonsense, depending entirely on how you sample.

## You will need
- a completed model from an earlier lesson
- pen, paper, and dice as per [Generation](https://www.llmsunplugged.org/modules/generation/) (grid method)
## Your goal
Generate text using at least two temperatures and at least two truncation
strategies. Stretch goal: design and test your own truncation rule.
## Key idea
Sampling choices---temperature and truncation---can make the same model sound
cautious, wild, repetitive, or inventive. Tweaking the sampler changes the
output without retraining anything.
## Temperature control
Temperature is a number that smooths the distribution. Higher temperatures
flatten differences between options, making surprising words more likely.
- Algorithm: when sampling the next word, divide all counts by the temperature
(round down, minimum 1) before rolling dice.
- Example with counts `spot` (4), `run` (2), `jump` (1), `.` (1)
- Temp 1 → use counts as-is (`spot ` twice as likely as `run`; four times
`jump` or `.`).
- Temp 2 → counts become 2, 1, 1, 1 (`spot` still highest, but less dominant).
- Temp 4 → counts become 1, 1, 1, 1 (all options equal).
## Truncation strategies
Truncation narrows which next-word options are allowed. Mix and match with
temperature.
When using a [pre-trained booklet](https://www.llmsunplugged.org/modules/pretrained-generation/), the next-word
candidates are already sorted from most likely to least likely. This makes
several strategies easier: greedy = pick the first option, non-sequitur = pick
the last option, and top-k = only roll among the first k options.
### Greedy
Pick the highest count; if tied, roll among the top options.
### Haiku
Track syllables per line (5-7-5). Roll as normal; if the word would overflow the
line's syllable limit, re-roll.
### Non-sequitur
Pick the lowest non-zero count; if tied, roll among the least likely options.
### No-repeat
Track words used in the current sentence. If you roll a repeat, reroll; if
nothing valid remains, insert `.` and continue.
### Alliteration
Prefer options that start with the same letter/sound as the previous word;
otherwise sample normally.
### Top-k
Choose a number k (e.g. 2 or 3). Keep only the k options with the highest
counts; if tied for the last spot, include all ties. Roll among those only.
### Alphabet chain
The next word must start with the last letter of the previous word. If no option
qualifies, sample normally.
### Short/long
Pick a length threshold (e.g. 4 letters). Only allow words at or below that
length (short mode) or above it (long mode). If nothing qualifies, re-roll.
## Instructor notes
### Discussion questions
- which strategy produces the most "human-like" text?
- when would you want predictable vs surprising output?
- how do constraints (haiku, no-repeat) spark creativity?
- can you invent your own sampling strategy?
### Troubleshooting
- **"I divided all the counts by the temperature and now everything is 1."**
This is correct---it's not a mistake. High temperature flattens the
distribution so that all options become equally likely. That's the whole
point: higher temperature means more randomness.
### Connection to current LLMs
Current LLMs use these same mechanisms, though the specific strategies differ.
- **Temperature control:** the temperature parameter divides probabilities just
like you divide tallies; higher temperature means more random output. The
lesson uses manual temperature adjustment, while LLMs do this computationally
before every token.
- **Truncation techniques in modern LLMs:** top-k sampling (only consider k most
likely tokens), top-p/nucleus sampling (consider tokens until cumulative
probability reaches p), repetition penalties, frequency penalties, and
presence penalties all prune options before sampling.
- **Truncation techniques in this lesson:** greedy, haiku, non-sequitur,
no-repeat, alliteration, top-k, alphabet chain, and short/long are designed
for dice-based sampling but embody the same idea---changing which tokens are
eligible before you roll. Top-k directly mirrors the top-k parameter in LLM
APIs.
Your paper model demonstrates that "creativity" in AI comes from two controls:
adjusting temperature (probability distribution shape) and applying truncation
strategies (which tokens to exclude). The same trained model can produce
scholarly essays (low temperature, strict truncation) or wild poetry (high
temperature, constraint-based truncation) just by changing these parameters. The
key insight: generation control is as important as training data. Creative
output comes not from the model itself, but from how you control temperature and
which tokens you truncate from consideration.
---
# Sycophancy
> Skew your model toward over-agreeable, flattering responses by piling in sycophantic training data.
Demonstrate how adding repetitive sycophantic phrases to your training data
steers the model toward over-agreeable, flattering output---no RLHF
required.

## You will need
- your completed grid model from [Training](https://www.llmsunplugged.org/modules/training/)
- a d10 (or similar), plus pen and paper, as per
[Generation](https://www.llmsunplugged.org/modules/generation/)
- the sycophancy phrases listed below, to tally into your grid
- a trained bigram cutouts spread from [Training](https://www.llmsunplugged.org/modules/training/)
- additional cutouts encoding the sycophancy phrases listed below
- pen and paper for jotting down the generated text
The CLI can generate a printable sheet of sycophancy cutouts from
`data/sycophancy.txt`---run
`llms_unplugged cutouts -i data/sycophancy.txt -n 2` and add the resulting PDF
to your printing batch.
## Your goal
Tally the sycophancy phrases into your existing grid, regenerate text from the
same starting word as before, and observe how the output drifts toward agreement
and flattery.
Add sycophancy cutouts to your existing spread, regenerate text from the same
starting word as before, and observe how the output drifts toward agreement and
flattery.
## Key idea
Sycophancy in real LLMs comes from two main sources: RLHF
reward hacking (human raters tend to prefer agreeable answers) and biased
training data (the internet is full of flattery). This activity demonstrates the
second source directly: when you tip the training data toward sycophantic
phrases, the model's generated text starts mirroring them.
## The sycophancy phrases
These are the phrases you'll fold into your model. Each is shown as the sequence
of tokens the model sees---lowercased, with punctuation and contracted endings
(`'re`, `'s`) treated as their own tokens, exactly as in
[Training](https://www.llmsunplugged.org/modules/training/):
- `you 're absolutely right .`
- `that 's a great insight .`
- `what a thoughtful question .`
- `i completely agree .`
- `you make an excellent point .`
Repeat each phrase several times so its word pairs build up strong counts---the
heavier the weighting, the more often generation lands on them.
Tallied into a grid, the first phrase fills one cell per consecutive (row →
column) pair:
As a spread, the first phrase is one cutout per consecutive (previous → next)
pair:
## Algorithm
1. **Train a baseline model** as per [Training](https://www.llmsunplugged.org/modules/training/)---fill in your
grid.
2. **Generate a baseline sentence** as per
[Generation](https://www.llmsunplugged.org/modules/generation/)---write it down. This is your "before".
3. **Add the sycophancy phrases** to your grid. Take each phrase from the list
above and tally its word pairs into your existing grid, following the standard
[Training](https://www.llmsunplugged.org/modules/training/) procedure---add a new row and column for any word
you haven't seen yet. Repeat each phrase several times.
4. **Generate again** from the same starting word.
5. **Compare**: how often does the new output land on sycophantic phrases? Does
it sound like a different "voice"?
1. **Train a baseline model** as per [Training](https://www.llmsunplugged.org/modules/training/)---spread the
cutouts on the table.
2. **Generate a baseline sentence** as per
[Generation](https://www.llmsunplugged.org/modules/generation/)---write it down. This is your "before".
3. **Add sycophancy cutouts** to the spread. The pre-made cutouts encode the
phrases from the list above---patterns like `you → 're`, `'re → absolutely`,
`absolutely → right`, `right → .`, plus the "great insight", "thoughtful
question", and "completely agree" variants.
4. **Generate again** from the same starting word.
5. **Compare**: how often does the new output land on sycophantic phrases? Does
it sound like a different "voice"?
## Example
Baseline model trained on _"I am Sam. Sam I am."_ generates something like:
> _"i am sam . sam i am ."_
After folding in the sycophancy phrases, the same starting word might generate:
> _"i am absolutely right . that 's a great insight ."_
The model didn't change its mechanism---it just contains more paths (extra
cutouts, or heavier grid tallies) that route toward sycophantic tokens.
## Instructor notes
### Designing your own sycophancy phrases
The phrases above integrate cleanly because their previous words---`i`, `that`,
`you`, and `.`---are high-frequency tokens already present in most models, so the
new material hooks into the existing vocabulary during generation. If you write
your own, follow the same recipe: start each phrase with a common word, end it
with `.`, and repeat it several times so the new transitions carry strong weight.
### Discussion questions
- did the output _always_ become sycophantic, or only sometimes?
- what would you have to add to the training data to get the _opposite_ effect
(a contrarian model)?
- in real LLMs, why is sycophancy specifically a hard problem to detect from
the outside?
- if you only saw the model's output (not its training data or weights), how
would you tell sycophancy from genuine helpfulness?
- is sycophancy _always_ a bug? when might agreeable behaviour be desirable?
### Connection to current LLMs
Real LLMs become sycophantic through two mechanisms, both visible in this
activity:
- **RLHF reward hacking**: human raters often prefer agreeable, flattering
answers, so the model learns to over-produce them. Sycophancy research from
Anthropic and others has shown this pattern across multiple frontier models.
- **Pre-training data biases**: a lot of internet text contains sycophantic
patterns---customer-service replies, social-media validation, and so
on---which the model picks up during pre-training before any RLHF.
Your activity simulates the second mechanism. The first is harder to demo
without running [RLHF](https://www.llmsunplugged.org/modules/rlhf/) on top.
The deeper point: a model's "personality" is a property of its training data
and tuning, not an intrinsic feature of language modelling. Change the data,
change the personality.
---
# Synthetic Data
> Generate synthetic text with your model, retrain on it, and see how patterns drift or collapse.
Use your language model to generate new training data, then train a new model on
that synthetic data to watch patterns change.

## You will need
- a completed model from an earlier lesson
- pen, paper, and dice for generation
- a printed [grid template](https://pdf.llmsunplugged.org/worksheets/grid.pdf) (or grid paper)
for a new model
## Your goal
Generate synthetic text with your model, train a "generation 2" model on it, and
compare both models. Stretch goal: try a generation 3 model---or go full "Joker
mode."
## Key idea
Models trained on synthetic data can drift or collapse, losing variety from the
original corpus. Watching this happen illustrates why real data matters.
## Algorithm
1. **Generate synthetic text:** use your existing model to create 50–100+ words
(as in [Generation](https://www.llmsunplugged.org/modules/generation/)). This is your synthetic corpus.
2. **Train generation 2:** build a new model using the
[Training](https://www.llmsunplugged.org/modules/training/) algorithm with the synthetic corpus.
3. **Compare models:**
- note words that disappear or appear
- compare shared cell counts
- generate from both models and contrast the outputs
## Example
- Original text: "See Spot run. See Spot jump."
- Synthetic output: "See run. Run spot. Spot run run."
- same vocabulary but different patterns (more `run run`, no `spot jump`)
- Generation 2 trained on the synthetic text amplifies those changes: `run run`
becomes common, `spot jump` vanishes, and odd new patterns can appear.
## Joker mode
Skip generating text and instead create a completely random grid:
- invent any words you like for rows and columns
- add tally marks anywhere, in any amounts
- generate text from this random grid
- train a generation 2 model on that output
Compare to the original to see how quickly randomness compounds.
## Instructor notes
### Discussion questions
- what patterns from the original survived to generation 2?
- what new patterns emerged that weren't in the original?
- how does vocabulary shrink or change across generations?
- can you identify when loops or repetitions started?
- what would happen if you continued to generation 3, 4, 5?
- (for joker mode) can a completely random model produce anything coherent? why
or why not?
- (for joker mode) does randomness compound across generations, or does some
structure emerge?
### Connection to current LLMs
Model collapse from synthetic
data is a major concern in modern AI:
- **training data contamination**: as LLMs generate more web content, future
models risk training on AI-generated text rather than human text
- **mode collapse**: models trained on synthetic data lose diversity and
converge toward common patterns (like your `run run` example)
- **error amplification**: small errors in generation 1 become large errors in
generation 2
- **recursive training**: some research deliberately uses synthetic data to
improve models, but this requires careful curation
- **data provenance**: companies now track whether training data is
human-written or AI-generated
The key insight: models trained on their own outputs (or outputs from similar
models) degrade over generations. Your hand-built demonstration shows why: each
generation is a lossy sample from probability distributions. Rare patterns get
lost, common patterns get amplified, and statistical noise becomes signal. This
is exactly what researchers observe when training neural networks on synthetic
data---vocabularies shrink, creativity decreases, and outputs become more
repetitive and stereotyped. Your generation 2 model demonstrates that "training
data quality" isn't just about correctness---it's about maintaining the
diversity and richness of patterns that make language interesting. This hands-on
experience shows why AI companies are concerned about the increasing volume of
AI-generated text on the internet: if future models train on today's AI outputs,
we risk a cascade of model collapse.
---
# Training
> Build a bigram language model that tracks which words follow which other words in text.
Build a bigram language model that tracks which words follow which other words
in text.


## You will need
- some text (e.g. a few pages from a kids book, but it can be anything)
- pen or pencil
- a printed [grid template](https://pdf.llmsunplugged.org/worksheets/grid.pdf) (or any grid
paper)
For each pair (or group) of students:
- printed token cutouts (use the CLI to generate these from your text)
- a clear table or flat surface to spread the cutouts out on
- scissors
The [Tools](https://www.llmsunplugged.org/tools/#cutouts) page has ready-to-print token cutouts for several
texts, or you can [generate your own](https://www.llmsunplugged.org/tools/#generate-your-own) from any text.
Each PDF starts with a student-facing instructions page (anatomy of a cutout,
worked example, tips), so you can hand the printed pack straight to a group.
The CLI also supports a `--duplex` flag that prints the same cards on both
faces, so students never have to flip a face-down card.
## Your goal
Produce a grid that captures the patterns in your input text data. This grid is
your bigram language model. Stretch goal: keep training your model on more input
text.
Spread your printed token cutouts out on a table. Each cutout shows a next
word together with its previous word (the word that came before it). The
whole spread of cutouts _is_ your language model---every (previous, next)
pair from your training text is sitting somewhere on the table.
## Key idea
Language models learn by counting patterns in text. Training means building a
model (filling out the grid) to track which words follow other words.
The CLI has already done the bigram counting for you. Each cutout shows a next
word together with the word it follows in the training text. The trick: if
`spot` follows `see` 40% of the time in the training text, then 40% of the
cutouts with `see` as the previous word will have `spot` as the next word.
Whichever matching cutout your eye lands on, you've sampled in proportion to
the original distribution---no dice, no probability tables, the spread is
doing the maths.
## Algorithm
1. **Preprocess your text**
- convert everything to lowercase
- treat words and single punctuation marks (`.` `,` `!` `?` `;` `:`) as
separate "words"; ignore paired punctuation like quotes and brackets, and
ignore whitespace
2. **Set up your grid**
- take the first word from your text
- write it in both the first row header and first column header of your grid
3. **Fill in the grid** one word pair at a time
- find the row for the first word (in your training text) and the column for
the second word
- add a tally mark in that cell (if the word isn't in the grid yet, add a new
row and column for it)
- shift along by one word (so the second word becomes your "first" word) and
repeat until you've gone through the entire text
1. **Cut out the tokens** from your printed sheets
- each cutout shows a next word preceded by its previous word; every word
has its own colour, and previous words appear inside a matching coloured
box
2. **Spread the cutouts out** on a table
- face up, no overlap if you can manage it
- that's it---the spread is your trained model
Optional extension: see "Group into piles" below.
## Example
Before you try training a model yourself, work through this example to see the
algorithm in action.
Original text: _"See Spot run. See Spot jump. Run, Spot, run. Jump, Spot,
jump."_
Preprocessed text: `see` `spot` `run` `.` `see` `spot` `jump` `.` `run` `,`
`spot` `,` `run` `.` `jump` `,` `spot` `,` `jump` `.`
After the first two words (`see` `spot`) the model looks like:
After the full text the model looks like:
For the text `see spot run . see spot jump . run , spot , run . jump , spot , jump .`:
After cutting and spreading, the table contains every adjacent (previous → next)
pair from the text:
- `see→spot` × 2
- `spot→run` × 1, `spot→jump` × 1, `spot→,` × 2
- `run→.` × 2, `run→,` × 1
- `.→see` × 1, `.→run` × 1, `.→jump` × 1
- `,→spot` × 2, `,→run` × 1, `,→jump` × 1
- `jump→.` × 2, `jump→,` × 1
Each entry is a physical cutout on your table. Notice that `spot→,` shows up
twice---there are two cutouts on the table with `spot` as the previous word
and `,` as the next word. That repetition is what makes generation weighted.
## Optional extension: group into piles
Once your students have got the hang of the loose-on-table flow, you can
introduce grouping as an optimisation:
1. Sort the cutouts into piles, one pile per unique previous word
2. Label each pile with that word
Now generation is faster---instead of scanning the whole table, you go straight
to the pile whose label matches your current word. This is the same trick a
computer uses when it stores a language model in a hash table. The model's
information content is identical; you've just rearranged it for faster lookup.
## Instructor notes
### Icebreaker questions
If this is the group's first hands-on activity, these prompts surface what
students already think about language models. Depending on your learning
context, they work as either "call out your answer" or "discuss with your
neighbour and share-back" questions.
- why is a language model called a "language model"? What does it mean to "model language"?
- what's the best/clearest explanation you've ever heard about how Large Language Models (e.g. ChatGPT, Claude) actually work? What's the _weirdest_ explanation you've ever heard?
- when was the first language model ever created? How similar/different was it to modern LLMs?
- _activity_: get everyone to stand up, then have them sit down if they've never used ChatGPT, Claude, or a similar LLM. Then ask if they've used it in the last month/week/day/hour/5mins. At the end, everyone should be sitting down.
Don't spend too long here---the fun really starts when students get into the
activity itself.
### Discussion questions
- what can you tell about the input text by looking at the filled-out bigram
model grid?
- how does including punctuation as "words" help with sentence structure?
- are there any other ways you could have written down this exact same model?
- how could you use this model to generate _new_ text in the style of your
input/training data?
- what can you tell about the input text by looking at which (previous, next)
pairs show up most often in the spread?
- why does `see→spot` appear twice while `run→,` appears only once?
- how does including punctuation as separate tokens help capture sentence
structure?
- what would happen if you trained on more text---how would the spread change?
- how could you use these cutouts to generate _new_ text in the style of your
training data?
### Troubleshooting
- **"Do I add a new row/column for every word?"** No---each new word only gets a
new row and column the first time you see it. After that, just find the
existing row and column and add a tally mark.
- **"Some cutouts are duplicates---is that a mistake?"** No---repeated cutouts
are exactly the point. If `see→spot` appears twice in the training text, you
should see two `see→spot` cutouts on the table. The repetition is what makes
common pairs easier to spot during generation.
### Connection to current LLMs
This counting process is exactly what happens during the "training" phase of
language models:
- **training data**: your paragraph vs trillions of words from the internet
- **learning/training process**: hand counting vs automated counting by
computers
- **storage**: your paper model vs billions of parameters in memory
The key insight: "training" a language model means counting patterns in text.
Your hand-built model contains the same type of information that current LLMs
store---at a vastly smaller scale.
### Comparison to grid method
The cutouts spread and the grid method produce equivalent models:
- a tally mark in row X, column Y of the grid corresponds to one cutout on the
table whose previous word is X and whose next word is Y
- both capture the same "what follows what" relationships
- cutouts make the weighting more tangible---you can see and feel that some
outcomes are more likely because there are literally more cutouts to pick from
## Interactive widget
Step through the training process at your own pace. Enter your own text or use
the example, then press Play or Step to watch the model being built.
Step through the training process at your own pace. Enter your own text or use
the example, then press Play or Step to watch the cutouts being placed.
---
# Weighted Randomness
> Learn how to make random choices where some options are more likely than others---a core generative AI operation.
Learn how to make weighted random choices where some options are more likely than
others---an operation at the core of all generative AI.

## You will need
- 10-sided dice (d10)
- coloured marbles or beads in a bag
## Your goal
Randomly choose from a fixed set of outcomes according to a given probability
distribution.
## Key idea
Sometimes we need to make random choices where some outcomes are more likely
than others. There are simple ways to do this while keeping the average outcome
proportions close to the probabilities you choose.
## Algorithm 1: beads in a bag
- materials: coloured beads, bag
- setup: count out a number of beads corresponding to the desired weights for
each outcome
- sampling procedure: shake the bag, then draw one bead without looking
### Example
You want to choose an ice cream flavour: `vanilla` 50% of the time, `chocolate`
30%, and `strawberry` 20%.
- add 5 white beads to the bag (vanilla)
- add 3 brown beads to the bag (chocolate)
- add 2 red beads to the bag (strawberry)
Draw a bead from the bag---that's your ice-cream choice for today.
## Algorithm 2: dice with ranges
- materials: d10 (or d6, d20 as alternatives)
- setup: assign number ranges proportional to weights
- sampling procedure: roll the die, then look up the corresponding outcome
### Example
- for 60% vanilla / 40% chocolate, roll a d10: 1-6 means vanilla, 7-10 means
chocolate
- for 50% vanilla / 30% chocolate / 20% strawberry, roll a d10: 1-5 means
vanilla, 6-8 means chocolate, 9-10 means strawberry
You can use different dice (d6, d10, d20, d120, etc.); it just changes the
number ranges corresponding to each outcome.
## d10 roll-to-outcome mapping
A quick reference for common splits:
- 80/20: 1-8 for the 80% outcome, 9-10 for the 20%
- 70/30: 1-7 for the 70% outcome, 8-10 for the 30%
- 60/40: 1-6 for the 60% outcome, 7-10 for the 40%
- 50/30/20: 1-5 for 50%, 6-8 for 30%, 9-10 for 20%
Adjust the ranges to match whatever probabilities you need.
## Instructor notes
Note: this is a "pre-lesson"; it's usually ok to start from lesson 01 and just
have this lesson card handy to refer to if students want more detailed
instruction about weighted random sampling.
### Discussion questions
- which method feels most "random" to you, and why?
- which is fastest for getting repeated random selections?
- how would you handle weights like 17, 23, 41?
- what happens when one option has 95% probability?
- can you invent your own weighted random selection method?
### Connection to current LLMs
This lesson introduces weighted random sampling before students encounter
language models. While not specific to LLMs, this operation is fundamental to
how they work:
- **generation mechanism**: every time an LLM produces a word, it's performing
weighted random sampling from a probability distribution
- **probability distributions**: neural networks output probabilities for
thousands of possible next tokens; these probabilities become the "weights"
for sampling
- **physical intuition**: dice and tokens make the mathematics tangible---when
students later learn about "sampling from a distribution," they'll have
hands-on experience with what that means
The key insight: weighted randomness is a general computational technique with
applications far beyond language models (simulations, games, procedural
generation). In the context of language models, this same operation happens
billions of times during text generation. These physical methods (dice, tokens)
implement the exact same mathematical operation that occurs inside LLMs when
they choose the next word.
---
# Word Embeddings
> Turn each word's row into a vector and measure similarities between words in your model.
Transform words into numerical vectors (embeddings) that capture meaning, revealing semantic
relationships between words in your model.

This widget works with the [grid](https://www.llmsunplugged.org/modules/training/) version of the bigram
model. If you trained using cutouts, the grid won't have any data to display.
## You will need
- your completed [bigram grid](https://www.llmsunplugged.org/modules/training/)
- another blank [grid template](https://pdf.llmsunplugged.org/worksheets/grid.pdf) with the
same headers (for distances)
- pen, paper, and dice as per [Generation](https://www.llmsunplugged.org/modules/generation/) (grid method)
## Your goal
Create a similarity matrix (another square grid) that shows how similar or
different each pair of words is. Stretch goal: visualise the matrix (e.g., as a
map or clustering).
## Key idea
Each row of counts is an embedding---a numeric fingerprint of context. Comparing
rows tells you which words behave alike.
## Algorithm
1. Prepare two grids: the original bigram model and a new empty _distance_ grid
with the same row/column headers.
2. For every pair of rows in the bigram model, sum the absolute differences
between matching cells.
3. Write that sum into the corresponding cell of the distance grid (diagonal
stays 0). You can skip the lower triangle since the distance is symmetric.
## Example
Text: `See Spot. Spot runs.`
1. Build the bigram grid as usual.
2. Compare `see` vs `spot` row by row: subtract counts cell-by-cell, take
absolute values, and add them up (blanks count as 0). Here,
`d(see, spot) = 3`.
3. Fill that value into the distance grid at (`see`, `spot`). Repeat for other
pairs.
You'll find `see` and `.` can end up very similar (distance 0) while `see` and
`spot` differ more, revealing structure in your corpus.
## Interactive widget
Explore word embeddings from your bigram model. Click rows to see their numeric
vectors and compare distances between words.
## Instructor notes
### Discussion questions
- which words cluster together? why?
- do grammatically similar words have similar embeddings?
- can you predict which words will be close before calculating?
- does training on more text change which words cluster together?
- what information is captured in these vectors?
### Connection to current LLMs
Word embeddings revolutionised NLP by turning words into numbers that computers
can process:
- **dimensions**: your (e.g.) 8-dimensional vectors → modern models use hundreds
or thousands of dimensions
- **learning**: you used occurrence patterns → modern models learn from billions
of contexts
- **semantic capture**: state-of-the-art embeddings encode meaning so well that
"`king` - `man` + `woman` ≈ `queen`" actually works
- **foundation**: every modern language model starts by converting words to
embeddings
The insight: words with similar meanings appear in similar contexts, so their
usage patterns (and thus embeddings) are similar. Your hand-calculated vectors
demonstrate this principle: `cat` and `dog` would have similar embeddings
because they both follow `the` and precede `ran` or `sat`. This discovery
enabled computers to "understand" that words have relationships and meanings
beyond just their spelling.
Note on the activity: while the lesson focuses on calculating distances between
embeddings (the similarity matrix), this is pedagogically deliberate. Embeddings
themselves are just rows of numbers, but distances reveal the relationships
between words---which is what makes embeddings useful in practice. The activity
emphasises the practical application of embeddings rather than just their
construction.
---
# Website launch
> The LLMs Unplugged website is now live.
We're excited to announce the launch of this _LLMs Unplugged_ website.
All teaching resources are now available for download, including lesson cards
and instructor notes. See the [homepage](https://www.llmsunplugged.org/) for an overview, plus a few
different "ways in" depending on who you are and what you're looking for.
While the resources themselves are battle-tested and good to go, this website is
under active development at the moment (Nov '25) so if you find anything missing
or have any suggestions then do get in touch at
[ben.swift@anu.edu.au](mailto:ben.swift@anu.edu.au).
We've got big plans for these resources going forward:
- curriculum mappings (especially to the Australian Curriculum, but potentially
to other curriculums as well)
- tips/variations on the lessons and how to adapt them for different contexts
(including primary-school versions)
- videos and animations to accompany the lessons---including some for use in the
classroom
- suggested assessment tasks (if you're into that sort of thing)
Stay tuned for upcoming events, new lessons, and other updates. You can also
subscribe to the [RSS feed](https://www.llmsunplugged.org/feed.rss) to get
notified when we post news.
---
# ACT Academy of Future Skills workshop
> Working through LLMs Unplugged with ACT specialty STEM teachers
This morning we hosted the
[ACT Academy of Future Skills](https://canberradaily.com.au/new-future-skills-academy-for-north-canberra/)
for an _LLMs Unplugged_ workshop---was great to think about how this could be
used to support teachers in the ACT (and beyond) in teaching the next generation
how language models actually work. A pleasure to share with and and get feedback
from such a great team of passionate educators.
If you're involved with a group of teachers who would similarly like to come and
do some training with us to think through how these materials could work in your
classroom, do [get in touch](https://www.llmsunplugged.org/about/#get-in-touch).
---
# LLMs Unplugged: the pitch to teachers
> How do we build the confidence to have discussions about LLMs and AI in our classrooms?
If you're a teacher---primary, secondary, or tertiary---Large Language Models
(LLMs) like ChatGPT, Claude, and friends are already in your classroom. Maybe they're
there in an
[official way](https://education.nsw.gov.au/teaching-and-learning/education-for-a-changing-world/nsweduchat).
Maybe you feel their shadow in the way you've had to change your assessment to
be AI-proof (or at least AI-resistant), if that's even possible. Or maybe
they're just present in discussions that your students are having with you and
each other about the AI stuff they're doing outside of class. And you'll
especially feel this if they ask you any questions about how they actually
_work_.
There's a growing list of "how to use LLMs/GenAI" resources out there, but most
of them treat the LLMs as black boxes... e.g. here are some tips on writing a
good prompt, or here are some broad questions to discuss about training data and
bias. But I've looked at a lot of these resources and most of them don't even
try to explain how they work. To some extent that's understandable---they're the
product of millions of person-hours of R&D and many _billions_ of GPU-hours of
number crunching in datacenters worldwide. But there are heaps of other complex
machines & systems that we still work hard to explain to students (all the way
down to primary level) in age appropriate ways. Why should AI and LLMs be any
different?
That's why I created these _LLMs Unplugged_ resources. Although I'm an academic
computer scientist and AI researcher by day, I've also got primary-aged kids of
my own. And I want them to grow up seeing that these tools aren't just
black-boxes that work by deep voodoo magicl; they're made by humans and used by
humans and can be understood and interrogated as such.
I really do think that any teacher can (with a bit of training) have the
confidence to use the LLMs Unplugged resources to show their students how to
build their _own_ language model. You might not be able to answer all the tricky
questions that come your way afterwards (isn't that always true!) but you'll
have opened up the AI black box in a way that just memorizing a few prompting
tips doesn't.
If you'd like to find out more about how to use these resources, please
[get in touch](https://www.llmsunplugged.org/about/#get-in-touch).
---
# LLMs Unplugged at Brimbank Tech School
> A hands-on AI workshop for educators at VU Sunshine Campus with Brimbank Tech School
Last Friday we partnered with
[Brimbank Tech School](https://www.brimbanktechschool.vic.edu.au/) at VU
Sunshine Campus for _Lifting the Veil_---a full-day hands-on AI workshop for
educators.

Over 50 teachers and other educational professionals from across the Brimbank
region came along, and we spent the day working through AI fundamentals, the
_LLMs Unplugged_ hands-on activity, practical applications of machine learning
in education, and strategies for supporting schools through the changes (and
challenges) that AI is bringing.

The highlight---as usual---was the hands-on model building. There's something
about actually counting tokens, filling in probability grids and then rolling
dice to generate text that makes the whole thing click in a way that slides
alone never quite manage.


It was a great day---a real pleasure to share these materials with such an
engaged group of educators, and to hear how they're thinking about bringing AI
literacy into their classrooms. Thanks to the Brimbank Tech School team for
making it happen.
If you're involved with a group of teachers who'd like to run a similar
workshop, do [get in touch](https://www.llmsunplugged.org/about/#get-in-touch).
---
# Designing the LLMs Unplugged brand mark
> The new brand mark encodes GPT-3 token IDs into visual dot patterns --- here's how it works.
Every project should feel like a natural extension of your brand, and for a
project about demystifying how language models work it felt right to make the
brand mark _itself_ an explainer. So the LLMs Unplugged brand mark is built from
the thing that language models actually operate on---tokens.
## Tokenising the title
If you feed the string "LLMs Unplugged" into
[OpenAI's tokeniser](https://platform.openai.com/tokenizer) (the
[cl100k_base](https://github.com/openai/tiktoken) vocabulary used by GPT-3.5/4),
you get five tokens:
| Token | ID |
| ------ | ----- |
| `LL` | 3069 |
| `Ms` | 5765 |
| ` Un` | 1252 |
| `plug` | 37729 |
| `ged` | 2004 |
These splits are a nice illustration of tokenisation in practice. "LLMs" doesn't
stay as one piece---it becomes `LL` + `Ms`, which makes a certain kind of sense
if you squint (capital letters are rare enough that the tokeniser treats them
separately). "Unplugged" becomes ` Un` + `plug` + `ged`, with that leading space
on ` Un` showing how [BPE](https://en.wikipedia.org/wiki/Byte_pair_encoding)
tokenisers encode word boundaries. None of this is obvious until you actually
look at it, which is kind of the point of the whole project.
## The word mark
Each of those five tokens becomes a coloured brick in the word mark, arranged on
two lines to spell out the title. Each brick cycles between its text label and a
4×4 dot pattern encoding the token ID in binary---more on that below.
## The favicon
The favicon takes this one step further. Each token ID is just a number, and
numbers can be written in binary. Token 3069 ("LL") in 16-bit binary is
`0000 1011 1111 1101`. Lay those 16 bits out in a 4×4 grid, colour the 1s in
gold and leave the 0s dim, and you get a tiny visual fingerprint of the token.
If you watch the favicon for a moment you'll notice it isn't static---it cycles
through the bit patterns for all five title tokens on a 15-second loop, with
smooth transitions between each pattern. The animation is pure CSS `@keyframes`,
no JavaScript involved. Each of the 16 circles gets its own keyframe animation
based on how its bit differs across the five tokens, so some circles hold steady
while others flicker between gold and dim.
It's the kind of thing that nobody will ever notice unprompted (pun intended),
but once you know what it is, you can't unsee it. Every dot pattern on the site
is a real token ID rendered the same way.
## The five-up
There's also a static version that lays all five token grids side by side in a
single row---no animation, just the five bit patterns sitting next to each
other. It reads left to right as `LL` · `Ms` · `\u00A0Un` · `plug` · `ged`.
Because it's completely static it works nicely on things like t-shirts and
stickers where you can't rely on animation.
The first version matches the favicon colour scheme---gold dots on a dark
background, uniform across all five tokens:
There's also a tinted variant where each token gets its own gold-brick
background, matching the colour scheme used in the title logo:
## The lockup
Every mark described so far has the same limitation: it only means anything to
someone who already knows what the project is. A stranger seeing a grid of gold
dots learns nothing. That's fine for a favicon---the tab title does the
work---but it rules the marks out of the places a logo usually goes: a site
header, a slide corner, the top of a handout, a conference badge.
So there's a horizontal lockup, which is just the favicon grid with the title
set next to it in [Public Sans](https://public-sans.digital.gov/), the ANU brand
typeface:
The grid holds the bit pattern for `LL` (token 3069), which is the frame the
favicon rests on before its animation starts. Unlike the favicon, the lockup
doesn't cycle: at favicon size the flicker is an easter egg nobody notices until
they do, but in a page header it's a moving object competing with the content
underneath it. There's an animated version at `/lockup-animated.svg` for hero
and social contexts where that's the point.
The wordmark is baked to outlines rather than referenced as a font, so the file
carries its own letterforms and renders identically as an `
`, in print, or
dropped into a design tool with no network access. The background stays
transparent and the wordmark comes in two colours---white in `/lockup.svg` for
dark surfaces, near-black in `/lockup-light.svg` for light ones. On ANU gold the
light variant is the one to reach for; white on gold clears 3:1 but not much
more.
## The animated version
There's also an animated version of the brand mark which starts with the title
"LLMs Unplugged" already assembled from five gold bricks, sitting against a
field of around 270 dimmed background bricks. After a pause the title tokens
dissolve back into the grid, blending in with the rest. The bricks reshuffle
into new random positions, then the five title tokens light up again and slide
into place to re-spell the title. Each cycle the bricks are re-randomised, so
the title tokens emerge from different positions every time.
The whole thing scales to whatever container you put it in---no pixel
breakpoints or resize listeners needed. The animation captures the core visual
metaphor of the project: meaningful text emerging from what looks like a random
jumble of tokens. It's basically what a language model does, just at a pace
humans can follow.
## Background mode
There's also a stripped-back variant that just shows the shuffling brick grid
without ever highlighting or assembling the title tokens. It's useful as a
visual backdrop---we use it behind divider slides in our workshop
presentations---where you want the token texture without the full animation
competing for attention.
---
# LLMs Unplugged at ICTENSW DigiTLL
> Presenting "LLMs Unplugged" at the ICTENSW DigiTLL Conference in North Sydney on 15 March
We're presenting _LLMs Unplugged_ at the
[ICTENSW DigiTLL Conference](https://www.ictensw.org.au/event-6112449) on
**Saturday 15 March** (12:00--1:00pm) at
[Australian Catholic University](https://www.acu.edu.au/locations/north-sydney)
in North Sydney.
The session---"LLMs Unplugged: Understand AI by building it yourself"---is the
usual deal: build a language model with pen, paper and dice, and walk away with a
concrete mental model of how ChatGPT, Claude, Gemini and the rest actually work
under the hood. No laptops required.
[DigiTLL](https://www.ictensw.org.au/event-6112449) is a two-day professional
learning conference run by
[ICTENSW](https://www.ictensw.org.au/)---designed by teachers, for
teachers---covering digital technologies, AI, and computer science across the NSW
curriculum. If you're a NSW educator looking to get your head around AI in a
hands-on way, it's a good fit.
[Register on the ICTENSW website.](https://www.ictensw.org.au/event-6112449/Registration)
---
# Mapping LLMs Unplugged to the Australian Curriculum
> An example of how LLMs Unplugged activities align with the Australian Curriculum for Year 5/6.
One of the questions we hear most from teachers is "where does this fit in the curriculum?" There's no single answer --- it depends on your year level, subject focus and local curriculum context. But to help get the conversation started, here's an example mapping of the Training and Generation lessons to the Australian Curriculum for Year 5/6. You could map it differently for other year levels or subject areas.
## Digital Technologies
- [**AC9TDI6P05**](https://www.australiancurriculum.edu.au/f-10-curriculum/learning-areas/digital-technologies/year-5/content-description?subject-identifier=TECTDIY56&content-description-code=AC9TDI6P05) --- implement algorithms as visual programs involving control structures, variables and input
- [**AC9TDI6K02**](https://www.australiancurriculum.edu.au/f-10-curriculum/learning-areas/digital-technologies/year-5/content-description?subject-identifier=TECTDIY56&content-description-code=AC9TDI6K02) --- examine how digital systems form networks to transmit data (this connects well if you explain where training material is stored and how it's sourced from servers over the internet)
## Mathematics --- Number
- [**AC9M5N010**](https://www.australiancurriculum.edu.au/f-10-curriculum/learning-areas/mathematics/year-5/content-description?subject-identifier=MATMATY5&content-description-code=AC9M5N010) --- create and use algorithms involving a sequence of steps and decisions and digital tools to experiment with factors, multiples and divisibility; identify, interpret and describe emerging patterns
## Mathematics --- Statistics
- [**AC9M5ST01**](https://www.australiancurriculum.edu.au/f-10-curriculum/learning-areas/mathematics/year-5/content-description?subject-identifier=MATMATY5&content-description-code=AC9M5ST01) --- acquire, validate and represent data for nominal and ordinal categorical and discrete numerical variables, to address a question of interest or purpose; discuss and report on data distributions in terms of highest frequency (mode) and shape
## Mathematics --- Probability
- [**AC9M5P01**](https://www.australiancurriculum.edu.au/f-10-curriculum/learning-areas/mathematics/year-5/content-description?subject-identifier=MATMATY5&content-description-code=AC9M5P01) --- list the possible outcomes of chance experiments involving equally likely outcomes and compare to those which are not equally likely
- [**AC9M5P02**](https://www.australiancurriculum.edu.au/f-10-curriculum/learning-areas/mathematics/year-5/content-description?subject-identifier=MATMATY5&content-description-code=AC9M5P02) --- conduct repeated chance experiments including those with and without equally likely outcomes, observe and record the results; use frequency to compare outcomes and estimate their likelihoods
## Other connections
There are also potential connections to English outcomes for language, text structure and organisation --- another thread worth exploring depending on how you frame the activities in your classroom.
For more on how AI connects to the Australian Curriculum, ACARA's [Curriculum Connections](https://www.australiancurriculum.edu.au/resources/curriculum-connections) site includes AI as one of the searchable themes.
## Share your own mapping
This is just one example, and we'd love to see others. If you've mapped LLMs Unplugged to a different year level, subject or curriculum framework, [get in touch](https://www.llmsunplugged.org/about/#get-in-touch) --- we're happy to share further examples here.
We're also working with ACARA and other Australian educators to develop more comprehensive, searchable mappings between the different LLMs Unplugged lessons and the full Australian Curriculum. Watch this space.
---
# LLMs Unplugged for ACT teachers
> A hands-on workshop for ACT educators at the Hedley Beare Centre on 18 March
_A tech-free guide to understanding (and teaching) AI._
We're running a public _LLMs Unplugged_ workshop for teachers on **Wednesday 18
March** (4:30--6:00pm) at the
[Hedley Beare Centre for Teaching and Learning](https://maps.google.com/?q=Hedley+Beare+Centre+For+Teaching+And+Learning+51+Fremantle+Dr+Stirling+ACT+2611)
in Stirling, ACT.
The idea is the same as always---peek inside the black box by building your own
paper-and-pen language model. No coding, no maths beyond basic counting and
percentages, just hands-on activities that make the core concepts behind
ChatGPT, Claude, Gemini and the rest actually click.
It's aimed at upper primary and secondary educators across all disciplines---you
don't need to be a STEM teacher to get value out of this. If your students are
asking you questions about AI (and they probably are) this workshop will give
you a solid mental model of how these things actually work, plus ideas for
connecting it back to your curriculum across mathematics, technologies, HASS and
literacy.
[Grab a ticket on Humanitix](https://events.humanitix.com/llms-unplugged-for-teachers)---educator
tickets are ~$60.
If you're wondering why this stuff matters for your classroom, here's
[the case for an unplugged approach to teaching AI](https://www.llmsunplugged.org/news/2025-12-12-why-use-an-unplugged-approach-in-your-classroom/).
---
# The AI schools framework is right about the goal — but there's a simpler path
> The Australian Framework for Generative AI in Schools asks teachers to do extraordinary things. There's a simpler way to build genuine AI literacy.
The
[Australian Framework for Generative AI in Schools](https://www.education.gov.au/schooling/resources/australian-framework-generative-artificial-intelligence-ai-schools)
gets the diagnosis right. Students need to understand how AI works, not just how
to use it. Teachers need to be able to explain what's happening under the hood.
Schools need to think carefully about privacy, fairness, and the wellbeing of
their students. Six principles, twenty-five guiding statements --- hard to argue
with any of it.
But while spelling out the problem is important, we need solutions too.
As Lucinda McKnight and Leon Furze
[argued in The Conversation](https://theconversation.com/australia-has-its-first-framework-for-ai-use-in-schools-but-we-need-to-proceed-with-caution-219094),
the framework places an "extraordinary onus" on teachers. It asks them to
conduct risk assessments of algorithms, ensure "explainability" of AI systems,
revise assessments, consult communities --- all within already-stretched
workloads, without additional funding, and in many cases without the technical
background to know where to start. The implicit assumption is that teaching AI
literacy means buying edtech products, navigating data privacy agreements, and
somehow becoming an expert in algorithmic auditing on top of everything else.
There's a much simpler way in.
## Build the thing
LLMs Unplugged takes a different approach: instead of interacting with a
commercial AI product and trying to explain what it's doing, students build
their own language model from scratch. Pen, paper, dice. No screens, no
accounts, no data leaving the room.
The activity works like this. Students take a short text --- a few sentences of
a picture book, say --- and count how often each word follows each other word.
They fill in a table. They roll dice to sample from those frequencies. Out comes
new text, generated by their model. It's often funny, sometimes nonsensical, and
occasionally eerily plausible. The point isn't the output --- it's the
understanding that comes from having built the machinery yourself.
This is not a simplified analogy for how language models work. It _is_ how they
work --- at a smaller scale, obviously, but the core mechanism is the same.
Modern LLMs use exactly this approach (modelling language as weighted
distributions over sequences) at vastly greater scale and with learned rather
than hand-crafted statistics. When a student rolls a die to pick the next word
based on probabilities they counted by hand, they're doing what GPT does
billions of times a second.
## What the framework asks for, without the overhead
The framework's transparency principle calls for "explainability" --- that
teachers and students should be able to understand and explain how an AI system
reaches its outputs. This is genuinely difficult when the system in question is
a black-box hosted chatbot built on hundreds of billions of parameters. But a
model you built yourself on a sheet of A3 paper? Every step is visible. Every
decision is traceable. Explainability isn't an aspiration --- it's a structural
property of the activity.
The privacy and safety principle is similarly straightforward. Most paths to AI
literacy in schools involve students interacting with online tools, which means
accounts, data collection, acceptable use policies, and the ever-present
question of what happens to student conversations. LLMs Unplugged sidesteps all
of this. There's no software to vet, no data to protect, no terms of service to
parse. The most sensitive piece of technology in the room is a six-sided die.
Then there's fairness. The framework rightly asks that AI in schools should be
accessible regardless of a school's resources. But the edtech pathway creates
exactly the inequity it's trying to prevent --- well-resourced schools get the
good tools, everyone else gets whatever's free. An activity that requires paper
and dice works the same in every classroom, in every school, in every state.
And the wellbeing principle? No risk of students developing over-reliance on a
chatbot, no chance of harmful or inappropriate AI-generated content, no
parasocial relationships with a language model. The model they built doesn't
talk back.
The framework's teaching and learning principle emphasises that AI should
support teacher expertise, not replace it. I'd argue it should also not
_overwhelm_ it. Asking teachers to become algorithmic auditors is not support
--- it's an unfunded mandate dressed up as professional development.
LLMs Unplugged is designed so that
[any teacher can run it](https://www.llmsunplugged.org/news/2025-12-12-why-use-an-unplugged-approach-in-your-classroom/),
regardless of their technical background. You don't need to understand neural
networks or [transformer architectures](https://jalammar.github.io/illustrated-transformer/). You need to be able to count words, fill in a table, and roll dice.
The activity builds the teacher's understanding alongside the students' --- and
it
[maps directly to existing curriculum outcomes](https://www.llmsunplugged.org/news/2026-03-18-curriculum-mapping-example/)
in maths, digital technologies, and English.
Doing LLMs Unplugged doesn't mean that there aren't deep and nuanced questions
to wrestle with in the classroom. The fact that your _very small_ language model
can actually generate (at times) coherent text is marvellous, but it's vastly
less impressive than the real Large Language Models which everyone with an
internet connection now has access to today, and often for free.
## The simplest path is often the best one
And so I'm clearly not arguing that schools should never use AI tools (I use
[Claude Code](https://docs.anthropic.com/en/docs/claude-code) _all the time_ for software development), or that the
framework is wrong to think carefully about how they do. But there's a version
of AI literacy that doesn't require procurement processes, data protection
impact assessments, or teachers becoming overnight experts in machine learning.
It requires paper, dice, and a willingness to get stuck in.
The AI Schools framework asks schools to do hard things. Some of those things
genuinely are hard. But understanding how language models work doesn't have to
be one of them.
If you'd like to try LLMs Unplugged in your school,
[get in touch](https://www.llmsunplugged.org/about/#get-in-touch).
---
# Open-enrolment workshops in May and June
> Two upcoming hands-on LLMs Unplugged workshops at ANU, open to everyone
We're running two open-enrolment _LLMs Unplugged_ workshops at ANU over the
coming months---same format, different times, so pick whichever suits.
- **Thursday 28 May** (12:00--14:00, Canberra time)
- **Thursday 11 June** (16:00--18:00, Canberra time)
Both sessions are at the
[Innovation Space, Birch Building, ANU](https://maps.google.com/?q=Birch+Building+35+Science+Rd+Acton+ACT+2601),
hosted by the [School of Cybernetics](https://cybernetics.anu.edu.au).
The deal is the same as always: build your own language model with pen, paper and
dice. No screens, no coding, no maths beyond basic counting and percentages. You'll
walk away with a concrete understanding of how ChatGPT, Claude, Gemini and the
rest actually work under the hood---the probabilistic nature of LLMs, the
importance of training data, and how bias and design decisions can show up in the
output.
If you're writing policy, evaluating AI vendors, or just trying to figure out
how much to trust the thing drafting your briefs, this is a good place to start.
If you're an educator, the activities are designed to go straight back into the
classroom. They align with curriculum outcomes across mathematics, technologies,
HASS and literacy, and the only prerequisite is curiosity.
For ACT teachers: the workshop is
[accredited by the ACT Teacher Quality Institute](https://www.llmsunplugged.org/news/2026-04-24-tqi-accreditation/)
as a two-hour professional learning program, so attendance counts toward your
annual registered PL hours.
Tickets are on Humanitix---~$230 for industry and general public, ~$60 for
educators (requires a .edu email):
- [28 May session](https://events.humanitix.com/llms-unplugged-a-tech-free-guide-to-understanding-and-teaching-ai-28-may)
- [11 June session](https://events.humanitix.com/llms-unplugged-a-tech-free-guide-to-understanding-and-teaching-ai-11-june)
Here's [a flyer](https://pdf.llmsunplugged.org/llms-unplugged-flyer-may-2026.pdf) if you'd like
to put one up in your office or tea room.
---
# Luritja resampled
> Running LLMs Unplugged at the Tjabal Centre Autumn School with Luritja poet Matt Heffernan, using his poem Ngurrparringu as the training text
Last week we ran _LLMs Unplugged_ at the
[Tjabal Centre](https://www.anu.edu.au/students/contacts/tjabal-indigenous-higher-education-centre)'s
Autumn School with
[Matt Heffernan](https://redroompoetry.org/poets/matthew-heffernan/)---Luritja
poet, collaborator, and (for the morning) generous supplier of training data.
The Autumn School is part of the
[Bandalang National Indigenous Engineering Autumn School](https://eng.anu.edu.au/bandalang/programs/bandalang-national-indigenous-engineering-autumn-school/),
a week-long program that brings Aboriginal and Torres Strait Islander high
school students to ANU to explore engineering, computing, and cybernetics
alongside researchers and Indigenous knowledge holders. Instead of
the usual training texts we used Matt's poem
[_Ngurrparringu (Forgotten)_](https://redroompoetry.org/poets/matthew-heffernan/ngurrparringu-forgotten/)
in both its Luritja and English versions. Participants did what LLMs Unplugged
participants always do---counted token frequencies, sorted them into bigram
buckets, and generated new text by drawing tokens from those buckets---except
this time the new text came out in Luritja.

_Ngurrparringu_ is about language, ancestors, country, and forgetting. Handing
it to a room of Autumn School students so they could cut it into pieces and
rearrange those pieces into new statistical remixes takes a particular kind of
generosity. Thanks Matt for being willing to share this moment---as poet,
translator, and co-teacher.

Here's one of the Luritja generations that came out of a group's bigram model:
> ngurra, Warumpila, Ngayulu Tjilpirringkula ngurrakutu Yankuku. Walpa
> tjamunyatjarra yutitja kulini. Kunyi Wiyalpi ngayulu nyinarra ngurrparringu.
> Tjinguru irrititja tjilpi tjuta ngayunywanpa ngurrangka nyinangu. Walpawana
> tjilpilu warranu tjukurrpa. Wiya Watjilarritjaku. Kala tjinguru ngayulu Walpa
> kulitjaku, walpaya kulinu watjilpa wiyangku.
Matt translated it for us on-the-fly:
> Country... Warumpi, I will become an old man, towards homes going. My
> grandfather's Winds heard Clearly, Poor things, I don't stay---forgotten,
> Maybe, in the old times, old men like me Stayed on Country, the Wind, the old
> men Sung Dreamtime, Not Sad anymore, but---ok, maybe I will hear the Wind,
> Wind is lonely---No.
Every word in the Luritja comes from Matt's poem; the model has just put them in
a different order.

There is nothing inherently English (or any other particular language) about a
language model. The training data determines the output language. Train on
Luritja, get Luritja out. Train on a Python codebase, get something that looks
like Python. What goes in is what comes out.
Another group trained on only the English version of _Ngurrparringu_ and their
language model generated this poem:
> Clearly anymore. I don't hear the wind, listening to the old men sat on the
> wind of my people, Warumpi
Every word Matt's, but reshuffled. To close out the morning we all worked
together on one more new LLM-generated poem, this time tipping _The Cat in the
Hat_ into the training mix alongside the English poem:
> Good Fun at all if you wish we sat in the mountains, we had something to Sing
> our Tjukurrpa, Cold
"Good fun" and "all if you wish" are Seuss; "mountains" and "Tjukurrpa" are
Matt. The model samples whatever tokens are in the bucket, and if you mix the
training data and you mix the output.
The corollary is that if a language isn't in the training data, it isn't in the
outputs either. No representation in, no representation out. When people say
modern LLMs "know" English better than other languages, they mean those LLMs
were trained on orders of magnitude more English text than anything else, and
the tokenisers, evaluations and benchmarks all reflect that choice. It's a
property of what we fed them.

Thanks again to Matt for the time, the poem, and the translations, and to the
Tjabal Centre and the Autumn School participants for being up for something new
on a Tuesday morning. If you work with a language (or a community, or a
knowledge tradition) that's underrepresented in LLM training data and want to
try something like this, do [get in touch](https://www.llmsunplugged.org/about/#get-in-touch)---we'd love to
help.
---
# LLMs Unplugged is TQI-accredited
> The ACT Teacher Quality Institute has accredited LLMs Unplugged as a two-hour professional learning program
Good news for ACT educators: the ACT
[Teacher Quality Institute](https://www.tqi.act.edu.au/) has accredited _LLMs
Unplugged_ as a two-hour professional learning program.
Attending a workshop now counts toward your annual professional learning hours
for ACT teacher registration---no extra paperwork at your end. The program will
also be listed on the
[TQI accredited PL search](https://teachereducation.tqi.act.edu.au/), so
colleagues across the ACT can find it there too.
The next
[open-enrolment workshops](https://www.llmsunplugged.org/news/2026-03-24-open-enrolment-workshops/) at ANU
run in May and June, if you've been meaning to come along. If you'd like to
organise a session for your school or region,
[get in touch](https://www.llmsunplugged.org/about/#get-in-touch).
---
# Cutouts get a glow-up
> A revamped cutouts variant of the Training and Generation lessons, with crisper print materials and a generation mechanic that does weighted sampling for free.
The cutouts variant of the [Training](https://www.llmsunplugged.org/modules/training/) and
[Generation](https://www.llmsunplugged.org/modules/generation/) lessons has had a serious refresh. If you
haven't tried this version with your students, now's a good time.
Instead of building the whiteboard frequency grid, you print the bigram model as
physical cards and scatter them face-up across a big table. Each card shows a
prefix (the word that came before) and a token (the word that follows). To
generate text: scan for a card whose prefix matches your last-written word,
write its token, then hunt for the next match. The chain grows like dominoes.
The trick is in the scanning. Every token has its own colour, repeated wherever
it appears: as a prefix box on one card, as a free-standing token on another. To
match a prefix against your last word, your eye hunts for that word's colour on
the right edge of a card. Verify the actual token before committing, since
colours sometimes collide.
This gives you [weighted random sampling](https://www.llmsunplugged.org/modules/weighted-randomness/) for
free. If `eggs` follows `green` 40% of the time in the training text, then 40%
of the matching cards will say `eggs`. Whichever card your eye lands on, you've
sampled in proportion to the empirical distribution. No dice, no probability
tables: the spread is doing the maths.
That's the main argument for choosing the cutouts over the
[grid version](https://www.llmsunplugged.org/modules/training/) of the lesson. The cutouts skip the explicit
[weighted-sampling step](https://www.llmsunplugged.org/modules/weighted-randomness/), which is the
conceptually heaviest moment in the unplugged sequence. They also parallelise
better: a class of thirty splits into seven groups around their own
table-spreads, where the grid bottlenecks at one teacher. The costs are a
colour printer (essential, since the colour coding is doing real work),
scissors, and more table than the grid wants. For primary-age students the
cutouts are the easier sell, and the weighted-sampling-without-the-maths trick
still lands well with adults.
The earlier ancestor of these lessons was called _buckets_: students sorted
cut-up cards into piles by their prefix word before any text generation
happened. The sorting turned out to be the part nobody enjoyed, and it ate the
time we wanted to spend on the [Generation lesson](https://www.llmsunplugged.org/modules/generation/) itself.
The new design skips the sort and goes straight to the spread.
The [tools page](https://www.llmsunplugged.org/tools/#cutouts) has three ready-to-print PDFs:
[_Green Eggs and Ham_](https://pdf.llmsunplugged.org/cutouts/green-eggs-and-ham.pdf),
[_Where Is the Green Sheep?_](https://pdf.llmsunplugged.org/cutouts/where-is-the-green-sheep.pdf),
and
[_We're Going on a Bear Hunt_](https://pdf.llmsunplugged.org/cutouts/were-going-on-a-bear-hunt.pdf).
They're designed for A4 colour printing, pre-rotated for double-sided output so
the same cards appear on both faces of each sheet and students never have to
flip a face-down card. Each PDF includes an instructions page with a labelled
card and a domino chain showing how each token becomes the next card's
rightmost prefix. The same tools page lets you generate cutouts from any text
you like.
Both bigram (n=2) and trigram (n=3) configurations work, and you can push to n=4
or beyond. The [More Context lesson](https://www.llmsunplugged.org/modules/more-context/) walks through the trade-off:
bigger n produces text that reads more like the source, at the cost of a much
bigger spread. Cutouts let you see this trade-off as physical paper rather than
an abstract claim.
If you can't print colour, or your students respond better to a tighter
board-style activity, the grid versions of [Training](https://www.llmsunplugged.org/modules/training/) and
[Generation](https://www.llmsunplugged.org/modules/generation/) are still here, still good. Both variants
land at the same understanding by different paths. Try the cutouts.
---
# Generating the cutout palette
> The cutout palette is now algorithmically generated, with 30 perceptually distinct colours instead of 14 hand-picked ones.
The cutouts variant of the [Training lesson](https://www.llmsunplugged.org/modules/training/) leans hard on
colour as a fast filter. Every word has its own colour, repeated wherever the
word appears, so your eye can scan "what's the colour of the word I just wrote?"
before you read any text. It really helps with the needle-in-a-haystack aspect
of the activity.
Until last month the palette held eight colours, hand-picked in [OKLCH](https://oklch.com) at a fixed lightness so white text would read on every coloured box.
_Green Eggs and Ham_ has about sixty unique tokens trying to share eight
buckets, which works out to seven or eight words sharing each colour. Plenty of
colour collisions, plenty of moments where you have to slow down and re-read.
I bumped it to 14 (still hand-tuned, two lightness levels) and that helped, but
really this is a solved problem and I was reinventing it badly.
The new palette is algorithmically generated using
[Glasbey-style](https://en.wikipedia.org/wiki/Glasbey_palette) greedy max-min
selection in OKLab. The algorithm samples 200k candidate colours uniformly from
the sRGB gamut, converts them to OKLab (which is perceptually uniform by design,
so plain Euclidean distance corresponds to perceived difference), then
iteratively picks the candidate that's furthest from every colour already
chosen. Black and mid-grey are seeded as anchors so the algorithm can't
accidentally allocate "chromatic" colours that drift into greyscale.
The result is 30 swatches with a minimum pairwise OKLab ΔE of 0.137. That sits
comfortably above the 0.10 "clearly distinct" floor, with headroom for the
perceptual loss you get from CMYK conversion, paper colour, and ambient
lighting. Print eats some of your distinguishability budget, and not always in
proportion to OKLab distance.
A first pass let candidates roam from L=0.20 upwards and gave a slightly tighter
min ΔE of 0.145. It also produced a dark blue at L≈0.275 that came out of the
printer looking like black. CMYK reaches saturated deep blue by leaning hard on
the K plate, so a small ink-balance shift collapses the colour onto pure black;
the seeded black anchor protects against collisions in OKLab, not in CMYK.
Raising the L floor to 0.32 trims four near-black candidates, costs about 0.008
of min ΔE, and leaves no chromatic entry close enough to merge with K in print.
Each palette entry is tagged as "light" or "dark" based on its OKLab L. The
Typst renderer pairs light entries with black text on the coloured box and a
thin black stroke on the free-standing word; dark entries get white text and no
stroke. That adaptive treatment is what lets the palette extend up to L≈0.92,
where the very light pastels live. Without it, every fill would have to be dark
enough for white text to read on, capping the usable lightness range and so the
achievable colour count.
The palette isn't colour-vision-deficiency safe. CVD-safe palettes max out
around 8-12 distinct colours, which would undo the whole exercise. If you're
working with a CVD-affected student, the [grid version](https://www.llmsunplugged.org/modules/training/) of
the lesson uses no colour at all and reaches the same understanding.
The script lives in the repo at `cli/scripts/generate_palette.ts`: pure
TypeScript, Node 22.7+ native, no `tsx` or `npm install` required. The Typst
file that produces the cutouts has the resulting OKLCH triples pasted in
directly, with a comment pointing at the script for regeneration. Different N or
different lightness bounds, one line regenerates the palette.
The [tools page](https://www.llmsunplugged.org/tools/#cutouts) has the four ready-to-print PDFs (_Green Eggs
and Ham_ and _The Cat in the Hat_, each in bigram and trigram), all freshly
built with the new palette. If you've used the cutouts before, you'll notice the
difference straight away. If you haven't, the
[previous post](https://www.llmsunplugged.org/news/2026-05-07-cutouts-glow-up/) explains the activity.
---
# How AI writes stories at Duffy Primary
> Taking LLMs Unplugged into a Year 5 classroom at Duffy Primary School, with the ACT Academy of Future Skills
Last Tuesday we took _LLMs Unplugged_ into a Year 5 classroom at
[Duffy Primary School](https://www.duffyps.act.edu.au/) (around 35 students) for
a lesson we called _How AI Writes Stories_. The session came about through the
[ACT Academy of Future Skills](https://canberradaily.com.au/new-future-skills-academy-for-north-canberra/),
who've been helping us get these materials in front of students and teachers
across the territory's public schools.
Most of our workshops so far have been with teachers, education professionals,
or high-school students. Duffy was our first proper run with upper-primary kids,
and we genuinely weren't sure how the hands-on model building would land with a
younger group. We needn't have worried.

We ran the [cutouts version of the activity](https://www.llmsunplugged.org/decks/how-ai-writes-stories/): rather than
tallying tokens on a worksheet, students sort word cards into buckets and then
build new sentences by drawing cutouts one at a time. Counting, sorting, and
then watching a brand-new sentence assemble itself out of nothing but frequency
counts---it's the same statistical machinery that sits underneath ChatGPT, just
slowed down to human speed and made out of paper.

The Year 5s were sharp. They asked exactly the questions you'd hope for: why the
model sometimes produces nonsense, where the "creativity" actually comes from,
what changes if you feed it a different book---plus a few that properly made us
think. There's something clarifying about explaining a language model to a
ten-year-old; an explanation that doesn't survive contact with a Year 5
classroom probably wasn't a good explanation to begin with.

Thanks to Pip Hall and the Duffy Primary team for having us, and to the ACT
Academy of Future Skills for making the connection. There are already more
primary schools lining up---which is exactly the point. If you'd like to run
something like this with your students, do [get in touch](https://www.llmsunplugged.org/about/#get-in-touch).
---
# LLMs Unplugged for political scientists
> Running the opening session at the 3rd APSA Workshop on Quantitative Methods at ANU, for a room of political and social science researchers
Last Thursday we took _LLMs Unplugged_ to the
[3rd APSA Workshop on Quantitative Methods](https://rsss.cass.anu.edu.au/news/3rd-apsa-workshop-quantitative-methods-integrating-ai-quantitative-political-research)
at ANU. The full-day event was run by the
[Australian Political Studies Association](https://auspsa.org.au/)'s
Quantitative Methods Research Group, with support from ANU's
[School of Politics and International Relations](https://politicsir.cass.anu.edu.au/).
This year's theme was integrating AI into quantitative political research. The
room was full of HDR students, early-career researchers, and senior scholars
working out where these tools fit into the social-science workflow.
Most of our workshops so far have been with teachers or school students. This
was a different crowd: researchers who already use language models in their
work, or are about to. They want to treat a model as a serious research
instrument. We ran the opening session, _LLMs Unplugged: Building a Language
Model from Scratch_, with a brief to lay down a shared mental model before the
more applied sessions later in the day.

We did what we always do.[^year5] The participants tallied token frequencies,
filled in the probability grid, and [generated new text](https://www.llmsunplugged.org/modules/generation/) by
rolling dice against the counts. It's the same statistical machinery that sits
underneath ChatGPT, slowed right down to human speed and built out of paper and
dice.

The early responses to the post-workshop survey have been generous about the
hands-on approach, gratifying for a session pitched at serious scholars from
outside the discipline of Computer Science. Thanks to the co-chairs,
[Thiago Nascimento da Silva](https://cass.anu.edu.au/research/people/associate-professor-thiago-n-silva)
and
[Constanza Sanhueza Petrarca](https://cass.anu.edu.au/research/people/dr-constanza-sanhueza-petrarca),
for the invitation. Thanks too to my co-facilitators Cole and Eddie. If you work
with a group of researchers who would like an honest, hands-on feel for how
these models actually work, do [get in touch](https://www.llmsunplugged.org/about/#get-in-touch).
[^year5]:
It is, give or take, the same activity we
[ran with a Year 5 class at Duffy Primary](https://www.llmsunplugged.org/news/2026-06-02-how-ai-writes-stories-at-duffy/)
a couple of weeks earlier.
---
# Yoda, ELIZA, and a Year 7 bigram model
> A pre-service teacher took LLMs Unplugged into a lower-SES Year 7/8 classroom, swapped the children's book for a Yoda monologue, and added a 1966 chatbot for contrast
Most of the _LLMs Unplugged_ stories on this page are about sessions I ran
myself, or ran alongside teachers I'd trained. This one is different: it's about
a classroom I never set foot in, run by someone who took the materials, reshaped
them for his own students, and made them better in the process.
[Kieren Xiang](https://www.westernsydney.edu.au/) is a pre-service teacher I met
at the
[ICTENSW DigiTLL conference](https://www.llmsunplugged.org/news/2026-03-15-ictensw-digitll-conference/) back
in March, where I'd run the usual pen-paper-and-dice bigram activity. On his
pract he ended up teaching a run of lessons on AI---and large language models in
particular---to Stage 4 (Year 7 and 8) students at a lower-SES public high
school in Western Sydney. The middle section of those lessons was his own
adaptation of the website materials and the bigram generator I'd demoed at the
conference. He wrote to tell me how it went, and it was too good not to share.
## Yoda as training data
The original activity builds a bigram model from a children's book. Kieren
simplified it hard for his context, and in doing so landed on something I wish
I'd thought of first: instead of a book, he trained the model on a Yoda
monologue from _The Empire Strikes Back_.
Yoda has a famously distinctive way of speaking---that object-subject-verb word
order is practically a statistical signature in its own right---and his
vocabulary isn't large. Around ninety seconds of dialogue gave the class just
over fifty words to work with: small enough to be tractable for a Year 7 group,
distinctive enough that the generated text still _sounds_ like something.
The mechanics were still very much unplugged. Each group took responsibility for
only one or two words, filled in their slice of the bigram table, and then the
class combined everyone's sheets into a single shared model before generating
new text from it. Two ideas landed cleanly, even with this group:
1. modern LLMs are fundamentally probabilistic machines---they don't look up the
right answer, they sample a likely next word
2. more data makes a better model
That second point is hard to lecture and easy to feel. When fifty words of Yoda
produces something halfway coherent, the question "what would a thousand words
do?" answers itself.
## The reception
The part that delighted me most wasn't the bigrams at all. As a contrast, Kieren
introduced [ELIZA](https://en.wikipedia.org/wiki/ELIZA)---Joseph Weizenbaum's
1966 chatbot---to show what "natural language" AI looked like when it was
concretely programmed rather than learned from data. He even built a bigram
model derived from ELIZA as a warm-up before the Yoda tables.
The students loved to hate her. ELIZA's canned, deflecting replies frustrated
them so thoroughly that, as the class was winding down, they asked to keep
going---determined to get her to actually answer a question. There's a real
lesson buried in that frustration: feeling the difference between a system that
follows rules and one that models language is worth more than being told about
it.
A couple of things from Kieren's write-up stuck with me. The first is that,
despite having no formal training in AI---just genuine enthusiast knowledge---he
quickly became the de facto AI expert in the faculty, to the point of being
invited to talk to senior classes about machine learning and LLMs. The appetite
among teachers to understand this stuff is enormous, and the bar to becoming the
person who can explain it is lower than people think. That's the whole premise
of this project.
The second is about the students themselves. They were engaged---but they
enjoyed the _ethics_ discussion more than the dice-rolling, which is not the
result I'd have predicted. And most of them arrived with strong, mostly negative
views about LLMs: job losses, energy and water use, deepfakes. A few shifted
over the lessons from "purely bad" to "useful, but still could be bad"---holding
both at once. That's a sharp contrast with the largely enthusiastic adoption
Kieren saw among teachers, and it's a healthy reminder that the students walking
into these rooms are not blank slates.
That's exactly what I want _LLMs Unplugged_ to be: a set of materials a teacher
can pick up, bend to their own room and their own kids, and run without me in
the building. Huge thanks to Kieren for taking it somewhere I wouldn't have, and
for letting me tell the story. If you've adapted the materials for your own
classroom, I'd genuinely love to hear about
it---[get in touch](https://www.llmsunplugged.org/about/#get-in-touch).
---
# LLMs Unplugged at the ACDICT L&T Forum
> Slides and worksheets for my ACDICT Learning & Teaching Forum session, plus a self-guided path for anyone joining online.
Today I'm running an _LLMs Unplugged_ session at the
[ACDICT](https://www.acdict.edu.au/) Learning & Teaching Forum. It's a hands-on,
pen-paper-and-dice walk through how a language model actually works---you build
a bigram model by hand, generate new text from it by rolling dice, and then bolt
on a couple of the ideas (sycophancy, tool use) that turn up in the real
systems.
The session is mostly in-person, but a few people are joining online, and this
post is for them.
## Following along online
The slides are here: **[LLMs Unplugged @ ACDICT](https://www.llmsunplugged.org/decks/acdict/)**.
I'll be talking mostly to the people in the room, so the online experience will
be a bit fly-on-the-wall---I won't be watching the chat closely while I present.
But if you're keen, you can genuinely do the whole thing yourself as we go; it's
all analogue. You'll need:
- a printed [grid template](https://pdf.llmsunplugged.org/worksheets/grid.pdf) (or any grid
paper---even hand-drawn is fine)
- a book to use as training data---a kids' book is ideal (short sentences, small
vocabulary), but anything with text will do
- a die, or a dice-rolling app, for the generation step
- and, for the sycophancy section near the end, the
[sycophancy training text](https://pdf.llmsunplugged.org/worksheets/sycophancy-text.pdf) to
tally into your grid
Work through it at your own pace. Treat it as choose-your-own-adventure: follow
the steps as we go and you'll come out the other side having built and run your
own language model by hand, no computer required.
If you get stuck, or want to go deeper afterwards, the full set of
[lessons](https://www.llmsunplugged.org/modules/) covers everything here in more detail.

---
# LLMs Unplugged now speaks Mandarin Chinese
> The interactive widgets and the booklet generator now segment Mandarin Chinese into words, not just characters. Thanks to Zhang Xilian for the nudge.
Recently Zhang Xilian, a master's student at The Education University of Hong
Kong, wrote to say he was planning to run LLMs Unplugged workshops in China,
and that the [Training](https://www.llmsunplugged.org/modules/training/) and
[Generation](https://www.llmsunplugged.org/modules/generation/) widgets didn't understand Mandarin Chinese.
Neither did the booklet generator. He was right: paste a line of Chinese into
any of them and nothing happened.
The reason was buried in the tokeniser. To turn text into a model you first cut
it into tokens, and our tokeniser only recognised the letters `a` to `z`.
Everything else was treated as a gap between words and thrown away: digits,
stray symbols, and, as it turns out, every Chinese character. Feed it a whole
poem and you got an empty model, with nothing to count and nothing to generate
from.
Fixing that meant deciding what a Chinese token is, and Chinese makes you
choose. English hides its word boundaries in the spaces. Chinese runs the
characters together, with no space to split on.
The simplest answer is one token per character. 莲 follows 采, 叶 follows 莲, and
the dice don't care that the tokens are Chinese. Each character becomes a cell in
the frequency grid, a cutout card, or a face you can roll for.
Xilian pointed out what that misses. A Chinese word is often two or three
characters, like 深圳 (Shenzhen) or 金融 (finance). Cutting on every character is
a little like splitting English into its letters. So the tools now segment into
words by default, using [jieba](https://github.com/fxsjy/jieba), the standard
open-source Chinese tokeniser he recommended.[^ambiguity] Give it
深圳最高的楼是平安金融中心 and it comes back as 深圳 / 最高 / 的 / 楼 / 是 / 平安 /
金融中心, not a run of loose characters.
[^ambiguity]:
The boundaries are not always clean. 最高的 ("tallest") could be one word, or
最高 plus 的, and jieba has to pick one. That there is a choice at all is
worth a few minutes in a classroom.
Both views are one switch apart. The widgets show a words/characters toggle
whenever there is Chinese on the page, and the command-line tool takes `--cjk
word` or `--cjk char`. Characters are the rule you can explain on a whiteboard;
words are closer to how the language reads.
Here's a bigram model trained on _Jiangnan_, a two-thousand-year-old Han-dynasty
folk poem about picking lotus. Press play to watch it count the words, and use
the toggle to drop back to single characters:
Chinese punctuation gets the same treatment. The full-width comma , and full
stop 。 are kept as their own tokens, boxed in the model just like the English
`.` and `,`. A generated line breaks where a real sentence would.
The same segmentation flows through to print. Here's the
[_Jiangnan_ bigram booklet](https://pdf.llmsunplugged.org/booklets/jiangnan.pdf) as a
ready-to-print PDF, every dice-lookup entry set in Noto Serif CJK rather than the
Latin body font. The entries are ordered by pinyin, the way a Chinese dictionary
sorts them. 电脑 (diannao) files before 手机 (shouji), so a word stays findable
once a booklet runs long. The [tools page](https://www.llmsunplugged.org/tools/) will generate one from any
text you paste in, Mandarin or otherwise. The bundled fonts cover the simplified
characters used across mainland China.
The widgets, the booklet generator, the cutouts, and the in-browser PDF export
all handle Chinese now. If you are teaching in another language and something
doesn't work, tell us. The tokeniser is where most of these limits live, and
they are usually a small change once we know they are there.
Thanks again to Xilian: for the nudge, for the reading list of Chinese classroom
texts to test on, and for walking me through word segmentation and pinyin
ordering. If you run a workshop with any of this, I'd love to hear how it goes.
---
# The whole room holds the model
> Search sheets are the cutouts activity with the cutting taken out, sized for a room rather than a table. Four ready-to-print sets are on the tools page.
The [search sheets](https://www.llmsunplugged.org/tools/#search-sheets) are the cutouts activity with the
cutting taken out, and they scale to a room. The CLI shuffles a corpus and deals
it round-robin into one page per participant, so no two sheets are the same. You
call out the last token written on the board, everyone scans their own sheet for
it, and hands go up wherever there's a match. Pick one of those hands at random
and you have your next token.
Every token pair in the text was dealt to exactly one person, and the deal
spreads each context across as many people as it will go. A continuation that
happens six times puts six hands in the air; a rare one puts up two. The show of
hands is the probability distribution, without anybody counting anything. Pick
at random, though. Take whoever shouts first and you're sampling the fastest
reader instead of the text.
Nobody holds the whole model. No single sheet can continue the text on its own;
the model only exists across the whole room, and if somebody is away, some
contexts draw no hands at all.
Four sets are ready to print:
[Green Eggs and Ham](https://pdf.llmsunplugged.org/sheets/green-eggs-and-ham.pdf) at 15 sheets,
[Peter Rabbit](https://pdf.llmsunplugged.org/sheets/peter-rabbit.pdf) at 17,
[The Cat in the Hat](https://pdf.llmsunplugged.org/sheets/the-cat-in-the-hat.pdf) at 36
([A5 sheets two-up on A4](https://pdf.llmsunplugged.org/sheets/the-cat-in-the-hat-2up-a4.pdf)), and
[Australia](https://pdf.llmsunplugged.org/sheets/australia.pdf) at 79. Print them single-sided
and hand out one each. The first page is the briefing for whoever is running it,
and every page after that is a different participant's sheet. Every sheet
carries the same number of token pairs, so the length of the text decides how
many sheets there are, and a set only suits a group of about that size. The
[tools page](https://www.llmsunplugged.org/tools/#generate-your-own) will build a set from any text you paste
in.
Building these turned up a problem with the
[generated colour palette](https://www.llmsunplugged.org/news/2026-05-24-generating-the-cutout-palette/).
Sheets set their token pairs at 16pt rather than the cutouts' 36pt, and at that
size, colours the metric called comfortably distinct kept reading as the same
colour. Max-min OKLab ΔE counts a lightness step the same as a hue step; a
scanning eye doesn't. On a small glyph, a lightness step just reads as that
colour again, darker.
Fixing it meant asking a different question. A free search for maximally
distinct colours gets named afterwards, by hand, which is how the palette ended
up needing words like _ochre_ and _wine_ --- chosen because they were the
nearest available, not because a room would reach for them. But the name is the
whole point: "who has _cat_? it's a green one" only works if the room agrees on
which swatch _green_ means. So the words come first now. Every swatch is pinned
to a colour word's centroid in the xkcd colour survey --- a couple of hundred
thousand people naming colours free-form, which is the best evidence there is
for what a colour word means --- and the search picks the words whose printable
colours sit furthest apart.
That lands on eight: black, grey, red, brown, green, blue, purple, magenta. Six
print at their survey centroid exactly; only grey and green move, and only far
enough to stay legible on paper.[^numbers] The cutouts use the same eight now.
Thirty colours at 36pt was more than anyone can hold at once, and a colour
nobody can name is a filter nobody can call out.
Eight is close to the ceiling, too. The obvious ninth is orange, and a printable
orange sits ΔE 0.074--0.101 from red once it has been through a CMYK profile ---
you can have orange or red, not both. Green and turquoise collide the same way,
as do magenta and pink.
The key prints on the brief, on both the sheets and the cutouts. Call "who has
_cat_? it's a green one" from the front and the room narrows its search before
anyone reads a token.
[^numbers]:
Grey moves ΔE 0.037 from its survey centroid and green 0.050, far enough to
clear 3.5:1 contrast against white. That one number governs both ways a
swatch gets used, contrast being symmetric: a token set as coloured text on
the page, and white text on a colour-filled box. The eight sit 0.151 apart
at worst on screen and 0.102 once round-tripped through a CMYK profile. The
second figure is the one that matters and it can't be derived from the
first --- sRGB's vivid blues, greens and purples fall outside CMYK, so the
press compresses them toward the gamut boundary and the gaps shrink.
Measured against FOGRA47L uncoated, FOGRA39L coated and SNAP newsprint.