- Added new planning AI functionality with the introduction of the `suggestPlanningExercises` API endpoint for context-based exercise suggestions. - Enhanced `ExercisePickerModal` to utilize planning context, allowing for a more tailored exercise selection experience. - Updated `TrainingUnitEditPage` to pass planning context to the exercise picker, improving integration with the new planning features. - Incremented application version to 0.8.167 and updated changelog to reflect the new planning AI capabilities and related enhancements.
6.4 KiB
Planungs-KI: Übungssuche & Kontext für Neu-Anlage
Version: 0.1
Datum: 2026-05-22
Status: P0 in Umsetzung (Hybrid-Retrieval ohne LLM-Intent)
Bezüge: AI_PLANNING_KI_MULTISTAGE_FORECAST.md · AI_PROMPT_TARGET_ARCHITECTURE.md · SKILL_SCORING_SPEC.md · TRAINING_FRAMEWORK_SPEC.md §3 (Progressionsgraph)
1. Ziel
Trainer in der Trainingsplanung sollen Übungen finden oder anlegen können mit natürlichen Anfragen wie:
- „Vertiefung zu Übung XY“
- „Nächste sinnvolle Übung im Progressionsgraph Z“
- „Baut auf der bisherigen Planung auf — Reaktionsschnelligkeit mit Partnern“
- Preset: „Schlage mir die nächste Übung vor“
Suche (Bibliothek) und Neu mit KI-Assistent (Anlage) nutzen dasselbe PlanningExerciseContextPack — unterschiedliches Ergebnis (Treffer vs. Entwurf).
2. Architektur (Mehrstufig)
| Stufe | Name | Technik | P0 |
|---|---|---|---|
| S0 | Kontext-Pack | SQL/API, deterministisch | ✅ |
| S1a | Intent strukturieren | Optional LLM planning_exercise_search_intent |
Heuristik |
| S1b | Hybrid-Retrieval | Score: Volltext + Graph + Skills + Plan | ✅ |
| S1c | Rerank + Begründung | Optional LLM planning_exercise_search_rank |
Regelbasierte reasons[] |
| S2 | Neu-Anlage | Bestehende suggestExerciseAi + Pack als Zusatzkontext |
Später |
Zwischen jeder Stufe: nur erlaubte exercise_ids (Governance / Sichtbarkeit).
3. Intent-Typen
intent_hint |
Bedeutung | Retrieval-Gewichtung (P0) |
|---|---|---|
suggest_next |
Nächste Übung (Default bei leerer/kurzer Query) | Progression + Skill-Overlap + Plan-Kontinuität |
progression_next |
Explizit Graph-Folge | Progression hoch |
deepen_exercise |
Vertiefung zu Anker-Übung | Skill-Overlap hoch, ähnlicher Fokus |
continue_plan_goal |
Auf bisherigen Plan aufbauen | Plan-Kontinuität, Wiederholungsstrafe |
free_search |
Freitext / Stichwort | Volltext hoch |
S1a (später): Freitext → JSON { intent, skill_hints[], requires_partner, level_hint, … } validiert per Pydantic.
P0: intent_hint vom Client oder Keyword-Heuristik auf query.
4. PlanningExerciseContextPack (S0)
Serverseitig aus Request + DB (tokenbewusst für spätere LLM-Stufen):
| Feld | Quelle | UI-Chip |
|---|---|---|
unit_id, Titel, group_id, Gruppenname |
training_units + training_groups |
Gruppe · Einheit |
section_order_index, Abschnittstitel |
training_unit_sections |
Abschnitt |
planned_exercise_ids[] |
Items der Einheit (Reihenfolge) | „N Übungen im Plan“ |
anchor_exercise_id, Titel |
Request oder letzte Übung vor Einfügepunkt | Anker |
anchor_skill_ids[] |
exercise_skills |
(intern) |
progression_graph_id |
Request (optional) | Graph |
progression_successor_ids[] |
exercise_progression_edges ab Anker |
(intern) |
group_recent_exercise_ids[] |
Letzte Einheiten derselben Gruppe | Wiederholungsstrafe |
framework_slot_notes |
Rahmen-Slot falls framework_slot_id |
(später) |
Berechtigung: get_tenant_context + _assert_training_unit_permission wie GET /training-units/{id}.
5. Hybrid-Retrieval (S1b, P0)
Kandidaten: sichtbare Übungen (library_content_visibility_sql), ohne archived, max. ~400 (recent).
Score (0–1, gewichtet nach Intent):
score = w_ft * fulltext_rank
+ w_prog * progression_hit
+ w_skill * skill_jaccard(anchor, candidate)
+ w_plan * plan_affinity
+ w_repeat * (candidate in unit_plan ? -1 : 0)
+ w_group_repeat * (candidate in group_recent ? -0.5 : 0)
reasons[] (regelbasiert, Deutsch): z. B. „Nachfolger im Progressionsgraph“, „Fähigkeiten passen zur Anker-Übung“, „Volltext-Treffer“.
6. API
POST /api/planning/exercise-suggest
Body:
{
"unit_id": 123,
"section_order_index": 0,
"phase_order_index": null,
"parallel_stream_order_index": null,
"anchor_exercise_id": 456,
"progression_graph_id": 7,
"query": "Schlage mir die nächste Übung vor",
"intent_hint": "suggest_next",
"limit": 20,
"exercise_kind_any": ["simple"]
}
Response:
{
"context_summary": {
"unit_title": "…",
"group_name": "…",
"section_title": "Hauptteil",
"planned_count": 4,
"anchor_title": "Partner-Fangspiel"
},
"intent_resolved": "suggest_next",
"hits": [
{
"id": 99,
"title": "…",
"summary": "…",
"score": 0.78,
"reasons": ["Nachfolger im Progressionsgraph", "3 gemeinsame Fähigkeiten mit Anker-Übung"],
"focus_area": "…"
}
]
}
Modul: backend/planning_exercise_suggest.py · Router backend/routers/planning_exercise_suggest.py
7. Frontend
| Ort | Verhalten |
|---|---|
ExercisePickerModal |
Prop planningContext → Planungs-API statt reiner listExercises; Kontext-Chips; reasons unter Treffer |
TrainingUnitEditPage |
planningContext aus Einheit + Picker-Ziel (Anker = letzte Übung im Abschnitt) |
| Rahmen / Kombi-Formular | analog, sobald unit_id / Slot-Blueprint bekannt |
| Übungsliste | weiter Volltext; Schalter „Neu mit KI-Assistent“ ohne Planungs-Pack |
Zweites Suchfeld im Picker: Query = Volltext + ergänzender Begriff (ODER in P0 als Konkatenation an Backend).
8. Neu-Anlage (Anbindung, Phase P1)
Wenn hits leer oder Trainer wählt „Mit KI anlegen“:
- Gleiches
context_summaryansuggestExerciseAianhängen (Felderplanning_context_jsono. ä. — noch offen) - Kurzbeschreibung optional leer (freier Vorschlag) oder aus Intent/Skizze
9. Phasen-Roadmap
| Phase | Inhalt |
|---|---|
| P0 ✅ | Context-Pack, Hybrid-Score, API, Picker in Planung |
| P1 | LLM Intent-JSON; Neu-Anlage mit Pack |
| P2 | LLM-Rerank + Kurzbegründung |
| P3 | Skill-Discovery / Framework-Ziele im Pack |
10. Changelog
- 2026-05-22: Erstfassung; P0 API + Planungs-Picker.
- 2026-05-22: P0 implementiert (
planning_exercise_suggest.py, Router, Picker); unsaved Formular-Plan noch nicht an API (nur persistierte Einheit).
11. Bekannte P0-Lücken
- Ungespeicherte Plan-Änderungen: API liest DB-Stand der Einheit — offene Formular-Items folgen in P0.1 (Client übergibt
planned_exercise_ids[]). - Progressionsgraph-ID: noch nicht aus UI wählbar (
progression_graph_idnur per API). - LLM-Intent / Rerank: P1/P2 laut Roadmap §9.