2026-06-15 12:13:15 +02:00
# Planungs-KI — Katalog-Prompt-Slots (Snippets)
2026-06-13 07:55:47 +02:00
**Stand:** 2026-05-22
2026-06-15 12:13:15 +02:00
**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`
2026-06-13 07:55:47 +02:00
---
## 1. Problem
2026-06-15 12:13:15 +02:00
Seit **F13 (0.8.233)** fließen Primärfokus, Trainingsstil, Zielgruppe und Stilrichtung als `planning_catalog_context` in **Retrieval und Scoring** .
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
Die **LLM-Prompts** brauchen zusätzlich **fachliche Textbausteine** pro gewähltem Katalog-Eintrag — editierbar, ohne Code-Deploy, unabhängig von fest codierten Katalog-Namen.
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
**Ziel:** Prompts in `ai_prompts` referenzieren **Slot-Typen** (Vokabular). Inhalte hängen an **Katalog-Zeilen** (Stammdaten). Der Resolver füllt Platzhalter zur Laufzeit.
2026-06-13 07:55:47 +02:00
---
2026-06-15 12:13:15 +02:00
## 2. Zwei Ebenen (Kern des Modells)
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
| 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 …“ |
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
**Nicht:** feste Attribute pro Eintrag im Code (`planning_lens`, `qa_criteria` …).
**Sondern:** beliebig viele Katalog-Einträge × definierte Slot-Typen.
2026-06-13 07:55:47 +02:00
---
2026-06-15 12:13:15 +02:00
## 3. Dimensionen & Priorität
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
| 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` |
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
**Kaskade:** Bei widersprüchlichen Hinweisen gilt Fokus → Trainingsstil → Zielgruppe → Stilrichtung.
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
Pro Dimension im Request: **ein aktiver Eintrag** (`is_primary`, sonst höchstes `weight` ).
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
---
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
## 4. Slot-Typ-Register (Vokabular)
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
Definiert in ** `catalog_prompt_slot_types` ** (DB) + Spiegel in `catalog_prompt_slots.py` .
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
| `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) |
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
**Erweiterung:** neuer Slot-Typ = eine Zeile in `catalog_prompt_slot_types` + Resolver/Admin-Katalog — **kein** neues Python-Feld pro Eintrag.
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
**Fallback `description` :** Wenn kein Slot-Wert gesetzt → `focus_areas.description` (bzw. `description` -Spalte der jeweiligen Katalog-Tabelle).
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
---
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
## 5. Platzhalter in `ai_prompts`
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
Mustache-Keys: ** `{catalog_kind}_{slot_key}` ** (nur `[a-z0-9_]` ).
2026-06-13 07:55:47 +02:00
| Platzhalter | Bedeutung |
|-------------|-----------|
2026-06-15 12:13:15 +02:00
| `{{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.
2026-06-13 07:55:47 +02:00
---
2026-06-15 12:13:15 +02:00
## 6. Speicherung (DB)
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
### 6.1 `catalog_prompt_slot_types`
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
Metadaten je Slot-Typ (`slot_key`, `display_name` , `description` , `applicable_kinds[]` , `sort_order` , `for_llm` , `for_code` ).
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
### 6.2 `catalog_prompt_slots`
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
```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)
```
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
Neuer Katalog-Eintrag im Admin → **keine** Code-Änderung; Slots optional befüllen.
2026-06-13 07:55:47 +02:00
2026-06-18 11:22:33 +02:00
**Keine Migrations-Seeds:** Primärfokus und andere Stammdaten sind pro Umgebung unterschiedlich. Leere `catalog_prompt_slots` sind normal; zur Laufzeit greifen Namens-Fallbacks (`catalog_slot_fallbacks.py`) und die `description` -Spalte der Stammdaten.
2026-06-13 07:55:47 +02:00
---
2026-06-15 12:13:15 +02:00
## 7. Laufzeit-Architektur
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
```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)
```
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
**Module:**
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
| 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) |
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
---
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
## 8. Admin-API
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
| 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) |
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
`kind` : `focus_area` · `training_type` · `target_group` · `style_direction`
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
**Später:** UI-Tabs am Katalog-Editor; Versionierung/Audit wie `ai_prompts` .
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
---
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
## 9. Rollout-Phasen
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
### H1 — Bootstrap (0.8.234) ✓
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
Hardcodierte `SNIPPET_REGISTRY` — Proof of Concept für `catalog_guidance_block` .
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
### H2 — Slot-Modell (0.8.235) ✓
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
- [x] Tabellen `catalog_prompt_slot_types` , `catalog_prompt_slots`
2026-06-18 11:22:33 +02:00
- [x] Seed aus H1-Texten (Name-Match auf Stammdaten) — **entfernt (095)** : keine Migrations-Seeds; Inhalte Admin oder `catalog_slot_fallbacks.py`
2026-06-15 12:13:15 +02:00
- [x] Resolver mit granularen Platzhaltern + Aggregat
- [x] Admin-API GET/PUT
- [x] `SNIPPET_REGISTRY` aus Laufzeit-Pfad entfernt
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
### H2.1 — Admin-UI
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
- [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)
2026-06-13 07:55:47 +02:00
### H1.5
2026-06-15 12:13:15 +02:00
- [ ] `rematch_guard` im Rematch-Loop
- [ ] Intent-Prompts + Gap-Fill: `hints_on_exercise`
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
### H3 — Trainingsplanung (Phase G)
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
- [ ] Gleicher Resolver, andere Orchestratoren
2026-06-13 07:55:47 +02:00
---
2026-06-15 12:13:15 +02:00
## 10. Tests & Akzeptanz
2026-06-13 07:55:47 +02:00
| Test | Erwartung |
|------|-----------|
2026-06-15 12:13:15 +02:00
| 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 |
2026-06-13 07:55:47 +02:00
---
2026-06-15 12:13:15 +02:00
## 11. Abgrenzung
2026-06-13 07:55:47 +02:00
2026-06-15 12:13:15 +02:00
| 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 |
2026-06-13 07:55:47 +02:00
---
2026-06-15 12:13:15 +02:00
## 12. Changelog
2026-06-13 07:55:47 +02:00
| Datum | Änderung |
|-------|----------|
2026-06-15 12:13:15 +02:00
| 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 |