shinkan-jinkendo/.claude/docs/technical/KI_FEATURES_SPEC.md
Lars 294b09a5d9
All checks were successful
Deploy Development / deploy (push) Successful in 41s
Test Suite / pytest-backend (push) Successful in 38s
Test Suite / lint-backend (push) Successful in 1s
Test Suite / build-frontend (push) Successful in 12s
Test Suite / k6 /health Baseline (push) Successful in 34s
Test Suite / playwright-tests (push) Successful in 1m13s
Implement AI Skill Retrieval Profiles and Enhance Exercise AI Functionality
- Introduced migration 068 for `ai_skill_retrieval_profiles`, enabling configurable weights and quotes for skill catalog prioritization in exercise AI suggestions.
- Updated the `POST /api/exercises/ai/suggest` endpoint to include an optional `focus_areas_context` field, allowing for enhanced context in AI-generated suggestions.
- Enhanced the `exercise_ai` module to utilize context-based skill selection, incorporating scoring, category caps, and keyword patches for improved AI responses.
- Updated the ExerciseFormPageRoot component to pass focus area context to the AI suggestion API, streamlining user interaction with AI-generated content.
- Incremented version numbers in `backend/version.py` to reflect the latest changes and ensure accurate tracking in the changelog.
2026-05-22 09:49:08 +02:00

