Skip to content

Architecture

LernWerkstatt follows a layered architecture with clearly separated responsibilities: a wizard interface, a job manager for server-side production runs, a pipeline layer with DAG execution, specialised components for normalisation, validation, terminology and assembly, and file-based persistence with an SQLite job register. Language models, embedder and reranker run outside the application and are addressed over OpenAI-compatible HTTP APIs. Generation is implemented as a generator-based pipeline that streams progress events to the interface.

At a glance

  • Layer separation: UI (Gradio 6) → job runner → pipeline → unit components → persistence and external endpoints
  • Server-side production in its own task, decoupled from the browser session
  • Per-chapter execution via a directed graph with layered parallelism
  • Two model roles with separate endpoints, assigned per task rather than globally
  • Deterministic normalisation and validation without model calls between generation and delivery
  • Persistence as JSON artefacts per job plus an SQLite register
  • Configuration exclusively via .env or environment variables
  • Deployment as a Docker container behind a reverse proxy

Layers and components

UI layer — A Gradio 6 application with five successive steps (learning profile, planning, release, production, result). The session state holds the job number and references, not the content itself. A status timer mirrors the server-side run into the interface and rests while no production is active.

Job management — A process registry holds running productions as asyncio tasks with a log buffer and status file. The browser window may be closed; a job list with status and phase reached allows reattaching later. Cancellation takes effect through a stop signal at the next chapter boundary.

Pipeline layer — Phase control coordinates eight phases: learning profile, gap analysis, concept graph, source coverage, detailed plan, prose, blocks and consolidation. Two directed graphs are planned per chapter and executed in layers; the layers follow from the dependencies, and within a layer tasks run in parallel under a semaphore. Chapters are additionally interleaved: run A of chapter k+1 overlaps run B of chapter k.

Unit components — Specialised modules for the processing steps between model output and delivery: normalisation (format repair), validator (schema, block contracts, didactic checks), terminology (term register and candidate verification), term marking (glossary tooltips), degradation (demotion of defective blocks) and assembler (composition into a single file).

Persistence — Every job has a directory holding a state file, the unit JSON, checkpoint artefacts, chapter scripts, term registers and the technical report. An SQLite register tracks job numbers. Resumption is fine-grained: the output of individual text sections and every finished lesson are saved as well.

External endpoints — Two OpenAI-compatible language model endpoints for the model roles, optionally an embedder and a reranker endpoint. Without an embedder the material is not inventorised; without a reranker, retrieval yields a ranking without a relevance decision — both are cleanly omitted rather than substituted.

Data flow

The user interacts solely with the UI layer. Step 1 reads uploaded files, derives a learning profile via the fast model and stores the full text in the job folder. If an embedder is configured, the material is segmented and embedded.

Step 2 uses the strong model to produce the concept inventory with treatment classes and the chapter plan, then the concept graph with introduction sites and prerequisites. Where an index exists, coverage analysis follows, mapping supporting passages to each concept.

Step 3 presents both as editable tables. On release the interface hands over to job management, which starts a server-side task.

In step 4 each chapter goes through two runs. Run A produces prose: a cross-reference task collects the binding terminology, then one task writes per concept, and a finalize task assembles the chapter script. Run B converts the text into blocks, one task per lesson, followed by the exercise section and the chapter summary. An enrichment pass then runs per lesson, returning nothing but new building blocks with insertion positions.

During consolidation the final test and the critic run in parallel, followed by fact checking and the redundancy pass. Step 5 performs normalisation, validation, degradation and assembly, and delivers the single file.

Normalisation, validation and terminology control act across the process after each generating phase without sitting in the main data flow.

AI components in the workflow

Three classes of AI component interact, embedded in a rule-based orchestration:

Language models in two roles — A strong model handles planning, the concept graph, assembly, the load-bearing concepts, the exercise section and the critic; a fast model handles format-oriented, volume-intensive work, in particular block generation. The assignment is recorded per task in the execution graph. Responses under a JSON contract are validated against a schema; on error a repair loop follows with the findings fed back.

Embedder and reranker — The material is segmented into typed units and embedded. To map concepts to supporting passages, a cosine pre-selection filters broadly and the reranker makes the relevance decision against a threshold. Its score is comparable across queries because query and document are scored jointly; a failure reports "no statement possible" rather than a substitute ordering.

Deterministic verification layer — Deliberately not an AI component. Schema, block contracts, quiz logic, data consistency, interaction density and format discipline are decided without a model call. Node-based probes check simulator code, Mermaid syntax and LaTeX conversion against the very library versions later embedded in the unit.

Concurrency and robustness

Production runs in a server-side task, independent of the browser session. Within a chapter a semaphore bounds the tasks running in parallel; chapters are executed interleaved.

Failures are graded rather than absolute: truncated JSON responses are closed and the incomplete final element discarded. A failed detailed plan yields, after three attempts, a fallback plan derived from the concept inventory. A lesson still unreadable after a retry is reported as a loss at the final gate rather than silently missing. An undisplayable building block is replaced by its description as text.

One particularity concerns model invocation: where response_format enforces valid JSON, guided decoding applies. A thinking model then cannot emit its reasoning tokens and returns nothing once the budget is exhausted. The client therefore disables thinking in JSON mode by default and retries an empty response exactly once without thinking.

Configuration and deployment

All endpoints, model names, budgets, concurrency settings and limits are set via a .env file or environment variables; there are no command-line arguments. Configurable items include base URL, model, model family, thinking behaviour, token budget, temperature, timeout and concurrency per model role, the budgets of the block phase, and the embedder and reranker endpoints.

The application starts as a Docker container based on Python 3.12-slim, which additionally contains Node.js for the verification probes. At build time the renderer libraries are fetched into the image; if that fails the application still runs and reports the shortfall as a warning. A volume for the working directory is mandatory — it holds the job register and all job folders, on which resumption depends. An nginx reverse proxy sits in front with a path prefix and generous timeouts, since individual model calls can run long.

Technology overview

  • UI: Gradio 6
  • Runtime: Python 3.12, asyncio
  • LLM access: openai (async), OpenAI-compatible endpoints
  • HTTP client: httpx for embedder and reranker
  • Schema validation: jsonschema
  • Document import: pdfminer.six, python-docx, stdlib zipfile
  • Document export: python-docx
  • Persistence: SQLite, JSON files in the job folder
  • Verification probes: Node.js with katex, mermaid, jsdom, dompurify (build time only)
  • Embedded renderers: Chart.js 4, Mermaid 11, Vega/Vega-Lite/Vega-Embed
  • Output format: single-file HTML with MathML and SVG
  • Deployment: Docker behind nginx