All checks were successful
Deploy Development / deploy (push) Successful in 44s
Test Suite / pytest-backend (push) Successful in 40s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 14s
Test Suite / k6 /health Baseline (push) Successful in 36s
Test Suite / playwright-tests (push) Successful in 1m16s
- Added `exercise_instruction_rewrite` functionality to enhance AI-generated instructions, incorporating fields for goal, execution, preparation, and trainer notes. - Updated `ExerciseFormAiPromptContext` to include new fields and methods for instruction handling. - Enhanced the `run_exercise_form_ai_suggestion` function to support instruction rewriting and validation. - Modified API endpoints and frontend components to integrate instruction features, including a new button for AI instruction revision. - Incremented application version to 0.8.163 and updated changelog to reflect these changes, including migration details and new functionality.
106 lines
3.5 KiB
Python
106 lines
3.5 KiB
Python
"""
|
|
Gemeinsame Pydantic-Modelle fuer Uebungs-KI-Kontext (Formularfelder → Prompt-Platzhalter).
|
|
|
|
Keine Imports aus exercise_ai — vermeidet Zirkelimporte mit ai_prompt_job / exercise_ai.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import List, Optional, Sequence, Tuple
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class ExerciseFormAiFocusRow(BaseModel):
|
|
"""Fokusbereich fuer Skill-Retrieval (ai_skill_retrieval_profiles)."""
|
|
|
|
focus_area_id: int = Field(..., ge=1)
|
|
is_primary: Optional[bool] = False
|
|
|
|
|
|
class ExerciseFormAiPromptContext(BaseModel):
|
|
"""
|
|
Inhaltliche Eingabe fuer Uebungs-Prompts (Kurzfassung / Skills / Anleitung).
|
|
|
|
Wird genutzt von Admin-Prompt-Vorschau und POST /exercises/ai/suggest (via Mapping).
|
|
"""
|
|
|
|
title: Optional[str] = ""
|
|
goal: Optional[str] = None
|
|
execution: Optional[str] = None
|
|
preparation: Optional[str] = None
|
|
trainer_notes: Optional[str] = None
|
|
focus_hint: Optional[str] = None
|
|
focus_areas_context: Optional[List[ExerciseFormAiFocusRow]] = None
|
|
|
|
def focus_area_tuples(self) -> Optional[List[Tuple[int, bool]]]:
|
|
if not self.focus_areas_context:
|
|
return None
|
|
return [(int(x.focus_area_id), bool(x.is_primary)) for x in self.focus_areas_context]
|
|
|
|
def has_instruction_source_text(self) -> bool:
|
|
"""Mindestens ein Anleitungsfeld oder Titel fuer instruction_rewrite."""
|
|
if (self.title or "").strip():
|
|
return True
|
|
for val in (self.goal, self.execution, self.preparation, self.trainer_notes):
|
|
if val and str(val).strip():
|
|
return True
|
|
return False
|
|
|
|
@classmethod
|
|
def from_api_suggest(
|
|
cls,
|
|
*,
|
|
title: Optional[str] = None,
|
|
goal: Optional[str] = None,
|
|
execution: Optional[str] = None,
|
|
preparation: Optional[str] = None,
|
|
trainer_notes: Optional[str] = None,
|
|
focus_area_hint: Optional[str] = None,
|
|
focus_areas_context: Optional[Sequence[ExerciseFormAiFocusRow]] = None,
|
|
) -> ExerciseFormAiPromptContext:
|
|
"""Mappt Felder aus POST /exercises/ai/suggest (focus_area_hint → focus_hint)."""
|
|
hint = (focus_area_hint or "").strip() or None
|
|
return cls(
|
|
title=(title or "").strip(),
|
|
goal=goal,
|
|
execution=execution,
|
|
preparation=preparation,
|
|
trainer_notes=trainer_notes,
|
|
focus_hint=hint,
|
|
focus_areas_context=list(focus_areas_context) if focus_areas_context else None,
|
|
)
|
|
|
|
@classmethod
|
|
def from_focus_tuples(
|
|
cls,
|
|
*,
|
|
title: str = "",
|
|
goal: Optional[str] = None,
|
|
execution: Optional[str] = None,
|
|
preparation: Optional[str] = None,
|
|
trainer_notes: Optional[str] = None,
|
|
focus_hint: Optional[str] = None,
|
|
focus_tuples: Optional[Sequence[Tuple[int, bool]]] = None,
|
|
) -> ExerciseFormAiPromptContext:
|
|
rows = None
|
|
if focus_tuples:
|
|
rows = [
|
|
ExerciseFormAiFocusRow(focus_area_id=int(fid), is_primary=bool(prim))
|
|
for fid, prim in focus_tuples
|
|
]
|
|
return cls(
|
|
title=(title or "").strip(),
|
|
goal=goal,
|
|
execution=execution,
|
|
preparation=preparation,
|
|
trainer_notes=trainer_notes,
|
|
focus_hint=(focus_hint or "").strip() or None,
|
|
focus_areas_context=rows,
|
|
)
|
|
|
|
|
|
__all__ = [
|
|
"ExerciseFormAiFocusRow",
|
|
"ExerciseFormAiPromptContext",
|
|
]
|