# 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