Files
creator2/DESIGN.md
2026-07-13 01:58:54 +02:00

5.6 KiB
Raw Blame History

Design creator2

Beschlossen am 2026-07-09 (Diskussion Nutzer + Claude). Ersetzt ../creator.

Warum Neubau

Der Vorgänger gruppierte nach Entitäts-Ähnlichkeit (Clustering → Naming → Umbrella → Dedup → Degradier-Pass). Der Guide las sich als Aneinanderreihung von Bausteinen. Viele Fixes waren Symptomreparatur an dieser Kerneinheit. creator2 wechselt das Kriterium: gruppiert wird nach „lernt sich gut zusammen" (Backward Design), nicht nach „ist dieselbe Entität".

Pipeline

E0 Korpus     Themen: N Recherche-Sweeps (Curricula/Lehrbuch/Syllabus/Übungen) → Snapshots
              Uni:    Dateien aus topics/<name>/ (txt/md/pdf) → Snapshots
              Soll-Extraktion je Quelle → Konsens (Themen: Punkt braucht ≥2 unabhängige
              Quellen; uni: 1 Beleg genügt — Korpus ist vertrauenswürdig, Zitat-Gate
              fängt Halluzinationen)
              Themen: Runden bis Sättigung (Runde ohne neuen Soll-Punkt) → Auto-Freeze
E1 Inventar   Abschnitte (~12k Zeichen) → 2 Reader je Abschnitt → Atome mit Verbatim-Anker
              Dedup: Anker-Overlap (auto) → Embedding-Kandidaten → 2er-Panel (einstimmig)
              Soll-Zuordnung je Atom; Soll-Punkt ohne Atom → gezielte Nachextraktion
E2 Artefakte  je Soll-Punkt-Gruppe: Flashcards + 1 typisiertes Beispiel pro Atom
              (Form: text|mathe|code|tabelle, beste Passung) → Form-Gate
              (Syntax/Struktur parse-only, kein Ausführen) → Verify-Panel gegen Anker → Fix
E3 Struktur   Lernziele+Zuordnung aus Atomen (je Soll-Punkt) → Ziel-Check → Kanten auflösen
              → Zyklen brechen (Judge) → Bausteine = Ziel-Gruppen im Band (split/merge)
              → topologische Ordnung (Bausteine + Atome darin)
E4 Guide      je Baustein: Writer (Facts inline, Atom-Marker; Ausgabe DELIMITED, nicht JSON
              — LaTeX-Backslashes) → det. Checks → Prüfer → Fix (Fix-Cap gegen Churn).
              Beispiel-Marker setzt der Code DETERMINISTISCH (nicht der Writer);
              Assembly tauscht Marker gegen ```-Fence/Tabelle.

Jede Ebene endet mit qa.messen(ebene); auto_loop fährt QA→Repair bis Note 10,0, Stillstand oder 10 Iterationen. Erst dann startet die nächste Ebene.

Datenmodell (SQLite, backend/db.py)

  • topics(name, titel, art thema|uni, status, provider)
  • runs(id, topic, status running|paused|done|failed|budget, gestartet, beendet, git_hash, git_dirty, budget_tokens, grund)
  • events(run_id, ts, ebene, stage, item, template, template_hash, provider, model, role, status, dur_ms, wait_ms, tok_in, tok_out, tok_cache_read, tok_cache_write, meta) — Ledger, append-only
  • quellen(id, topic, art web|datei, titel, url, snapshot, hash, runde, status)
  • soll(id, topic, punkt, status kandidat|bestaetigt, belege JSON [{quelle,zitat}])
  • atome(id, topic, titel, typ, definition, level, status, soll_id, ziel_id, baustein_id, ord, merged_into)
  • anker(atom_id, quelle_id, start, ende, zitat)
  • kanten(topic, von_atom, zu_atom, art braucht|verwandt, status)
  • artefakte(id, atom_id, typ flashcard|beispiel, inhalt JSON, status kandidat|verifiziert|verworfen) — beispiel-inhalt trägt form + formspezifische Felder (text|code+sprache|tabelle); code/tabelle kommen verbatim via <!-- beispiel: id --> in den Guide (Assembly-Swap)
  • lernziele(id, topic, text, soll_id, status)
  • bausteine(id, topic, ziel_id, titel, ord, status)
  • sections(baustein_id, stage, text_kompakt, text_lang, befunde JSON)
  • leitner(artefakt_id, box, faellig, historie)
  • befunde(run_id, ebene, art, item, detail, status offen|repariert|freigesprochen)

Alles status-basiert → Resume = Lauf neu starten, fertige Items werden übersprungen.

QA (backend/qa.py)

Invarianten (deterministisch, gated):

  • E0: jeder bestätigte Soll-Punkt hat ≥2 Belege aus verschiedenen Quellen; Korpus nicht leer
  • E1: jedes Atom hat Anker (Zitat verbatim in Quelle gefunden), Definition, Typ, genau einen Soll-Punkt; jeder Soll-Punkt ≥1 Atom
  • E2: jedes Atom ≥1 verifizierte Flashcard; Beispiel-Status entschieden
  • E3: Partition (jedes Atom genau ein Baustein via Ziel), Bandgröße, DAG azyklisch, keine Kante von spätem zu frühem Baustein
  • E4: jeder Atom-Marker vorhanden, Ziel-Anker im Text, Längenband, keine Vorwärtsverweise (Titel eines späteren Atoms fällt nicht früher)

LLM-Stichproben (nur wo nötig, immer 2 unabhängige Bestätiger): fachlich-falsch im Guide.

Note = 10 · (1 gewichtete Befundquote); 10,0 nur bei null offenen Befunden.

Nebenläufigkeit

Einfache Wellen (asyncio.gather + Semaphoren in agents.py), keine Streaming-Engine. Innerhalb einer Ebene laufen unabhängige KETTEN (gen→verify je Chunk/Baustein) parallel; Stage-Barrieren nur, wo ein Schritt global rechnet (Dedup, Level, Ordnung, Konsens). Panels = n parallele Calls + Konsensregel. Hedge: Slot ohne Ergebnis nach max(90 s, timeout/2) bekommt einen Zwilling, erstes valides Ergebnis gewinnt. Live-Board trotzdem: jeder Statuswechsel → WebSocket-Broadcast.

Provider

Wie Vorgänger: claude-CLI, opencode (MiniMax), MiniMax-Text-API direkt (tool-lose Calls). Rollen quick|judge|guide|fast je Provider-Stack, Routing via env (ROLE_JUDGE=claude). CREATOR_FAKE_AGENTS=1 → fake_agents.py.

Frontend (Vue 3 + Vite)

Tabs: Board (Spalten = Ebenen, ALLE Karten, scrollbar, live via WS) · Guide (marked+KaTeX+highlight, Level-Filter) · Üben (Leitner-Boxen) · Kennzahlen (Tokens/Zeit je Ebene/Stage/Template aus dem Ledger).

Bewusst gestrichen

Delta-Läufe (Material vollständig), Abnahme-Benchmark, Projekt-/Link-Quellen, Chat/Prüfungs-Features, ELO/Stufen-Ansichten (Level-Feld existiert, Ansichten später).