*/ private const array DEFAULTS = [ 'specs_research' => <<<'PROMPT' You are a hardware specifications expert. Extract the technical specifications for the {{articleType}}: "{{subject}}". Web search results: {{searchResults}} Based on the search results above, list all technical specifications including: processor, RAM, storage variants, display size and resolution, GPU, battery capacity, ports, connectivity, weight, dimensions, OS, and any other relevant specs. Be specific and accurate. If a spec is not found in the search results, omit it rather than guessing. PROMPT, 'ebay_title' => <<<'PROMPT' Create a concise eBay listing title (max 80 characters) for this {{typeName}}. Device: {{deviceLabel}} Use the most important specifications. Include condition if not "new". Condition: {{condition}} {{specsSection}} Return ONLY the title text, no quotes, no explanation. PROMPT, 'ebay_description' => <<<'PROMPT' Create a professional eBay listing description in German for this {{typeName}}. Device: {{deviceLabel}} Include all available specifications in a clear, structured format. Mention the condition: {{condition}}. {{conditionNotes}} {{specsSection}} Use HTML formatting (ul, li, strong tags). Max 2000 characters. PROMPT, 'vision_analyze' => <<<'PROMPT' Look at this nameplate/label photo of IT hardware. Extract the manufacturer, any model identifier (name or number), and serial number visible on the label. If the label shows both a product name (e.g. "ThinkPad T490s") and a part/product code (e.g. "20NXS0BA00"), put the product name in MODEL_NAME and the code in MODEL_NUMBER. If only one model field is visible (regardless of whether it looks like a name or a code), put it in MODEL_NAME and leave MODEL_NUMBER empty. Do not guess or add information not visible on the label. Respond in exactly this format (use empty string if not visible): MANUFACTURER: MODEL_NAME: MODEL_NUMBER: SERIAL: PROMPT, 'json_coding' => <<<'PROMPT' Convert the following hardware specifications to a JSON object. The JSON must use these exact keys (UUIDs) and follow the indicated value formats: {{schema}} {{missingHint}} Specifications text: {{specsText}} Return ONLY valid JSON. No explanation. No markdown. No extra text. JSON: PROMPT, ]; public function __construct( private readonly PromptTemplateRepositoryInterface $repository, ) { } /** * Renders a prompt template by key, substituting {{variable}} placeholders. * * @param array $variables */ public function render(string $key, array $variables = []): string { $template = $this->repository->findByKey($key); $body = $template?->getBody() ?? self::DEFAULTS[$key] ?? throw new \InvalidArgumentException("Unknown prompt template key: {$key}"); $search = array_map(static fn (string $k) => '{{'.$k.'}}', array_keys($variables)); return str_replace($search, array_values($variables), $body); } /** * Returns all known prompt keys with their available variables. * * @return array> */ public static function knownKeys(): array { return [ 'specs_research' => ['articleType', 'subject', 'searchResults'], 'ebay_title' => ['typeName', 'deviceLabel', 'condition', 'specsSection'], 'ebay_description' => ['typeName', 'deviceLabel', 'condition', 'conditionNotes', 'specsSection'], 'vision_analyze' => [], 'json_coding' => ['schema', 'missingHint', 'specsText'], ]; } /** @return string */ public static function defaultFor(string $key): string { return self::DEFAULTS[$key] ?? ''; } }