configRepo->getAuthorProfile($profileId); if ($profile === null) { return null; } $config = json_decode($profile['content'] ?? '{}', true); if ($config === null) { return null; } $parts = []; if (isset($config['stimme']['ton'])) { $parts[] = 'Ton: ' . $config['stimme']['ton']; } if (isset($config['stimme']['perspektive'])) { $parts[] = 'Perspektive: ' . $config['stimme']['perspektive']; } if (isset($config['stil']['fachsprache']) && $config['stil']['fachsprache']) { $parts[] = 'Verwende Fachsprache'; } if (isset($config['stil']['beispiele']) && $config['stil']['beispiele'] === 'häufig') { $parts[] = 'Nutze häufig Beispiele'; } if (isset($config['stil']['listen']) && $config['stil']['listen'] === 'bevorzugt') { $parts[] = 'Bevorzuge Listen und Bullet-Points'; } if (isset($config['tabus']) && is_array($config['tabus'])) { $parts[] = 'Vermeide: ' . implode(', ', $config['tabus']); } if ($parts === []) { return null; } return 'Schreibstil (' . ($profile['name'] ?? 'Profil') . '): ' . implode('. ', $parts) . '.'; } /** * Load system prompt by ID. * * @throws \RuntimeException When prompt cannot be parsed */ public function getSystemPrompt(int $promptId): ?string { if ($promptId === 0) { return null; } $prompt = $this->configRepo->getSystemPrompt($promptId); if ($prompt === null) { return null; } $content = json_decode($prompt['content'] ?? '{}', true); return $content['prompt'] ?? null; } /** * Load structure prompt. * * @throws \RuntimeException When structure cannot be parsed */ public function getStructurePrompt(int $structureId): ?string { if ($structureId === 0) { return null; } $structure = $this->configRepo->getStructure($structureId); if ($structure === null) { return null; } $name = $structure['name'] ?? 'Struktur'; $config = json_decode($structure['content'] ?? '{}', true); if ($config === null) { return null; } $parts = ["Formatiere deine Antwort als: {$name}"]; if (isset($config['sections']) && is_array($config['sections'])) { $parts[] = 'Struktur: ' . implode(' → ', $config['sections']); } if (isset($config['max_chars'])) { $parts[] = 'Maximale Länge: ' . $config['max_chars'] . ' Zeichen'; } if (isset($config['min_words'])) { $parts[] = 'Mindestens ' . $config['min_words'] . ' Wörter'; } if (isset($config['max_words'])) { $parts[] = 'Maximal ' . $config['max_words'] . ' Wörter'; } if (isset($config['format']) && $config['format'] === 'qa') { $parts[] = 'FAQ mit ' . ($config['min_questions'] ?? 3) . ' Paaren'; } if (isset($config['hashtags']) && $config['hashtags']) { $parts[] = 'Füge passende Hashtags hinzu'; } if (isset($config['cta']) && $config['cta']) { $parts[] = 'Schließe mit einem Call-to-Action ab'; } return implode('. ', $parts) . '.'; } /** * Get structure name by ID. */ public function getStructureName(int $structureId): ?string { if ($structureId === 0) { return null; } $structure = $this->configRepo->getStructure($structureId); return $structure['name'] ?? null; } /** * Compose effective system prompt from components. */ public function composeSystemPrompt( int $systemPromptId, int $structureId, int $authorProfileId, bool $hasContext, string $defaultRagPrompt, string $defaultNoContextPrompt ): string { $systemPrompt = $this->getSystemPrompt($systemPromptId); $structurePrompt = $this->getStructurePrompt($structureId); $stylePrompt = $this->getStylePrompt($authorProfileId); // Add structure to system prompt if ($structurePrompt !== null) { $systemPrompt = ($systemPrompt ?? '') . "\n\n" . $structurePrompt; } // Use default if no system prompt $effectivePrompt = $systemPrompt ?? ($hasContext ? $defaultRagPrompt : $defaultNoContextPrompt); // Add style prompt if ($stylePrompt !== null && $stylePrompt !== '') { $effectivePrompt .= "\n\n" . $stylePrompt; } return $effectivePrompt; } }