Generating Lehrplan-aware lesson prompts
The German curricula (Lehrpläne) look deceptively simple from the outside: a syllabus, a topic, a grade. In practice each federal state ships its own document, formatted differently, sliced into competencies, sub-competencies, content objectives, and cross-cutting themes. A lesson plan that feels right to a teacher hits the matching nodes in that tree.
When we first prototyped the Lesson Planner we did the obvious thing: paste the relevant Lehrplan section into the prompt as text. It worked for one state and broke quietly for the rest. The model would happily invent plausible-sounding competency codes, mix Bavaria’s structure with Berlin’s wording, and produce lesson outlines no teacher would file.
What changed
We now parse each Lehrplan once into a normalised tree and let the planner ask for exactly the slice it needs before drafting anything:
slice = curriculum.find(
state="NRW",
subject="Mathematik",
grade=7,
competency="Funktionen.LineareFunktionen",
)
prompt = render(
"lesson_plan.jinja",
objective=slice.objective,
sub_competencies=slice.children,
cross_cutting=slice.cross_cutting_themes,
duration_minutes=45,
)
Two things fall out of this:
- The model stops hallucinating competency codes — it only sees real ones.
- We can show teachers which Lehrplan nodes a given lesson plan claims to cover, with citations back to the source document. That’s the difference between a tool you trust and a toy.
What’s still hard
Cross-state alignment. NRW’s “Funktionen” and Bavaria’s “Funktionale Zusammenhänge” overlap maybe 80%. We currently don’t try to bridge them — each state’s tree stands alone. A teacher moving from Bayern to NRW gets fresh material, not a translated version of their old one. We’re fine with that for now; pretending the trees are interchangeable would be worse than admitting they aren’t.