Kairo-Jinkendo/docs/reference/design-principles/mitai/PROMPT_ENGINE_DESIGN_PRINCIPLES.md

306 lines
16 KiB
Markdown
Raw Permalink Normal View History

# Prompt Engine – Designprinzipien (Extraktion)
**Status:** Analyse / Arbeitspapier
**Stand:** 2026-07-04
**Geltungsbereich:** Modul „Prompt Engine“ (Unified Prompt System, Issue #28) — keine Mitai-Gesamtarchitektur, keine Domänenlogik (Gesundheit, Ernährung, Messwerte)
**Serie:** Designprinzipien für Produktfamilie · Dokument 1 von n
**Kernkomponenten:**
| Bereich | Pfade |
|---------|-------|
| Executor | `backend/prompt_executor.py`, `backend/workflow_executor.py` |
| Platzhalter | `backend/placeholder_resolver.py`, `backend/placeholder_registry.py`, `backend/placeholder_registrations/` |
| API | `backend/routers/prompts.py`, `backend/routers/workflows.py` |
| Admin-UI | `frontend/src/pages/AdminPromptsPage.jsx`, `UnifiedPromptModal.jsx`, `WorkflowEditorPage.jsx` |
| Fachliche Spec | `.claude/docs/functional/AI_PROMPTS.md` |
| Platzhalter-Governance | `.claude/docs/technical/PLACEHOLDER_REGISTRY_FRAMEWORK.md`, `docs/PLACEHOLDER_GOVERNANCE.md` |
---
## Modul
**Prompt Engine** (Unified Prompt System, Issue #28)
Backend-Kern: `prompt_executor.py`, `placeholder_resolver.py`, `placeholder_registry` / `placeholder_registrations/`, `workflow_executor.py`
API: `routers/prompts.py`
Admin-UI: `AdminPromptsPage`, `UnifiedPromptModal`, `WorkflowEditorPage`
---
## Fachliche Verantwortung
Die Prompt Engine ist die **zentrale Ausführungs- und Konfigurationsschicht für KI-Analysen**. Sie übernimmt:
1. **Prompt-Orchestrierung** — Laden aktiver Prompt-Definitionen aus der DB und Ausführung als `base` (Einzelprompt), `pipeline` (mehrstufig) oder `workflow` (Graph).
2. **Kontextaufbereitung** — Befüllen von Platzhaltern mit profilbezogenen Daten (Resolver → Data Layer).
3. **LLM-Aufruf** — Einheitlicher OpenRouter-Call über injizierte Callback-Funktion.
4. **Ergebnisbehandlung** — JSON-Validierung, strukturierte Container (Fragenergänzungen), Debug-Metadaten, optionales Speichern in `ai_insights`.
5. **Admin-Konfiguration** — CRUD für Prompts/Workflows, Import/Export, Vorschau und Test ohne Produktions-Ausführung.
### Administrierte Konfigurationen
| Konfiguration | Speicherort | Inhalt |
|---------------|-------------|--------|
| Prompt-Metadaten | `ai_prompts` | `name`, `slug`, `category`, `active`, `sort_order`, `display_name` |
| Templates | `ai_prompts` | `template` |
| Pipeline-Stages | `ai_prompts.stages` (JSONB) | Stages mit `inline` / `reference` |
| Workflow-Graphen | `ai_prompts.graph_data` | Knoten, Kanten, Metadaten |
| Output-Regeln | `ai_prompts` | `output_format`, `output_schema` |
| Fragenergänzungen | `ai_prompts.question_augmentations` | Optionale Standard-Fragen (Hybridmodell: Knoten > Prompt) |
| System-Reset | `ai_prompts` | `is_system_default`, `default_template` |
| Legacy-Pipeline-Configs | `pipeline_configs` | Module, Zeiträume, Stage-Slugs (parallel zum Unified System) |
| Workflow-Fragenkatalog | `workflow_question_catalog` | Fragetypen, Templates, Normalisierung |
### Bewusst nicht hardcodiert
- Prompt-Texte, Pipeline-Zusammensetzung, Workflow-Topologie
- Kategorie, Sichtbarkeit (`active`), Sortierung
- Output-Format und Schema pro Prompt
- Referenz vs. Inline in Pipeline-Stages
### Hardcodiert (Code / Env)
- Platzhalter-Definitionen und Resolver (`PLACEHOLDER_MAP`, Registry)
- LLM-Modell (`OPENROUTER_MODEL`)
- Default-Module und -Zeiträume in `/prompts/execute`
- Domänen-Kategorien im Frontend (`analysisCategories.js`)
- Meta-Prompts für Generate/Optimize (Admin-Tooling)
### Trennung: Template · Platzhalter · Kontext · Workflow
| Schicht | Ort | Rolle |
|---------|-----|-------|
| **Templates** | `ai_prompts.template`, `stages`, Knoten-Templates im Graph | Was an die KI geht |
| **Platzhalter** | `placeholder_resolver` + Registry | Semantische API-Keys `{{key}}`, Resolver-Funktionen |
| **Kontextdaten** | `execute_prompt_with_data` + Resolver → `data_layer/` | Werte für Platzhalter |
| **Workflows** | `graph_data` + `workflow_executor` | Ausführungsgraph, Verzweigung, Join, Aggregation |
### Durchsetzung: keine Sonderlogik außerhalb der Engine
**Konzeptionell:** Ein Executor (`execute_prompt` → `execute_prompt_with_data`) als Single Entry Point.
**Praktisch unvollständig:** Legacy-Pfade in `insights.py` (`/insights/run`, `/insights/pipeline`) mit eigener Template-Logik (`_prepare_template_vars`, `_render_template`) und direkten LLM-Calls; `History.jsx` nutzt noch `runInsight`. Kein technischer Guard (Lint/Policy), nur Konvention.
### Rollen und Berechtigungen
| Rolle | Darf |
|-------|------|
| **Admin** (`require_admin`) | Prompts/Workflows/Pipeline-Configs CRUD, Import/Export, Reset-to-default, Generate/Optimize, Platzhalter-Metadaten-ZIP |
| **Nutzer** (`require_auth`) | Aktive Prompts listen (ohne Pipeline-Slugs), ausführen (`/prompts/execute`), Preview, Platzhalter-Katalog, eigene Werte exportieren |
Workflow-Editor-Route (`/workflow-editor/:id`) ist nicht hinter `RequireAdmin`; Schreib-APIs sind admin-geschützt.
### Versionierung, Freigabe, Test
| Mechanismus | Status |
|-------------|--------|
| Prompt-Versionsverlauf in DB | ❌ Overwrite |
| Reset-to-default für System-Prompts | ✅ `is_system_default` + `default_template` |
| JSON Import/Export (Dev→Prod) | ✅ `/export-all`, `/import` |
| Admin-Test mit Debug | ✅ `debug=true`, UnifiedPromptModal |
| Preview ohne LLM | ✅ `POST /preview` |
| Platzhalter-Deprecation-Prozess | 📄 dokumentiert, nicht runtime-erzwungen |
| Formales Freigabe-Workflow | ❌ |
| Executor-E2E-Tests | ⚠️ punktuell (Modifier, Output-Compact) |
---
## Designprinzipien
### 1. Single Executor für Prompt-Ausführung
| | |
|---|---|
| **Prinzip** | Alle KI-Analysen laufen über `execute_prompt` / `execute_prompt_with_data`. |
| **Begründung** | Einheitliche Platzhalter-Auflösung, Debug, JSON-Validierung, Speicher-Metadaten. |
| **Quelle** | `backend/prompt_executor.py`; `POST /api/prompts/execute`; `Analysis.jsx` → `executeUnifiedPromptStream` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Legacy `insights.py` und teils `History.jsx` umgehen den Executor noch. |
### 2. Konfigurierbare Prompt-Bibliothek statt fest verdrahteter Texte
| | |
|---|---|
| **Prinzip** | Prompt-Inhalte und Workflows liegen in `ai_prompts`, nicht im Anwendungscode. |
| **Begründung** | Admins können Analysen anpassen, duplizieren, deaktivieren, ohne Deploy. |
| **Quelle** | Migration 020; `UnifiedPromptCreate`/`Update` in `models.py`; `AdminPromptsPage.jsx` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Parallel existieren noch `pipeline_configs` und hardcodierte Default-Module/Zeiträume. |
### 3. Drei Prompt-Typen mit klarer Verantwortung
| | |
|---|---|
| **Prinzip** | `base` = wiederverwendbarer Baustein; `pipeline` = sequenzielle Stages; `workflow` = Graph mit Verzweigung. |
| **Begründung** | Komposition ohne Copy-Paste; Reference-Prompts in Pipelines (`source: 'reference'`). |
| **Quelle** | `execute_prompt()` Typ-Verzweigung; `StagePromptCreate` in `models.py` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Pipeline-Stages laufen sequentiell, obwohl konzeptionell „parallel“; `workflow_definitions` und `ai_prompts.graph_data` doppelt. |
### 4. Platzhalter als API-Verträge (Registry)
| | |
|---|---|
| **Prinzip** | Platzhalter sind registrierte, dokumentierte Verträge — keine freien Prompt-Hilfsvariablen. |
| **Begründung** | Konsistenz für Injektion, GUI-Picker, Export, Validierung. |
| **Quelle** | `PLACEHOLDER_REGISTRY_FRAMEWORK.md`; `docs/PLACEHOLDER_GOVERNANCE.md`; `import placeholder_registrations` in `main.py` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Duplikat `PLACEHOLDER_MAP` in `placeholder_resolver.py` neben Registry; Metadaten teils noch Legacy. |
### 5. Trennung Template (Was) vs. Resolver (Daten)
| | |
|---|---|
| **Prinzip** | Templates enthalten nur `{{keys}}`; Berechnung liegt in Resolver/Data Layer. |
| **Begründung** | Prompt-Autoren ändern Text, nicht Berechnungslogik. |
| **Quelle** | `resolve_placeholders()` in `prompt_executor.py`; Registry-Felder `resolver_function`, `data_layer_function` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | `execute_prompt_with_data` lädt zusätzlich Roh-SQL pro Modul — zweite Kontext-Schicht. |
### 6. Layer-1-Daten vs. Layer-2a-Prompt-Injektion
| | |
|---|---|
| **Prinzip** | Berechnungen in `data_layer/`; Prompt Engine konsumiert nur formatierte Werte. |
| **Begründung** | Single Source of Truth für Charts, Platzhalter, KI. |
| **Quelle** | Phase-0c-Architektur; Registry-Felder `data_layer_module` / `layer_1_decision` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Legacy `_prepare_template_vars` in `insights.py` umgeht Data Layer. |
### 7. Transparenz durch Debug- und Preview-Modus
| | |
|---|---|
| **Prinzip** | Aufgelöste/unaufgelöste Platzhalter, Final-Prompt und Stage-Outputs sind inspizierbar; Preview ohne LLM. |
| **Begründung** | Admin kann Prompts testen und Wertetabelle/Expertenmodus speisen. |
| **Quelle** | `debug`-Parameter; `/preview`; `UnifiedPromptModal` Test-Button; `ai_insights.metadata` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Debug-Daten in Responses können groß/sensibel sein; kein separates Staging. |
### 8. Wiederverwendbare Base-Prompts via Reference
| | |
|---|---|
| **Prinzip** | Pipeline-Stages referenzieren Slugs statt Templates zu duplizieren. |
| **Begründung** | Ein Baustein, mehrere Workflows; zentral wartbar. |
| **Quelle** | `source == 'reference'` in `execute_pipeline_prompt()` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Keine Referenz-Versionierung; Änderung am Base-Prompt wirkt sofort auf alle Referenzen. |
### 9. Strukturierte LLM-Ausgaben per Output-Format
| | |
|---|---|
| **Prinzip** | Pro Prompt/Prompt-Def: `output_format: text\|json`, optional `output_schema`; Pipeline-Outputs als Stage-Keys im Kontext. |
| **Begründung** | Maschinenlesbare Zwischenergebnisse für Multi-Stage und Wertetabelle. |
| **Quelle** | `validate_json_output()`; Stage `output_key` in Pipeline |
| **Tragfähigkeit** | **mittel** |
| **Einschränkung** | JSON-Schema-Validierung ist TODO (`jsonschema`); Markdown-Unwrap als Heuristik. |
### 10. Admin-only Konfiguration, User-only Ausführung
| | |
|---|---|
| **Prinzip** | Schreibende Prompt-/Workflow-Operationen nur mit `require_admin`. |
| **Begründung** | Produktions-Prompts sind Systemkonfiguration, nicht Nutzerdaten. |
| **Quelle** | `require_admin` in `routers/prompts.py`; `RequireAdmin` für `/admin/prompts` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | `/workflow-editor/:id` ohne Frontend-Admin-Gate; `/prompts/execute` ohne `check_feature_access` (Legacy-Pfad in `insights.py` hat Enforcement). |
### 11. Import/Export als Umgebungs-Sync
| | |
|---|---|
| **Prinzip** | Prompt-Sätze als JSON exportierbar/importierbar (Dev→Prod). |
| **Begründung** | Konfiguration versionierbar in Git, nicht in der App-DB. |
| **Quelle** | `GET /export-all`, `POST /import` in `routers/prompts.py`; Admin-UI Buttons |
| **Tragfähigkeit** | **mittel** |
| **Einschränkung** | Kein Diff, keine Merge-Strategie, kein Rollback; Overwrite-Flag manuell. |
### 12. Workflow-Erweiterung: Graph + Fragenergänzungen + Signale
| | |
|---|---|
| **Prinzip** | Workflows als Knoten/Kanten-Graph; optionale Fragen am Knoten; Normalisierung/Logic/Join als Engine-Schicht. |
| **Begründung** | Bedingte, verzweigte Analysen jenseits linearer Pipelines. |
| **Quelle** | `workflow_executor.py`; Migration 034; `question_augmenter.py` |
| **Tragfähigkeit** | **mittel** |
| **Einschränkung** | Hohe Komplexität; zwei Speicherorte (`graph_data` vs. `workflow_definitions`); Jinja2 im Workflow-Pfad zusätzlich zu `{{}}`-Resolver. |
### 13. Platzhalter-Modifier für KI-Kontext
| | |
|---|---|
| **Prinzip** | `{{key\|d}}` (Wert + Beschreibung), `{{key\|x}}` (Erklärung ohne Zahl) über Katalog-Metadaten. |
| **Begründung** | Prompts können Kontext für das Modell reichhaltiger machen ohne Template-Duplikate. |
| **Quelle** | `resolve_placeholders()` Modifier-Logik; `get_placeholder_catalog()` |
| **Tragfähigkeit** | **mittel** |
| **Einschränkung** | Modifier-Syntax ad hoc; Katalog-Pflicht für sinnvolle `\|x`-Nutzung. |
### 14. System-Prompt-Reset statt DB-Versionierung
| | |
|---|---|
| **Prinzip** | Shipped Prompts mit `is_system_default` + `default_template`; Admin-Reset auf Original. |
| **Begründung** | Schutz vor irreversiblen Fehlkonfigurationen ohne vollständiges Versionsmodell. |
| **Quelle** | Migration 019; `POST /{prompt_id}/reset-to-default` |
| **Tragfähigkeit** | **mittel** |
| **Einschränkung** | Nur ein Default-Snapshot; keine Historie benutzerdefinierter Änderungen. |
### 15. Governance für Platzhalter-Änderungen
| | |
|---|---|
| **Prinzip** | Breaking Changes nur über Deprecation + Replacement; semantische Verträge dokumentiert. |
| **Begründung** | Prompts in Produktion brechen nicht still. |
| **Quelle** | `docs/PLACEHOLDER_GOVERNANCE.md` §4 |
| **Tragfähigkeit** | **mittel** (prozessual) |
| **Einschränkung** | Prozess in Doku, nicht im Runtime erzwungen; Checkliste verweist noch auf Legacy-Dateien. |
---
## Nicht übernehmen
Muster, die sich nicht bewährt haben oder zu produktspezifisch sind — bei Neuentwicklung vermeiden:
1. **Parallele Ausführungspfade** — Legacy `insights.py` (`/insights/run`, `/insights/pipeline`) mit eigener Template-Engine und LLM-Calls neben `prompt_executor`; Frontend-Split (`Analysis` vs. `History`).
2. **Doppelte Metadaten für Platzhalter** — `PLACEHOLDER_MAP`, Registry, `placeholder_metadata_complete.py` und Katalog-Fallbacks parallel; erzeugt Sync-Risiko (114 Keys müssen deckungsgleich bleiben).
3. **Zwei Pipeline-Modelle gleichzeitig** — `pipeline_configs` (3 fixe Stages) und Unified `type=pipeline` in `ai_prompts`; Migration 020 migriert, Tabelle bleibt aktiv.
4. **Zwei Workflow-Speicher** — `workflow_definitions.graph` und `ai_prompts.graph_data`; unklare Single Source of Truth.
5. **Roh-SQL-Kontextladung im Executor** — `execute_prompt_with_data` lädt Modul-Rohdaten per SQL, obwohl Resolver/Data Layer existieren; Domänenwissen in der Engine.
6. **Hardcodierte Execute-Defaults** — Module/Zeiträume in `/execute` fest verdrahtet statt aus Prompt-/Pipeline-Konfiguration.
7. **Fehlende Feature-Enforcement-Konsistenz** — `check_feature_access` auf Legacy-Insights, nicht auf `/prompts/execute`.
8. **„Parallel“ als sequentiell implementiert** — Pipeline-Stages kommentiert als parallel, Code sequentiell; irreführendes Modell.
9. **Unvollständige Output-Validierung** — JSON-Parse + Markdown-Unwrap, Schema-Check auskommentiert/TODO.
10. **Workflow-Editor ohne klares Admin-Gate in Routing** — Schreib-API geschützt, UI-Route für alle Authentifizierten erreichbar.
11. **Domänen-spezifische Hardcodings in der Engine** — Kategorien (`körper`, `ernährung`, …), deutsche Meta-Prompts für Generate/Optimize, Fitness-Kontext in Prompt-Generator.
12. **Kein integriertes Prompt-Versions- und Freigabemodell** — Overwrite + JSON-Export ersetzt keine Revision/Review/Publish-Pipeline.
13. **Issue #51 (Seitenzuordnung) nicht umgesetzt** — Prompt-Verfügbarkeit kontextuell nicht konfigurierbar; alles über zentrale Analyse-Seite.
14. **Globales LLM-Modell per Env** — `workflow_executor` übergibt Modell pro Call, `call_openrouter` ignoriert es; keine prompt-spezifische Modellwahl trotz API-Shape.
---
## Verwandte Dokumentation
- Fachliche Spec: [AI_PROMPTS.md](../../functional/AI_PROMPTS.md)
- Platzhalter-Registry: [PLACEHOLDER_REGISTRY_FRAMEWORK.md](../../technical/PLACEHOLDER_REGISTRY_FRAMEWORK.md)
- Platzhalter-Governance: [PLACEHOLDER_GOVERNANCE.md](../../../../docs/PLACEHOLDER_GOVERNANCE.md)
- Issue #28 (Unified Prompt System): abgeschlossen, siehe `CLAUDE.md`
- Issue #51 (Prompt-Seitenzuordnung): [issue-51-prompt-page-assignment.md](../../../../docs/issues/issue-51-prompt-page-assignment.md)
- **Serie (abgeschlossen):** [Index](./README.md) · [Jinkendo Foundation](../README.md) · Dokumente #1–#9