KI-Backend: Umfangs-Umschalter + Prompt Caching (4.5.15/4.5.16)

Umfangs-Umschalter: Checkbox "Auch bestehende Stundeninhalte anpassen" im
AiAssistDialog steuert, ob die KI bestehende Stunden inhaltlich ändern darf oder
die Einheit nur um neue Stunden erweitern soll. Zweifach durchgesetzt (Systemprompt
+ hartes client-seitiges Verwerfen in ApplyResponse), nicht nur der KI-Antwort
vertraut. Dabei auch einen Bug gefixt: eine bereits "Durchgeführt" markierte Stunde
wurde durch eine übernommene KI-Änderung stillschweigend auf "Geplant" zurückgesetzt.

Prompt Caching: der Systemprompt ist jetzt vollständig statisch (Voraussetzung für
Caching) und wird von AnthropicProvider.php als "cache_control: ephemeral" markiert
— wiederholte Anfragen innerhalb der 5-Minuten-TTL zahlen nur den reduzierten
Cache-Read-Preis. transactions-Tabelle und Preistabelle um Cache-Token-Spalten
erweitert, Migration für bereits deployte Installationen beigelegt.
This commit is contained in:
2026-08-16 16:06:52 +02:00
parent 4437f951d9
commit 1928916eac
14 changed files with 328 additions and 38 deletions
+50 -4
View File
@@ -702,15 +702,33 @@ folgenden Punkte gehören direkt in `LehrerApp.Desktop`:
anbieten, nicht nur für Einheiten/Stunden im Verlaufsplan — z.B. Vorschläge beim Aufbau eines
neuen Stundenplans oder beim Ausgleich nach Änderungen. Gleiches Backend/gleiche Abrechnung
wie 4.5.9, aber eigenes Export/Import-Schema für die Stundenplan-Daten.
- [ ] **4.5.12** Offene Frage: Kann ein Agent/Project bei console.claude.ai eingerichtet werden,
- [x] **4.5.12** Offene Frage: Kann ein Agent/Project bei console.claude.ai eingerichtet werden,
um Standardinformationen (JSON-Schema, grundlegender Auftragskontext) dort dauerhaft zu
hinterlegen, statt sie bei jeder Anfrage über das eigene PHP-Backend mitschicken zu müssen?
Würde die Nutzer-Anweisung auf das eigentlich Fachliche reduzieren.
- [ ] **4.5.13** Alternative zu 4.5.12: statt eines extern gepflegten Agents ein app-interner
**Antwort: nein, technisch nicht wie gedacht umsetzbar.** Projects/Agents bei console.claude.ai
sind eine Funktion der claude.ai-Chat-Oberfläche, nicht der Messages-API, die
`ai-backend/plan.php` serverseitig aufruft — es gibt keine Möglichkeit, von dort
programmatisch auf einen dort hinterlegten Kontext zuzugreifen (nutzbar wäre das nur bei
manueller Bedienung im Browser, ohne App/Abrechnung). Stattdessen wie in 4.5.13 umgesetzt.
- [x] **4.5.13** Alternative zu 4.5.12: statt eines extern gepflegten Agents ein app-interner
Standard-Prompt neben dem freien Nutzer-Prompt, der den grundlegenden Kontext (Schema,
Auftragsbeschreibung) automatisch mitliefert — der Nutzer muss ihn dann nicht jedes Mal
selbst formulieren. Ansatzweise bereits vorhanden (`ai-backend/plan.php`, `$systemPrompt`),
hier ginge es um eine bewusstere/erweiterte Ausgestaltung statt der aktuell schlanken Variante.
selbst formulieren. **Umsetzung:** `$systemPrompt` in `ai-backend/plan.php` zeigt der KI
jetzt zuerst das vollständige, literale Eingabeschema (nicht nur Fließtext-Beschreibungen
der Felder) und stellt explizit klar, dass die Einheiten-Ebene reiner Lesekontext ist —
nur `lessons[]` wird vorgeschlagen/verändert, für die Einheit selbst gibt es in der
Antwort kein Feld (Nutzer-Nachtrag, nachdem die erste Fassung Felder nur prosaisch statt
strukturell beschrieb). Danach folgen Feldbedeutungen (Fach/Stufe/Gruppe,
Kompetenz-/Alternativpfad-Katalog), deutsche Verlaufsplan-Konventionen (typische
Phasennamen, übliche Sozialform-Kürzel wie "EA"/"GA"/"UG") und Zeitrichtwerte
(≈45 Min./Einzelstunde) — die freie Nutzer-Anweisung muss dadurch nur noch das fachlich
Konkrete enthalten. Zusätzlich die Anweisung, bei unklarer Nutzer-Anweisung eine
begründete Annahme zu treffen statt zu blockieren (Rückfragen sind über diese Schnittstelle
nicht möglich), mit kurzer Begründung im `summary`-Feld. Bewusst nicht angefasst in dieser
Runde: der Kürzel-Katalog (`IShorthandCodeRepository`) selbst wird der KI noch nicht als
Kontext mitgegeben (nur die Konvention allgemein erklärt) — wäre der nächste sinnvolle Schritt,
analog zu `CompetencyCatalog`/`AlternativePathCatalog`.
- [ ] **4.5.14** Planungsdiff: KI-Vorschläge (4.5.9) mit dem bereits Geplanten auf Feldebene
vergleichbar machen, nicht nur pauschal als "Neu"/"Geändert" markieren wie aktuell im
`AiAssistDialog`. Bei geänderten Stunden sollte sichtbar sein, was sich konkret unterscheidet
@@ -718,6 +736,34 @@ folgenden Punkte gehören direkt in `LehrerApp.Desktop`:
zusammenführen lassen — z.B. nur einzelne Phasen einer Stunde übernehmen statt zwingend die
ganze Stunde, oder eigene zwischenzeitliche Änderungen nicht versehentlich überschreiben,
falls sich die Einheit seit dem Absenden der Anfrage schon geändert hat.
- [x] **4.5.15** Umfangs-Umschalter im `AiAssistDialog`: "Einheit umplanen ohne Stunden zu ändern"
vs. "mit Stunden ändern" (Nutzer-Nachtrag zum Konzeptgespräch nach 4.5.9). Neue Checkbox
"Auch bestehende Stundeninhalte anpassen" (Default: an, entspricht dem bisherigen Verhalten).
Zweifach durchgesetzt statt der KI-Antwort blind vertraut: der (bewusst statisch gehaltene,
siehe 4.5.16) Systemprompt erklärt im Abschnitt "Umfang dieser Anfrage", dass die KI das
mitgesendete Feld `allowModifyingExistingLessons` selbst auswerten und befolgen muss, UND
`AiPlanningService.ApplyResponse`/`AiAssistDialogViewModel.Send` verwerfen client-seitig hart
jede zurückgegebene Änderung an einer bestehenden Lesson, falls der Umschalter das verbietet
— auch wenn die KI die Anweisung ignoriert. Noch nicht umgesetzt:
eine interaktive Rückfrage der KI selbst wäre über diese Schnittstelle (einzelne, separat
abgerechnete Anfragen) nicht sinnvoll möglich — der Umschalter muss vorher vom Nutzer gesetzt
werden, keine Rückfrage während der Anfrage.
- [x] **4.5.16** Prompt Caching für wiederkehrende Kontexte (Nutzer-Nachtrag zur Guthabenfrage):
der Systemprompt in `ai-backend/plan.php` ist bei jeder Anfrage identisch — dafür extra
der zuvor dynamisch interpolierte Umfangs-Abschnitt (4.5.15) wieder statisch gemacht, die KI
liest `allowModifyingExistingLessons` jetzt selbst aus der Eingabe statt einer variablen
Formulierung im Prompt. `AnthropicProvider.php` markiert den Systemprompt jetzt als
"cache_control: ephemeral"; wiederholte Anfragen innerhalb der Anthropic-Cache-TTL (Standard
5 Min.) zahlen dafür nur den reduzierten Cache-Read-Preis statt des vollen Input-Preises.
`transactions` um `cache_creation_input_tokens`/`cache_read_input_tokens` erweitert
(`ai-backend/migrations/2026-08-add-cache-tokens.sql` für bereits deployte Installationen),
Preistabelle in `config.example.php` um `cache_write`/`cache_read` je Modell ergänzt.
Provider-Interface entsprechend erweitert (`FakeProvider` liefert dafür einfach 0 zurück).
**Nicht ohne echten API-Key verifizierbar**, ob Caching tatsächlich greift — nur an
`cache_read_input_tokens > 0` in `transactions` bei einer zweiten Anfrage innerhalb der
TTL beobachtbar (siehe `ai-backend/README.md`).
---
## 5. Schülerdokumentation