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
- 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.
126 lines
4.0 KiB
SQL
126 lines
4.0 KiB
SQL
-- Migration 068: KI Skill-Retrieval-Profile pro Fokusbereich (+ Standardprofil)
|
|
-- Purpose: Gewichtungen/Quota fuer exercise_ai Skill-Katalog (OpenRouter Kontext)
|
|
|
|
CREATE TABLE IF NOT EXISTS ai_skill_retrieval_profiles (
|
|
id SERIAL PRIMARY KEY,
|
|
focus_area_id INT REFERENCES focus_areas(id) ON DELETE CASCADE,
|
|
is_default BOOLEAN NOT NULL DEFAULT FALSE,
|
|
name VARCHAR(200) NOT NULL,
|
|
description TEXT,
|
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS ux_ai_skill_retrieval_profile_focus_area
|
|
ON ai_skill_retrieval_profiles (focus_area_id)
|
|
WHERE focus_area_id IS NOT NULL AND active = TRUE;
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS ux_ai_skill_retrieval_profile_default_only
|
|
ON ai_skill_retrieval_profiles (is_default)
|
|
WHERE is_default IS TRUE AND active = TRUE;
|
|
|
|
COMMENT ON TABLE ai_skill_retrieval_profiles IS
|
|
'Gewichte/Quota fuer Skill-Katalog in exercise_ai; optional gebunden an focus_areas, genau eine is_default=TRUE';
|
|
|
|
INSERT INTO ai_skill_retrieval_profiles (focus_area_id, is_default, name, description, active, config)
|
|
VALUES (
|
|
NULL,
|
|
TRUE,
|
|
'Standard',
|
|
'Kein/Undefinierter Fokusbereich: neutrale Gewichte mit sanften Caps auf sehr breite Unterkategorien.',
|
|
TRUE,
|
|
'{
|
|
"version": 1,
|
|
"importance_multiplier": 1,
|
|
"text_overlap_bonus": 2,
|
|
"main_slug_weights": { "karate": 1, "allgemeine": 1 },
|
|
"category_slug_weights": {},
|
|
"category_max_share": {
|
|
"kondition": 0.38,
|
|
"koordination": 0.35
|
|
},
|
|
"main_min_share": {},
|
|
"description_plain_max_len": 160,
|
|
"karate_relevance_max_len": 72,
|
|
"keyword_overrides": [
|
|
{
|
|
"keywords_any": ["rollenspiel", "szenario", "deesk", "diskussion"],
|
|
"case_insensitive": true,
|
|
"patch": {
|
|
"category_slug_weights": {
|
|
"psychische_faehigkeiten": 1.65,
|
|
"soziale_faehigkeiten": 1.65,
|
|
"kognition": 1.4
|
|
},
|
|
"category_max_share": {
|
|
"kondition": 0.08,
|
|
"koordination": 0.1
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"keywords_any": ["befreiung", "haltegriff", "greifer", "umklammer"],
|
|
"case_insensitive": true,
|
|
"patch": {
|
|
"category_slug_weights": {
|
|
"selbstverteidigung": 2.2,
|
|
"koordination": 0.9
|
|
},
|
|
"main_slug_weights": { "karate": 1.35 }
|
|
}
|
|
}
|
|
]
|
|
}'::jsonb
|
|
);
|
|
|
|
INSERT INTO ai_skill_retrieval_profiles (focus_area_id, is_default, name, description, active, config)
|
|
SELECT
|
|
fa.id,
|
|
FALSE,
|
|
'Gewaltschutz',
|
|
'Kaum klassische Sportfaehigkeit; Gewicht auf Deeskalation, Kognition/Soziales; SV-Schwerpunkt per Keywords verstaerken.',
|
|
TRUE,
|
|
'{
|
|
"version": 1,
|
|
"importance_multiplier": 1,
|
|
"text_overlap_bonus": 2.25,
|
|
"main_slug_weights": { "karate": 1.08, "allgemeine": 1.06 },
|
|
"category_slug_weights": {
|
|
"kognition": 1.72,
|
|
"psychische_faehigkeiten": 1.78,
|
|
"soziale_faehigkeiten": 1.78,
|
|
"selbstverteidigung": 1.82,
|
|
"kondition": 0.32,
|
|
"koordination": 0.4
|
|
},
|
|
"category_max_share": {
|
|
"kondition": 0.12,
|
|
"koordination": 0.16
|
|
},
|
|
"main_min_share": {},
|
|
"description_plain_max_len": 150,
|
|
"karate_relevance_max_len": 0,
|
|
"keyword_overrides": [
|
|
{
|
|
"keywords_any": ["befreiung", "haltegriff", "greifer"],
|
|
"case_insensitive": true,
|
|
"patch": {
|
|
"category_slug_weights": {
|
|
"selbstverteidigung": 3.25,
|
|
"koordination": 1.08
|
|
},
|
|
"main_slug_weights": { "karate": 1.5 }
|
|
}
|
|
}
|
|
]
|
|
}'::jsonb
|
|
FROM focus_areas fa
|
|
WHERE fa.name = 'Gewaltschutz'
|
|
AND (fa.status IS NULL OR fa.status = 'active')
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM ai_skill_retrieval_profiles p
|
|
WHERE p.focus_area_id = fa.id AND p.active = TRUE
|
|
)
|
|
LIMIT 1;
|