, , ). Zwróć odpowiedź WYŁĄCZNIE w formacie JSON: {"title": "tytuł artykułu", "content": "treść HTML artykułu"}'; private Client $client; public function __construct() { $this->client = new Client([ 'base_uri' => 'https://api.openai.com/v1/', 'timeout' => 120, ]); } public function generateArticle(string $topicName, string $topicDescription, array $existingTitles): ?array { $apiKey = Config::getDbSetting('openai_api_key', Config::get('OPENAI_API_KEY')); $model = Config::getDbSetting('openai_model', Config::get('OPENAI_MODEL', 'gpt-4o')); $minWords = Config::getDbSetting('article_min_words', '800'); $maxWords = Config::getDbSetting('article_max_words', '1200'); $systemPromptTemplate = Config::getDbSetting('article_generation_prompt', self::DEFAULT_ARTICLE_PROMPT_TEMPLATE); if (!is_string($systemPromptTemplate) || trim($systemPromptTemplate) === '') { $systemPromptTemplate = self::DEFAULT_ARTICLE_PROMPT_TEMPLATE; } if (empty($apiKey)) { Logger::error('OpenAI API key not configured', 'openai'); return null; } $existingList = !empty($existingTitles) ? implode("\n- ", $existingTitles) : '(brak - to pierwszy artykuł z tego tematu)'; $systemPrompt = strtr($systemPromptTemplate, [ '{min_words}' => (string) $minWords, '{max_words}' => (string) $maxWords, ]); $userPrompt = "Napisz artykuł na temat: {$topicName}\n"; if (!empty($topicDescription)) { $userPrompt .= "Wytyczne: {$topicDescription}\n"; } $userPrompt .= "\nWAŻNE - NIE pisz o następujących tematach, bo artykuły o nich już istnieją na stronie:\n- {$existingList}"; $fullPrompt = $systemPrompt . "\n\n" . $userPrompt; try { $response = $this->client->post('chat/completions', [ 'headers' => [ 'Authorization' => "Bearer {$apiKey}", 'Content-Type' => 'application/json', ], 'json' => [ 'model' => $model, 'messages' => [ ['role' => 'system', 'content' => $systemPrompt], ['role' => 'user', 'content' => $userPrompt], ], 'temperature' => 0.8, 'max_tokens' => 4000, 'response_format' => ['type' => 'json_object'], ], ]); $data = json_decode($response->getBody()->getContents(), true); $content = $data['choices'][0]['message']['content'] ?? null; if (!$content) { Logger::error('Empty response from OpenAI', 'openai'); return null; } $article = json_decode($content, true); if (!isset($article['title']) || !isset($article['content'])) { Logger::error('Invalid JSON structure from OpenAI: ' . $content, 'openai'); return null; } Logger::info("Generated article: {$article['title']}", 'openai'); return [ 'title' => $article['title'], 'content' => $article['content'], 'model' => $model, 'prompt' => $fullPrompt, ]; } catch (GuzzleException $e) { Logger::error('OpenAI API error: ' . $e->getMessage(), 'openai'); return null; } } }