403 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# KI-Funktionen Specification Exercises
**Version:** 1.1
**Datum:** 2026-04-24
**Status:** DRAFT
**Autor:** Claude Code
**Änderungen v1.1:** Prompts sind nicht hardcoded sie werden aus der DB geladen (AI_PROMPT_SYSTEM_SPEC.md)
**Verwandte Specs:** AI_PROMPT_SYSTEM_SPEC.md (Prompt-DB + Platzhalter), SKILLS_MATRIX_SPEC.md (Fähigkeitsmatrix)
**Übergeordnete Produkt-Vision** (breiter Scope: Zielausbau, bereichsweise vs. Gesamtüberarbeitung, Varianten, Planungs-/Nachbereitungskontext, Admin-Masse):
`functional/AI_EXERCISE_ASSISTANT_VISION.md`
---
## 1. Übersicht
KI-gestützte Assistenzfunktionen beim Anlegen und Bearbeiten von Übungen (Mindestpaket dieser Spec):
**Hinweis:** Die beiden folgenden Zeilen entsprechen **P0** der Phasierung in **`AI_EXERCISE_ASSISTANT_VISION.md`**; spätere Funkteile sind dort beschrieben.
| Funktion | Ziel |
|---------|------|
| **KI-Zusammenfassung** | Generiert `summary` aus `goal` + `execution` (für Listen + Trainingspläne) |
| **KI-Skill-Empfehlung** | Schlägt passende Fähigkeiten + Stufen vor (reduziert manuelle Zuordungsarbeit) |
**Abhängigkeit:** OpenRouter API (`OPENROUTER_API_KEY` in `.env`).
Ist der Key nicht gesetzt, sind alle KI-Funktionen deaktiviert Formular funktioniert ohne KI normal.
---
## 2. UX-Prinzip: Manual First, Auto als Fallback
```
Trainer gibt goal + execution ein
├─► [KI-Vorschlag]-Button sichtbar
│ │
│ ▼ (Klick)
│ KI generiert sofort Vorschlag
│ → Trainer sieht Vorschlag inline
│ → Kann akzeptieren / bearbeiten / ablehnen
└─► Kein Klick bis zum Speichern?
▼ (automatisch beim POST/PUT)
KI läuft im Hintergrund
→ summary + skill_suggestions werden gesetzt
→ Trainer kann danach noch bearbeiten
```
**Regel:** Manuell generierte Werte (wo Trainer aktiv bestätigt hat) werden
beim Auto-Fallback NICHT überschrieben. Auto-generierte Werte werden als
`ai_generated: true` markiert und können jederzeit neu generiert oder überschrieben werden.
---
## 3. KI-Zusammenfassung (`summary`)
### 3.1 Was wird generiert
Aus `title` + `goal` + `execution` generiert die KI eine **kurze Zusammenfassung**
(2-4 Sätze, max. 200 Zeichen) für:
- Übungslisten (Karten-Ansicht)
- Trainingsplan-Darstellung (kompakte Anzeige)
- Export-Berichte
### 3.2 Prompt-Logik (Backend)
**Prompt ist NICHT hardcoded** er wird aus der `ai_prompts` Tabelle geladen
(Slug: `exercise_summary`). Admins können das Template anpassen.
```python
# Aufruf via zentralem AI-Service (siehe AI_PROMPT_SYSTEM_SPEC.md)
result = await ai_service.run_ai_prompt(
slug="exercise_summary",
context_data={"exercise": exercise_data},
db=db,
openrouter_key=settings.openrouter_api_key
)
```
**Default-Template** (in Migration 020 als `default_template` gespeichert):
Siehe `AI_PROMPT_SYSTEM_SPEC.md` §2.1 Prompt `exercise_summary`.
### 3.3 DB-Feld
Kein neues Feld nötig `exercises.summary` nimmt den generierten Text auf.
Zusätzliches Tracking-Feld: `summary_ai_generated BOOLEAN DEFAULT false`
---
## 4. KI-Skill-Empfehlung
### 4.1 Was wird empfohlen
Aus `title` + `goal` + `execution` + Katalog aller verfügbaren Skills empfiehlt die KI:
- **Welche Skills** relevant sind (aus dem bestehenden Skill-Katalog)
- **Erforderliche Stufe** (`required_level`) was der Trainierende mitbringen muss
- **Ziel-Stufe** (`target_level`) was durch regelmäßige Ausführung erreicht wird
- **Intensität** (`intensity`) wie stark diese Fähigkeit trainiert wird
### 4.2 Prompt-Logik (Backend)
**Prompt ist NICHT hardcoded** Slug: `exercise_skill_suggestions`.
Der `{{skills_catalog}}`-Platzhalter wird vom Backend automatisch mit der aktuellen
Skill-Liste aus der DB aufgelöst.
Admins können den Prompt anpassen (z.B. die Anweisung zur Auswahl verschärfen oder
fachliche Hinweise ergänzen). Siehe `AI_PROMPT_SYSTEM_SPEC.md`.
### 4.3 Bestätigungsflow (UX)
```
KI gibt Vorschläge
┌─────────────────────────────────────────┐
│ KI-Vorschläge (3 Fähigkeiten) │
│ ─────────────────────────────────────── │
│ ✓ Distanzgefühl │
│ Voraussetzung: Grundlagen │
│ Ziel: Aufbau · Intensität: Hoch │
│ [✓ Übernehmen] [Stufe ändern ▼] [✕] │
│ ─────────────────────────────────────── │
│ ✓ Reaktionsschnelligkeit │
│ Voraussetzung: Einsteiger │
│ Ziel: Grundlagen · Intensität: Mittel │
│ [✓ Übernehmen] [Stufe ändern ▼] [✕] │
│ ─────────────────────────────────────── │
│ ◦ Gleichgewicht (optional) │
│ Voraussetzung: Grundlagen │
│ Ziel: Grundlagen · Intensität: Niedrig│
│ [✓ Übernehmen] [Stufe ändern ▼] [✕] │
│ ─────────────────────────────────────── │
│ [Alle übernehmen] [Verwerfen] │
└─────────────────────────────────────────┘
```
- Jeder Vorschlag kann **einzeln** übernommen, angepasst oder abgelehnt werden
- „Alle übernehmen" nimmt alle aktuell angezeigten Vorschläge
- Stufen können per Dropdown direkt angepasst werden bevor sie übernommen werden
- Abgelehnte Vorschläge werden nicht gespeichert
---
## 5. API-Endpoints
### 5.1 Endpoints Overview
| Method | Endpoint | Beschreibung |
|--------|----------|--------------|
| POST | `/exercises/ai/suggest` | Vorschläge für neue Übung (vor dem Speichern) |
| POST | `/exercises/{id}/ai/regenerate` | Neu generieren für bestehende Übung |
---
### 5.2 `POST /exercises/ai/suggest`
Liefert KI-Vorschläge auf Basis von Eingabe-Text, **bevor** die Übung gespeichert wurde.
Wird beim Klick auf „KI-Vorschlag" im Formular aufgerufen.
**Required Fields:** mindestens `goal` ODER `execution`
**Optional Skill-Katalogpriorisierung (Stand 068):**
```json
{
"focus_areas_context": [
{ "focus_area_id": 3, "is_primary": true },
{ "focus_area_id": 1, "is_primary": false }
],
"focus_area_hint": "Karate, Kumite…"
}
```
- `focus_areas_context`: IDs aus Stammdatum **Fokusbereiche**; Primär soll zuerst stehen (`is_primary`). Ohne Feld oder leere Liste gilt das DB-Profil **`is_default`** (`ai_skill_retrieval_profiles`).
- `focus_area_hint`: bleibt lesbarer Text für den Prompt (bestehende Prompts).
**Minimal-Beispiel (Mit Fokus für Retrieval):**
```json
{
"title": "Maai - Distanzübung",
"goal": "…",
"execution": "…",
"focus_areas_context": [ { "focus_area_id": 1, "is_primary": true } ]
}
```
**Minimal-Beispiel ( ohne Fokus — nur Texts):**
```json
{
"title": "Maai - Distanzübung",
"goal": "Distanzgefühl entwickeln durch Partnerübungen...",
"execution": "1. Partnerwahl\n2. Ausgangsstellung..."
}
```
**Response:** `200 OK`
```json
{
"summary": {
"text": "Partnerübung zur Entwicklung des Distanzgefühls. Trainiert werden räumliche Wahrnehmung und reaktives Verhalten in der Kumite-Distanz.",
"ai_generated": true,
"model": "anthropic/claude-sonnet-4"
},
"skills": [
{
"skill_id": 10,
"skill_name": "Distanzgefühl",
"skill_category": "Kumite",
"required_level": "grundlagen",
"target_level": "aufbau",
"intensity": "hoch",
"confidence": 0.92
},
{
"skill_id": 15,
"skill_name": "Reaktionsschnelligkeit",
"skill_category": "Athletik",
"required_level": "einsteiger",
"target_level": "grundlagen",
"intensity": "mittel",
"confidence": 0.74
}
]
}
```
**Errors:**
- `400` - Zu wenig Text (goal und execution leer)
- `503` - KI nicht verfügbar (OPENROUTER_API_KEY fehlt)
---
### 5.3 `POST /exercises/{id}/ai/regenerate`
Generiert summary und/oder skill-Empfehlungen für eine bestehende Übung neu.
Verwendet die aktuellen gespeicherten Felder als Input.
**Request Body:**
```json
{
"regenerate": ["summary", "skills"]
}
```
**Werte:** `"summary"` | `"skills"` (oder beide)
**Response:** `200 OK` (gleiche Struktur wie `/ai/suggest`)
**Hinweis:** Regenerieren überschreibt NICHT Felder, die manuell gesetzt wurden
(`summary_ai_generated = false`). Es wird nur der Vorschlag zurückgegeben,
Trainer muss aktiv übernehmen.
---
## 6. Datenbank
### 6.1 Neues Feld: `summary_ai_generated`
```sql
-- Als Teil von Migration 014 ergänzen:
ALTER TABLE exercises
ADD COLUMN IF NOT EXISTS summary_ai_generated BOOLEAN DEFAULT false;
```
**Semantik:**
- `false` (default) = Zusammenfassung manuell geschrieben oder noch leer
- `true` = Zuletzt von KI generiert (kann überschrieben werden)
Beim manuellen Überschreiben durch den Trainer: `summary_ai_generated = false` setzen.
### 6.2 Kein Feld für Skill-Empfehlungen
Skill-Vorschläge der KI werden **nicht** persistent gespeichert sie erscheinen
nur im Formular-UI und werden erst bei expliziter Bestätigung als reguläre
`exercise_skills`-Einträge gespeichert.
---
## 7. Integration in Speicher-Flow
### 7.1 Auto-Fallback beim Speichern (POST/PUT exercises)
```python
# In backend/routers/exercises.py
async def create_exercise(data, session):
# 1. Übung normal speichern
exercise_id = db.insert_exercise(data)
# 2. Auto-KI nur wenn:
# - OPENROUTER_API_KEY gesetzt
# - summary noch leer
# - goal oder execution vorhanden
if settings.openrouter_api_key and not data.summary and (data.goal or data.execution):
# Background Task (non-blocking)
background_tasks.add_task(
auto_generate_summary,
exercise_id=exercise_id,
title=data.title,
goal=data.goal,
execution=data.execution
)
return exercise_id
```
### 7.2 Skill-Auto-Suggestion
Skill-Empfehlungen werden beim Auto-Fallback **NICHT** automatisch gespeichert
(wegen Bestätigungs-Pflicht). Sie werden nur beim manuellen Trigger angeboten.
---
## 8. Frontend-Integration
### 8.1 ExerciseFormPage KI-Buttons
```
┌──────────────────────────────────────┐
│ Ziel der Übung * │
│ ┌────────────────────────────────┐ │
│ │ Distanzgefühl entwickeln... │ │
│ └────────────────────────────────┘ │
│ │
│ Durchführung * │
│ ┌────────────────────────────────┐ │
│ │ 1. Partnerwahl... │ │
│ └────────────────────────────────┘ │
│ ↓ │
│ Zusammenfassung (für Listen) │
│ ┌────────────────────────────────┐ │
│ │ [Leer] │ │
│ └────────────────────────────────┘ │
│ [✨ KI-Vorschlag] ← Button │
│ │
│ ─────────────────────────────────── │
│ Fähigkeiten │
│ [Keine zugeordnet] │
│ [+ Manuell hinzufügen] │
│ [✨ KI-Empfehlungen] ← Button │
└──────────────────────────────────────┘
```
### 8.2 KI-Vorschlag für Summary (Inline)
Beim Klick auf „✨ KI-Vorschlag":
```
┌──────────────────────────────────────┐
│ ✨ KI-Vorschlag │
│ ─────────────────────────────────── │
│ "Partnerübung zur Entwicklung des │
│ Distanzgefühls. Trainiert räumliche │
│ Wahrnehmung und reaktives Verhalten."│
│ ─────────────────────────────────── │
│ [✓ Übernehmen] [✕ Verwerfen] │
└──────────────────────────────────────┘
```
Nach „Übernehmen": Text landet im Summary-Feld, Button zeigt „↺ Neu generieren".
### 8.3 Anzeige KI-generierter Inhalte
Felder die KI-generiert sind, werden mit einem kleinen Badge markiert:
```
Zusammenfassung ✨ KI-generiert [bearbeiten]
```
Nach manuellem Bearbeiten verschwindet der Badge.
---
## 9. Konfiguration
```env
OPENROUTER_API_KEY=sk-or-...
OPENROUTER_MODEL=anthropic/claude-sonnet-4 # Für Zusammenfassung
OPENROUTER_MODEL_FAST=anthropic/claude-haiku-4-5 # Für Skill-Empfehlungen (billiger)
```
---
## 10. Fehlerbehandlung
| Szenario | Verhalten |
|----------|-----------|
| OPENROUTER_API_KEY nicht gesetzt | KI-Buttons nicht anzeigen, kein Auto-Fallback |
| API-Timeout (> 10s) | Fehlermeldung inline: "KI momentan nicht verfügbar. Bitte manuell ausfüllen." |
| API-Fehler (5xx) | Gleiche Meldung, kein Absturz |
| Unbekannte Skills in Empfehlung | Backend filtert Skills die nicht im Katalog sind heraus |
| Summary zu lang generiert | Backend kürzt auf 200 Zeichen |
---
**Version:** 1.0
**Datum:** 2026-04-24
**Status:** DRAFT