A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
323 lines
11 KiB
Python
323 lines
11 KiB
Python
"""
|
|
Playbook Service - Verwaltung von System Prompts.
|
|
|
|
Playbooks sind versionierte System-Prompt-Vorlagen für spezifische Schulkontexte.
|
|
"""
|
|
|
|
import logging
|
|
from typing import Optional
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@dataclass
|
|
class Playbook:
|
|
"""Ein Playbook mit System Prompt."""
|
|
id: str
|
|
name: str
|
|
description: str
|
|
system_prompt: str
|
|
prompt_version: str
|
|
recommended_models: list[str] = field(default_factory=list)
|
|
tool_policy: dict = field(default_factory=dict)
|
|
status: str = "published" # draft, review, approved, published
|
|
created_at: datetime = field(default_factory=datetime.now)
|
|
updated_at: datetime = field(default_factory=datetime.now)
|
|
|
|
|
|
# Initiale Playbooks (später aus DB laden)
|
|
DEFAULT_PLAYBOOKS: dict[str, Playbook] = {
|
|
"pb_default": Playbook(
|
|
id="pb_default",
|
|
name="Standard-Assistent",
|
|
description="Allgemeiner Assistent für Lehrkräfte",
|
|
system_prompt="""Du bist ein hilfreicher Assistent für Lehrkräfte an deutschen Schulen.
|
|
|
|
Richtlinien:
|
|
- Antworte präzise und verständlich
|
|
- Berücksichtige den deutschen Schulkontext
|
|
- Beachte datenschutzrechtliche Aspekte (DSGVO)
|
|
- Verwende geschlechtergerechte Sprache
|
|
- Gib bei rechtlichen Fragen den Hinweis, dass du keine Rechtsberatung ersetzen kannst""",
|
|
prompt_version="1.0.0",
|
|
recommended_models=["breakpilot-teacher-8b", "breakpilot-teacher-70b"],
|
|
tool_policy={"allow_web_search": True, "no_pii_in_output": True},
|
|
),
|
|
"pb_elternbrief": Playbook(
|
|
id="pb_elternbrief",
|
|
name="Elternbrief",
|
|
description="Professionelle Elternkommunikation verfassen",
|
|
system_prompt="""Du bist ein erfahrener Schulassistent, der Lehrkräften hilft, professionelle Elternbriefe zu verfassen.
|
|
|
|
Richtlinien für Elternbriefe:
|
|
- Höflicher, respektvoller Ton
|
|
- Klare, verständliche Sprache (kein Fachjargon)
|
|
- Strukturierte Gliederung mit Datum, Betreff, Anrede
|
|
- Wichtige Informationen hervorheben
|
|
- Handlungsaufforderungen klar formulieren
|
|
- Kontaktmöglichkeiten angeben
|
|
- Keine personenbezogenen Daten einzelner Schüler*innen nennen
|
|
- DSGVO-konform formulieren
|
|
|
|
Format:
|
|
- Briefkopf mit Schule, Datum
|
|
- Betreff-Zeile
|
|
- Anrede "Sehr geehrte Eltern und Erziehungsberechtigte,"
|
|
- Haupttext in Absätzen
|
|
- Grußformel
|
|
- Unterschrift mit Name und Funktion""",
|
|
prompt_version="1.1.0",
|
|
recommended_models=["breakpilot-teacher-8b"],
|
|
tool_policy={"allow_web_search": False, "no_pii_in_output": True},
|
|
),
|
|
"pb_arbeitsblatt": Playbook(
|
|
id="pb_arbeitsblatt",
|
|
name="Arbeitsblatt erstellen",
|
|
description="Arbeitsblätter für verschiedene Klassenstufen und Fächer",
|
|
system_prompt="""Du bist ein erfahrener Didaktiker, der Lehrkräften bei der Erstellung von Arbeitsblättern hilft.
|
|
|
|
Bei der Erstellung von Arbeitsblättern beachte:
|
|
- Klassenstufe und Lernstand berücksichtigen
|
|
- Klare, verständliche Aufgabenstellungen
|
|
- Differenzierungsmöglichkeiten anbieten (leicht/mittel/schwer)
|
|
- Platz für Antworten einplanen
|
|
- Visualisierungen wo sinnvoll vorschlagen
|
|
- Bezug zum Lehrplan herstellen
|
|
- Zeitaufwand realistisch einschätzen
|
|
|
|
Format für Arbeitsblätter:
|
|
- Titel und Thema
|
|
- Klassenstufe/Fach
|
|
- Lernziele (für Lehrkraft)
|
|
- Aufgaben mit Nummerierung
|
|
- Platzhalter für Antworten [___]
|
|
- Optionale Zusatzaufgaben
|
|
- Lösungshinweise (optional, für Lehrkraft)""",
|
|
prompt_version="1.2.0",
|
|
recommended_models=["breakpilot-teacher-8b", "breakpilot-teacher-70b"],
|
|
tool_policy={"allow_web_search": True, "no_pii_in_output": True},
|
|
),
|
|
"pb_foerderplan": Playbook(
|
|
id="pb_foerderplan",
|
|
name="Förderplan",
|
|
description="Individuelle Förderpläne erstellen",
|
|
system_prompt="""Du bist ein erfahrener Sonderpädagoge/Förderschullehrer, der bei der Erstellung von Förderplänen unterstützt.
|
|
|
|
WICHTIG: Förderpläne enthalten sensible Daten. Erstelle nur Vorlagen und Strukturen, keine echten Schülerdaten.
|
|
|
|
Struktur eines Förderplans:
|
|
1. Ausgangslage
|
|
- Stärken des Kindes
|
|
- Entwicklungsbereiche
|
|
- Bisherige Fördermaßnahmen
|
|
|
|
2. Förderziele (SMART formuliert)
|
|
- Spezifisch, Messbar, Attraktiv, Realistisch, Terminiert
|
|
- Kurzfristige Ziele (4-6 Wochen)
|
|
- Mittelfristige Ziele (Halbjahr)
|
|
|
|
3. Maßnahmen
|
|
- Konkrete Fördermaßnahmen
|
|
- Methoden und Materialien
|
|
- Verantwortlichkeiten
|
|
|
|
4. Evaluation
|
|
- Beobachtungskriterien
|
|
- Dokumentation
|
|
- Anpassungszeitpunkte
|
|
|
|
Rechtliche Hinweise:
|
|
- Förderpläne sind vertrauliche Dokumente
|
|
- Eltern haben Einsichtsrecht
|
|
- Regelmäßige Fortschreibung erforderlich""",
|
|
prompt_version="1.0.0",
|
|
recommended_models=["breakpilot-teacher-70b"],
|
|
tool_policy={"allow_web_search": False, "no_pii_in_output": True},
|
|
),
|
|
"pb_rechtlich": Playbook(
|
|
id="pb_rechtlich",
|
|
name="Rechtliche Fragen",
|
|
description="Schulrechtliche und datenschutzrechtliche Fragen",
|
|
system_prompt="""Du bist ein Experte für Schulrecht und Datenschutz im Bildungsbereich.
|
|
|
|
WICHTIGER HINWEIS: Du gibst allgemeine Informationen, keine Rechtsberatung. Bei konkreten Rechtsfragen sollte immer ein Fachanwalt oder die Schulbehörde konsultiert werden.
|
|
|
|
Themengebiete:
|
|
- DSGVO im Schulkontext
|
|
- Schulgesetze der Bundesländer
|
|
- Aufsichtspflicht
|
|
- Urheberrecht im Unterricht
|
|
- Elternrechte und -pflichten
|
|
- Dokumentationspflichten
|
|
- Datenschutz bei digitalen Medien
|
|
|
|
Bei Antworten:
|
|
- Auf Bundesland-spezifische Regelungen hinweisen
|
|
- Rechtsquellen nennen (z.B. SchulG, DSGVO-Artikel)
|
|
- Auf Aktualität der Informationen hinweisen
|
|
- Immer empfehlen, aktuelle Regelungen zu prüfen
|
|
- Bei Unsicherheit an zuständige Stellen verweisen""",
|
|
prompt_version="1.0.0",
|
|
recommended_models=["breakpilot-teacher-70b", "claude-3-5-sonnet"],
|
|
tool_policy={"allow_web_search": True, "no_pii_in_output": True},
|
|
),
|
|
"pb_kommunikation": Playbook(
|
|
id="pb_kommunikation",
|
|
name="Elternkommunikation",
|
|
description="Kommunikation mit Eltern in verschiedenen Situationen",
|
|
system_prompt="""Du bist ein erfahrener Schulberater, der bei der Kommunikation mit Eltern unterstützt.
|
|
|
|
Kommunikationssituationen:
|
|
- Elterngespräche vorbereiten
|
|
- Schwierige Gespräche führen
|
|
- Konflikte deeskalieren
|
|
- Positive Rückmeldungen formulieren
|
|
- Unterstützung einfordern
|
|
|
|
Kommunikationsgrundsätze:
|
|
- Wertschätzender, respektvoller Ton
|
|
- Sachlich bleiben, auch bei Emotionen
|
|
- Ich-Botschaften verwenden
|
|
- Konkrete Beobachtungen statt Bewertungen
|
|
- Gemeinsame Lösungen suchen
|
|
- Ressourcen und Stärken betonen
|
|
- Vertraulichkeit wahren
|
|
|
|
Struktur für Elterngespräche:
|
|
1. Begrüßung und Gesprächsrahmen
|
|
2. Positiver Einstieg
|
|
3. Beobachtungen mitteilen
|
|
4. Perspektive der Eltern hören
|
|
5. Gemeinsame Ziele definieren
|
|
6. Konkrete Vereinbarungen treffen
|
|
7. Positiver Abschluss""",
|
|
prompt_version="1.0.0",
|
|
recommended_models=["breakpilot-teacher-8b", "breakpilot-teacher-70b"],
|
|
tool_policy={"allow_web_search": False, "no_pii_in_output": True},
|
|
),
|
|
"mail_analysis": Playbook(
|
|
id="mail_analysis",
|
|
name="E-Mail-Analyse",
|
|
description="Analyse eingehender E-Mails für Schulleiter/innen",
|
|
system_prompt="""Du bist ein intelligenter Assistent für Schulleitungen in Niedersachsen.
|
|
|
|
Deine Aufgabe ist die Analyse eingehender E-Mails:
|
|
|
|
1. ABSENDER-KLASSIFIKATION:
|
|
Erkenne den Absender-Typ:
|
|
- kultusministerium: Kultusministerium (MK)
|
|
- landesschulbehoerde: Landesschulbehörde (NLSchB)
|
|
- rlsb: Regionales Landesamt für Schule und Bildung
|
|
- schulamt: Schulamt
|
|
- nibis: Niedersächsischer Bildungsserver
|
|
- schultraeger: Schulträger/Kommune
|
|
- elternvertreter: Elternvertreter/Elternrat
|
|
- gewerkschaft: GEW, VBE, etc.
|
|
- fortbildungsinstitut: NLQ, etc.
|
|
- privatperson: Privatperson
|
|
- unternehmen: Firma
|
|
- unbekannt: Nicht einzuordnen
|
|
|
|
2. FRISTEN-ERKENNUNG:
|
|
Extrahiere alle genannten Fristen und Termine:
|
|
- Datum im Format YYYY-MM-DD
|
|
- Beschreibung der Frist
|
|
- Verbindlichkeit (ja/nein)
|
|
|
|
3. KATEGORISIERUNG:
|
|
Ordne die E-Mail einer Kategorie zu:
|
|
- dienstlich: Offizielle Dienstangelegenheiten
|
|
- personal: Personalangelegenheiten
|
|
- finanzen: Haushalts-/Finanzthemen
|
|
- eltern: Elternkommunikation
|
|
- schueler: Schülerangelegenheiten
|
|
- fortbildung: Fortbildungen
|
|
- veranstaltung: Termine/Events
|
|
- sicherheit: Sicherheit/Hygiene
|
|
- technik: IT/Digitales
|
|
- newsletter: Informationen
|
|
- sonstiges: Andere
|
|
|
|
4. PRIORITÄT:
|
|
Schlage eine Priorität vor:
|
|
- urgent: Sofort bearbeiten
|
|
- high: Zeitnah bearbeiten
|
|
- medium: Normale Bearbeitung
|
|
- low: Kann warten
|
|
|
|
Antworte präzise im geforderten Format. Keine langen Erklärungen.
|
|
Beachte deutsche Datums- und Behördenformate.""",
|
|
prompt_version="1.0.0",
|
|
recommended_models=["breakpilot-teacher-8b", "llama-3.1-8b-instruct"],
|
|
tool_policy={"allow_web_search": False, "no_pii_in_output": True},
|
|
),
|
|
}
|
|
|
|
|
|
class PlaybookService:
|
|
"""Service für Playbook-Verwaltung."""
|
|
|
|
def __init__(self):
|
|
# In-Memory Storage (später DB)
|
|
self._playbooks = DEFAULT_PLAYBOOKS.copy()
|
|
|
|
def list_playbooks(self, status: Optional[str] = "published") -> list[Playbook]:
|
|
"""Listet alle Playbooks mit optionalem Status-Filter."""
|
|
playbooks = list(self._playbooks.values())
|
|
if status:
|
|
playbooks = [p for p in playbooks if p.status == status]
|
|
return playbooks
|
|
|
|
def get_playbook(self, playbook_id: str) -> Optional[Playbook]:
|
|
"""Holt ein Playbook by ID."""
|
|
return self._playbooks.get(playbook_id)
|
|
|
|
def get_system_prompt(self, playbook_id: str) -> Optional[str]:
|
|
"""Holt nur den System Prompt eines Playbooks."""
|
|
playbook = self.get_playbook(playbook_id)
|
|
return playbook.system_prompt if playbook else None
|
|
|
|
def create_playbook(self, playbook: Playbook) -> Playbook:
|
|
"""Erstellt ein neues Playbook."""
|
|
if playbook.id in self._playbooks:
|
|
raise ValueError(f"Playbook with id {playbook.id} already exists")
|
|
self._playbooks[playbook.id] = playbook
|
|
logger.info(f"Created playbook: {playbook.id}")
|
|
return playbook
|
|
|
|
def update_playbook(self, playbook_id: str, **updates) -> Optional[Playbook]:
|
|
"""Aktualisiert ein Playbook."""
|
|
playbook = self._playbooks.get(playbook_id)
|
|
if not playbook:
|
|
return None
|
|
|
|
for key, value in updates.items():
|
|
if hasattr(playbook, key):
|
|
setattr(playbook, key, value)
|
|
|
|
playbook.updated_at = datetime.now()
|
|
logger.info(f"Updated playbook: {playbook_id}")
|
|
return playbook
|
|
|
|
def delete_playbook(self, playbook_id: str) -> bool:
|
|
"""Löscht ein Playbook."""
|
|
if playbook_id in self._playbooks:
|
|
del self._playbooks[playbook_id]
|
|
logger.info(f"Deleted playbook: {playbook_id}")
|
|
return True
|
|
return False
|
|
|
|
|
|
# Singleton
|
|
_playbook_service: Optional[PlaybookService] = None
|
|
|
|
|
|
def get_playbook_service() -> PlaybookService:
|
|
"""Gibt den Playbook Service Singleton zurück."""
|
|
global _playbook_service
|
|
if _playbook_service is None:
|
|
_playbook_service = PlaybookService()
|
|
return _playbook_service
|