Some checks failed
Test Suite / playwright-tests (push) Waiting to run
Deploy Development / deploy (push) Successful in 43s
Test Suite / pytest-backend (push) Failing after 1s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Has been cancelled
- Updated the exercise form to include a tabbed navigation structure, improving user experience with sections for Stammdaten, Anleitung, Einordnung, Varianten, and Medien & Mehr. - Introduced the concept of **Freigabelevel** (visibility level) in the UI, replacing previous terminology for clarity and consistency across components. - Implemented new AI endpoints for exercise suggestions and regeneration, allowing for dynamic content generation without direct database writes. - Removed the legacy `is_primary` flag from exercise skills in the UI, ensuring that intensity levels (`niedrig`, `mittel`, `hoch`) are the primary focus for skill management. - Enhanced the variant management process with improved saving mechanisms and UI updates to reflect changes more intuitively.
142 lines
4.9 KiB
SQL
142 lines
4.9 KiB
SQL
-- Migration 067: Konfigurierbare KI-Prompts + Tracking-Feld fuer Uebungs-Zusammenfassung
|
|
-- Datum: 2026-05-22
|
|
-- Spec: technical/KI_FEATURES_SPEC.md, AI_PROMPT_SYSTEM_SPEC.md
|
|
|
|
-- ============================================================================
|
|
-- AI PROMPTS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS ai_prompts (
|
|
id SERIAL PRIMARY KEY,
|
|
slug VARCHAR(100) NOT NULL UNIQUE,
|
|
display_name VARCHAR(200) NOT NULL,
|
|
description TEXT,
|
|
template TEXT NOT NULL,
|
|
|
|
category VARCHAR(50) DEFAULT 'exercise'
|
|
CHECK (category IN ('exercise', 'training', 'matrix', 'import', 'admin')),
|
|
|
|
output_format VARCHAR(10) DEFAULT 'text'
|
|
CHECK (output_format IN ('text', 'json')),
|
|
|
|
output_schema JSONB,
|
|
is_system_default BOOLEAN DEFAULT false,
|
|
default_template TEXT,
|
|
|
|
active BOOLEAN DEFAULT true,
|
|
sort_order INT DEFAULT 0,
|
|
|
|
created_by INT REFERENCES profiles(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_ai_prompts_slug ON ai_prompts(slug);
|
|
CREATE INDEX IF NOT EXISTS idx_ai_prompts_category ON ai_prompts(category);
|
|
CREATE INDEX IF NOT EXISTS idx_ai_prompts_active ON ai_prompts(active, sort_order);
|
|
|
|
DROP TRIGGER IF EXISTS ai_prompts_update ON ai_prompts;
|
|
CREATE TRIGGER ai_prompts_update
|
|
BEFORE UPDATE ON ai_prompts
|
|
FOR EACH ROW EXECUTE FUNCTION update_timestamp();
|
|
|
|
-- ============================================================================
|
|
-- TRACKING SUMMARY (KI)
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE exercises ADD COLUMN IF NOT EXISTS summary_ai_generated BOOLEAN DEFAULT false;
|
|
|
|
COMMENT ON COLUMN exercises.summary_ai_generated IS 'TRUE wenn Kurzbeschreibung zuletzt von KI vorgeschlagen und uebernommen (UI setzt bei manueller Aenderung false)';
|
|
|
|
-- ============================================================================
|
|
-- SEED PROMPTS (idempotent)
|
|
-- ============================================================================
|
|
|
|
INSERT INTO ai_prompts (
|
|
slug, display_name, description, template,
|
|
category, output_format, is_system_default, default_template, active, sort_order
|
|
)
|
|
SELECT
|
|
'pipeline',
|
|
'Mehrstufige Gesamtanalyse',
|
|
'Master-Schalter fuer die Pipeline-Anzeige.',
|
|
'PIPELINE_MASTER',
|
|
'admin',
|
|
'text',
|
|
false,
|
|
'PIPELINE_MASTER',
|
|
true,
|
|
-10
|
|
WHERE NOT EXISTS (SELECT 1 FROM ai_prompts WHERE slug = 'pipeline');
|
|
|
|
INSERT INTO ai_prompts (
|
|
slug, display_name, description, template,
|
|
category, output_format, is_system_default, default_template, active, sort_order
|
|
)
|
|
SELECT
|
|
'exercise_summary',
|
|
'Uebungs-Zusammenfassung',
|
|
'Erzeugt eine kurze Kurzbeschreibung fuer Listen/Galerie.',
|
|
$s$Du bist Assistent fuer Kampfsport-Trainer.
|
|
Erstelle eine kurze Kurzbeschreibung fuer Listen und Trainingsplaene.
|
|
|
|
Anforderungen:
|
|
- Hochstens etwa 200 Zeichen (bei Bedarf gekuerzt fuer Mobile)
|
|
- Kern: Welche Trainingsqualitaeten? Wie fuehrt man die Uebung kurz aus?
|
|
- Sachlich, auf Deutsch
|
|
|
|
Uebung: {{exercise_title}}
|
|
Fokuskontext: {{exercise_focus_area}}
|
|
Ziel (Fliesstext, kann HTML sein): {{exercise_goal}}
|
|
Durchfuehrung (Fliesstext, kann HTML sein): {{exercise_execution}}
|
|
|
|
Antworte NUR mit der Kurzbeschreibung als einfachen Text (keine Markdown-Codeblocks, keine Anfuehrungszeichen um den ganzen Text).$s$,
|
|
'exercise',
|
|
'text',
|
|
true,
|
|
NULL,
|
|
true,
|
|
1
|
|
WHERE NOT EXISTS (SELECT 1 FROM ai_prompts WHERE slug = 'exercise_summary');
|
|
|
|
INSERT INTO ai_prompts (
|
|
slug, display_name, description, template,
|
|
category, output_format, is_system_default, default_template, active, sort_order
|
|
)
|
|
SELECT
|
|
'exercise_skill_suggestions',
|
|
'Faehigkeiten-Empfehlungen',
|
|
'Schlaegt passende Skills mit Stufen/Intensitaet vor (JSON-Ausgabe-Prompt).',
|
|
$j$Du bist Assistent fuer Kampfsport-Trainer.
|
|
Ordne diese Uebung dem globalen Skill-Katalog zu.
|
|
|
|
Daten zur Uebung:
|
|
Titel: {{exercise_title}}
|
|
Fokuskontext (optional): {{exercise_focus_area}}
|
|
Ziel (gekuerzt_plain): {{exercise_goal}}
|
|
Durchfuehrung (gekuerzt_plain): {{exercise_execution}}
|
|
|
|
Verfuegbare Faehigkeiten (Auswahl NUR ueber diese IDs — keine anderen IDs verwenden):
|
|
{{skills_catalog}}
|
|
|
|
Waehle hoechstens 5 passende Skills. Für jede Faehigkeit:
|
|
- skill_id: ganze Zahl aus der Liste
|
|
- required_level: eines von basis, grundlagen, aufbau, fortgeschritten, optimierung
|
|
- target_level: derselbe Wertvorrat
|
|
- intensity: eines von niedrig, mittel, hoch
|
|
- is_primary (optional): true fuer die Hauptfaehigkeit der Uebung, sondern false/weglassen
|
|
|
|
Antworte NUR mit einem JSON-Array ohne Erklaertext, keine Markdown-Fences.
|
|
|
|
Beispielformat:
|
|
[{"skill_id": 1, "required_level": "grundlagen", "target_level": "aufbau", "intensity": "hoch", "is_primary": true}]
|
|
|
|
Wenn nichts gut passt, antworte mit [].$j$,
|
|
'exercise',
|
|
'json',
|
|
true,
|
|
NULL,
|
|
true,
|
|
2
|
|
WHERE NOT EXISTS (SELECT 1 FROM ai_prompts WHERE slug = 'exercise_skill_suggestions');
|