All checks were successful
Deploy Development / deploy (push) Successful in 41s
Test Suite / pytest-backend (push) Successful in 42s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 12s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m18s
- Added a new target architecture document for the AI Prompt System, detailing context types, composition, and planning phases. - Refactored the backend to utilize a shared function for loading AI prompt rows, reducing SQL duplication in the `exercise_ai` module. - Incremented the application version to 0.8.159 and updated the changelog to reflect these changes, including enhancements to the AI prompt management and documentation links.
75 lines
1.9 KiB
Python
75 lines
1.9 KiB
Python
"""
|
|
Gemeinsame KI-Prompt-Laufzeit (Shinkan): DB-Lesezugriff ai_prompts + Kontext-Arten.
|
|
|
|
Bleibt ohne Import von exercise_ai (kein Zirkel). Domänen wie exercise_ai nutzen
|
|
load_ai_prompt_row und die Enum; Platzhalter bauen sie selbst oder über geteilte Builder.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from enum import Enum
|
|
from typing import Any, Dict, Optional
|
|
|
|
_EXERCISE_AI_SLUGS = frozenset(
|
|
{
|
|
"exercise_summary",
|
|
"exercise_skill_suggestions",
|
|
}
|
|
)
|
|
|
|
|
|
class AiPromptContextKind(str, Enum):
|
|
"""
|
|
Logischer Kontext fuer Platzhalter/Builder — erweiterbar fuer Planung/Rahmen
|
|
ohne bestehende Slugs zu invalidieren.
|
|
"""
|
|
|
|
EXERCISE_FORM_AI = "exercise_form_ai"
|
|
|
|
|
|
def context_kind_for_slug(slug: str) -> Optional[AiPromptContextKind]:
|
|
"""Ordnet einen DB-Slug einer Kontext-Art zu, sofern registriert."""
|
|
s = (slug or "").strip().lower()
|
|
if s in _EXERCISE_AI_SLUGS:
|
|
return AiPromptContextKind.EXERCISE_FORM_AI
|
|
return None
|
|
|
|
|
|
def load_ai_prompt_row(cur, slug: str, *, active_only: bool = True) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
Laedt eine Zeile ai_prompts fuer Laufzeit-Orchestrierung.
|
|
|
|
active_only=True: inaktive Prompts werden wie fehlend behandelt (503 im Aufrufer).
|
|
"""
|
|
if active_only:
|
|
cur.execute(
|
|
"""
|
|
SELECT slug, display_name, template, output_format, active
|
|
FROM ai_prompts
|
|
WHERE slug = %s AND active = true
|
|
""",
|
|
(slug,),
|
|
)
|
|
else:
|
|
cur.execute(
|
|
"""
|
|
SELECT slug, display_name, template, output_format, active
|
|
FROM ai_prompts
|
|
WHERE slug = %s
|
|
""",
|
|
(slug,),
|
|
)
|
|
row = cur.fetchone()
|
|
if not row:
|
|
return None
|
|
d = dict(row)
|
|
if active_only and not d.get("active", True):
|
|
return None
|
|
return d
|
|
|
|
|
|
__all__ = [
|
|
"AiPromptContextKind",
|
|
"context_kind_for_slug",
|
|
"load_ai_prompt_row",
|
|
]
|