# Planungs-KI — Katalog-Prompt-Slots (Snippets) **Stand:** 2026-05-22 **Status:** **H2** umgesetzt (0.8.235) · **H2.1** Admin-UI + granulare Prompts (0.8.236) **Bezüge:** `PLANNING_PROGRESSION_GRAPH_KI.md` §4.4 · `AI_PROMPT_TARGET_ARCHITECTURE.md` §2.4 · `planning_catalog_context.py` · `catalog_prompt_slots.py` --- ## 1. Problem Seit **F13 (0.8.233)** fließen Primärfokus, Trainingsstil, Zielgruppe und Stilrichtung als `planning_catalog_context` in **Retrieval und Scoring**. Die **LLM-Prompts** brauchen zusätzlich **fachliche Textbausteine** pro gewähltem Katalog-Eintrag — editierbar, ohne Code-Deploy, unabhängig von fest codierten Katalog-Namen. **Ziel:** Prompts in `ai_prompts` referenzieren **Slot-Typen** (Vokabular). Inhalte hängen an **Katalog-Zeilen** (Stammdaten). Der Resolver füllt Platzhalter zur Laufzeit. --- ## 2. Zwei Ebenen (Kern des Modells) | Ebene | Was | Wer pflegt | Beispiel | |-------|-----|------------|----------| | **Slot-Typ** | Art des Textes (festes, erweiterbares Vokabular) | Produkt / Architektur | `hints_on_progression`, `hints_on_path_qa` | | **Slot-Wert** | Konkreter Text pro Katalog-Eintrag | Admin / Redakteur | Gewaltschutz → `hints_on_path_qa`: „Lücken = fehlende Deeskalation …“ | **Nicht:** feste Attribute pro Eintrag im Code (`planning_lens`, `qa_criteria` …). **Sondern:** beliebig viele Katalog-Einträge × definierte Slot-Typen. --- ## 3. Dimensionen & Priorität | Rang | Dimension | `catalog_kind` | DB-Tabelle | |------|-----------|----------------|------------| | **1** | Primärfokus | `focus_area` | `focus_areas` | | **2** | Trainingsstil | `training_type` | `training_types` | | **3** | Zielgruppe | `target_group` | `target_groups` | | **4** | Stilrichtung | `style_direction` | `style_directions` | **Kaskade:** Bei widersprüchlichen Hinweisen gilt Fokus → Trainingsstil → Zielgruppe → Stilrichtung. Pro Dimension im Request: **ein aktiver Eintrag** (`is_primary`, sonst höchstes `weight`). --- ## 4. Slot-Typ-Register (Vokabular) Definiert in **`catalog_prompt_slot_types`** (DB) + Spiegel in `catalog_prompt_slots.py`. | `slot_key` | Anzeige (DE) | LLM-Prompt | Code-only | |------------|--------------|------------|-----------| | `description` | Allgemeine Beschreibung | Roadmap, Goal-Analyse, Start/Ziel | — | | `hints_on_progression` | Hinweise Progressionsgraph / Stufen | Roadmap, Stage-Spec | — | | `hints_on_path_qa` | Bewertungsmaßstäbe Pfad-QS | Path-QA | — | | `hints_on_exercise` | Hinweise Übungsanlage / Gap-Fill | Exercise-AI, Suggest (später) | — | | `anti_patterns` | Explizit vermeiden (Fehlbewertung) | Path-QA, Stage-Spec | — | | `rematch_guard` | Kein Auto-Rematch erzwingen | — | Rematch-Loop (H1.5) | **Erweiterung:** neuer Slot-Typ = eine Zeile in `catalog_prompt_slot_types` + Resolver/Admin-Katalog — **kein** neues Python-Feld pro Eintrag. **Fallback `description`:** Wenn kein Slot-Wert gesetzt → `focus_areas.description` (bzw. `description`-Spalte der jeweiligen Katalog-Tabelle). --- ## 5. Platzhalter in `ai_prompts` Mustache-Keys: **`{catalog_kind}_{slot_key}`** (nur `[a-z0-9_]`). | Platzhalter | Bedeutung | |-------------|-----------| | `{{focus_area_description}}` | Aktiver Primärfokus — Beschreibung | | `{{focus_area_hints_on_progression}}` | … — Progressions-Hinweise | | `{{focus_area_hints_on_path_qa}}` | … — QS-Hinweise | | `{{focus_area_hints_on_exercise}}` | … — Übungsanlage | | `{{focus_area_anti_patterns}}` | … — Anti-Patterns | | `{{training_type_description}}` | Aktiver Trainingsstil — … | | `{{training_type_hints_on_progression}}` | … | | `{{target_group_hints_on_path_qa}}` | Aktive Zielgruppe — … | | `{{style_direction_hints_on_progression}}` | Aktive Stilrichtung — … | | *(analog für alle Slot-Typen × Dimension)* | | | `{{catalog_guidance_block}}` | **Aggregat** (Abwärtskompatibel): kaskadierter Markdown-Block aus aktiven Slots | | `{{catalog_context_json}}` | Audit: IDs, Namen, gesetzte Slot-Keys | | `{{has_catalog_guidance}}` | `"true"` oder leer | **Hinweis:** `prompt_resolver` unterstützt **keine** `{{#if}}`-Blöcke — leere Slots = leerer String. ### 5.1 Prompt-Profile (welche Slots im Aggregat) | Prompt-Slug | Aggregat enthält primär | |-------------|-------------------------| | `planning_exercise_path_qa` | `*_hints_on_path_qa`, `*_anti_patterns`, `*_description` | | `planning_progression_roadmap` | `*_description`, `*_hints_on_progression`, `*_anti_patterns` | | `planning_progression_stage_spec` | `*_hints_on_progression`, `*_anti_patterns` | | `planning_progression_goal_analysis` | `*_description` | Feinsteuerung: im Admin-Template **granulare** Platzhalter nutzen; Aggregat optional. --- ## 6. Speicherung (DB) ### 6.1 `catalog_prompt_slot_types` Metadaten je Slot-Typ (`slot_key`, `display_name`, `description`, `applicable_kinds[]`, `sort_order`, `for_llm`, `for_code`). ### 6.2 `catalog_prompt_slots` ```text catalog_kind — focus_area | training_type | target_group | style_direction catalog_id — FK auf jeweilige Stammtabelle (logisch, kein polymorpher FK) slot_key — FK → catalog_prompt_slot_types content — TEXT (Markdown/Plain für LLM) UNIQUE (catalog_kind, catalog_id, slot_key) ``` Neuer Katalog-Eintrag im Admin → **keine** Code-Änderung; Slots optional befüllen. --- ## 7. Laufzeit-Architektur ```text planning_catalog_context (Request / Graph-Artefakt) ↓ catalog_prompt_slots.resolve_catalog_prompt_variables(cur, catalog, slug?) ↓ planning_prompt_variables.merge_planning_prompt_variables(...) ↓ load_and_render_ai_prompt (ai_prompts Template) ``` **Module:** | Modul | Rolle | |-------|--------| | `catalog_prompt_slots.py` | Slot-Typen, DB-Lese/Schreib, Resolver, Aggregat-Block | | `planning_prompt_variables.py` | Zentrale Provider-Liste (erweiterbar) | | `planning_catalog_prompt_snippets.py` | Deprecated Re-Exports (Tests/Kompatibilität) | --- ## 8. Admin-API | Methode | Pfad | Beschreibung | |---------|------|--------------| | GET | `/api/catalog-prompt-slot-types` | Slot-Typ-Register | | GET | `/api/catalog-prompt-slots/{kind}/{catalog_id}` | Alle Slots eines Eintrags | | PUT | `/api/catalog-prompt-slots/{kind}/{catalog_id}` | Slots upserten (Admin) | `kind`: `focus_area` · `training_type` · `target_group` · `style_direction` **Später:** UI-Tabs am Katalog-Editor; Versionierung/Audit wie `ai_prompts`. --- ## 9. Rollout-Phasen ### H1 — Bootstrap (0.8.234) ✓ Hardcodierte `SNIPPET_REGISTRY` — Proof of Concept für `catalog_guidance_block`. ### H2 — Slot-Modell (0.8.235) ✓ - [x] Tabellen `catalog_prompt_slot_types`, `catalog_prompt_slots` - [x] Seed aus H1-Texten (Name-Match auf Stammdaten) - [x] Resolver mit granularen Platzhaltern + Aggregat - [x] Admin-API GET/PUT - [x] `SNIPPET_REGISTRY` aus Laufzeit-Pfad entfernt ### H2.1 — Admin-UI - [x] Slot-Editor an Fokusbereich / Trainingsstil / Zielgruppe / Stilrichtung (`CatalogPromptSlotsEditor`, Stammdaten-Katalog) - [x] Prompt-Templates mit granularen Platzhaltern (Migration 093) - [ ] Platzhalter-Hilfe im KI-Prompt-Editor (erweitert) ### H1.5 - [ ] `rematch_guard` im Rematch-Loop - [ ] Intent-Prompts + Gap-Fill: `hints_on_exercise` ### H3 — Trainingsplanung (Phase G) - [ ] Gleicher Resolver, andere Orchestratoren --- ## 10. Tests & Akzeptanz | Test | Erwartung | |------|-----------| | Slot aus DB | Gewaltschutz + `hints_on_path_qa` → Platzhalter enthält Deeskalation | | Ohne Katalog | Alle `{{focus_area_*}}` leer; `has_catalog_guidance` leer | | Neuer Eintrag | Leere Slots, kein Crash; `description`-Fallback aus Stammdaten | | Priorität | Aggregat: Primärfokus vor Trainingsstil | --- ## 11. Abgrenzung | Thema | Hinweis | |-------|---------| | Retrieval-Gewichte | `merge_catalog_context_into_target` — unverändert | | Technik-Gates | `planning_exercise_semantics` — unverändert | | Prompt-Text | `ai_prompts` — editierbar, referenziert Slot-Platzhalter | --- ## 12. Changelog | Datum | Änderung | |-------|----------| | 2026-05-22 | **H2.1** (0.8.236): Admin-UI `CatalogPromptSlotsEditor`; Migration 093 granulare Prompt-Templates | | 2026-05-22 | **H2** (0.8.235): Slot-Typ-Register + `catalog_prompt_slots` DB, granulare Platzhalter, Admin-API | | 2026-05-22 | Konzept §4–§8: zwei Ebenen Slot-Typ vs. Slot-Wert; Platzhalter `{kind}_{slot_key}` | | 2026-05-22 | H1 (0.8.234): Bootstrap-Registry — durch H2 ersetzt | | 2026-05-22 | Erstfassung |