base_url = rtrim($base_url, '/'); $this->api_key = $api_key; $this->default_model = $default_model; $this->timeout = 60; // Default 60 second timeout } /** * Set request timeout */ public function set_timeout($timeout) { $this->timeout = $timeout; return $this; } /** * Make a chat completion request */ public function chat_completion($params) { // Set default model if not provided if (!isset($params['model']) && $this->default_model) { $params['model'] = $this->default_model; } // Validate required parameters if (!isset($params['model'])) { throw new Exception('Model is required for chat completion'); } if (!isset($params['messages']) || empty($params['messages'])) { throw new Exception('Messages array is required for chat completion'); } // Set default parameters $params = array_merge(array( 'max_tokens' => 1000, 'temperature' => 0.7, 'top_p' => 1.0, 'frequency_penalty' => 0, 'presence_penalty' => 0 ), $params); return $this->make_request('POST', '/chat/completions', $params); } /** * Make a text completion request (for older models) */ public function text_completion($params) { // Set default model if not provided if (!isset($params['model']) && $this->default_model) { $params['model'] = $this->default_model; } // Validate required parameters if (!isset($params['model'])) { throw new Exception('Model is required for text completion'); } if (!isset($params['prompt'])) { throw new Exception('Prompt is required for text completion'); } // Set default parameters $params = array_merge(array( 'max_tokens' => 1000, 'temperature' => 0.7, 'top_p' => 1.0, 'frequency_penalty' => 0, 'presence_penalty' => 0 ), $params); return $this->make_request('POST', '/completions', $params); } /** * List available models */ public function list_models() { return $this->make_request('GET', '/models'); } /** * Get model information */ public function get_model($model_id) { return $this->make_request('GET', '/models/' . $model_id); } /** * Create embeddings */ public function create_embeddings($params) { // Set default model if not provided if (!isset($params['model']) && $this->default_model) { $params['model'] = $this->default_model; } // Validate required parameters if (!isset($params['model'])) { throw new Exception('Model is required for embeddings'); } if (!isset($params['input'])) { throw new Exception('Input is required for embeddings'); } return $this->make_request('POST', '/embeddings', $params); } /** * Create image generation request (DALL-E style) */ public function create_image($params) { // Validate required parameters if (!isset($params['prompt'])) { throw new Exception('Prompt is required for image generation'); } // Set defaults $params = array_merge(array( 'n' => 1, 'size' => '512x512', 'response_format' => 'url' ), $params); return $this->make_request('POST', '/images/generations', $params); } /** * Moderate content */ public function moderate_content($params) { if (!isset($params['input'])) { throw new Exception('Input is required for moderation'); } return $this->make_request('POST', '/moderations', $params); } /** * Create fine-tuning job */ public function create_fine_tune($params) { if (!isset($params['training_file'])) { throw new Exception('Training file is required for fine-tuning'); } return $this->make_request('POST', '/fine-tunes', $params); } /** * List fine-tuning jobs */ public function list_fine_tunes() { return $this->make_request('GET', '/fine-tunes'); } /** * Get fine-tuning job */ public function get_fine_tune($fine_tune_id) { return $this->make_request('GET', '/fine-tunes/' . $fine_tune_id); } /** * Cancel fine-tuning job */ public function cancel_fine_tune($fine_tune_id) { return $this->make_request('POST', '/fine-tunes/' . $fine_tune_id . '/cancel'); } /** * Upload file */ public function upload_file($file_path, $purpose = 'fine-tune') { if (!file_exists($file_path)) { throw new Exception('File not found: ' . $file_path); } // For file uploads, we need to use a different approach $boundary = wp_generate_password(16, false); $file_content = file_get_contents($file_path); $filename = basename($file_path); $body = ''; $body .= '--' . $boundary . "\r\n"; $body .= 'Content-Disposition: form-data; name="purpose"' . "\r\n\r\n"; $body .= $purpose . "\r\n"; $body .= '--' . $boundary . "\r\n"; $body .= 'Content-Disposition: form-data; name="file"; filename="' . $filename . '"' . "\r\n"; $body .= 'Content-Type: application/octet-stream' . "\r\n\r\n"; $body .= $file_content . "\r\n"; $body .= '--' . $boundary . '--' . "\r\n"; $response = wp_remote_post($this->base_url . '/files', array( 'headers' => array( 'Authorization' => 'Bearer ' . $this->api_key, 'Content-Type' => 'multipart/form-data; boundary=' . $boundary, 'User-Agent' => 'TigerStyle-SEO/' . TIGERSTYLE_HEAT_VERSION ), 'body' => $body, 'timeout' => $this->timeout )); return $this->process_response($response); } /** * List files */ public function list_files() { return $this->make_request('GET', '/files'); } /** * Get file */ public function get_file($file_id) { return $this->make_request('GET', '/files/' . $file_id); } /** * Delete file */ public function delete_file($file_id) { return $this->make_request('DELETE', '/files/' . $file_id); } /** * Make HTTP request to OpenAI API */ private function make_request($method, $endpoint, $params = null) { $url = $this->base_url . $endpoint; $args = array( 'method' => $method, 'headers' => array( 'Authorization' => 'Bearer ' . $this->api_key, 'Content-Type' => 'application/json', 'User-Agent' => 'TigerStyle-SEO/' . TIGERSTYLE_HEAT_VERSION ), 'timeout' => $this->timeout ); if ($params && ($method === 'POST' || $method === 'PUT' || $method === 'PATCH')) { $args['body'] = json_encode($params); } elseif ($params && $method === 'GET') { $url = add_query_arg($params, $url); } $response = wp_remote_request($url, $args); return $this->process_response($response); } /** * Process API response */ private function process_response($response) { if (is_wp_error($response)) { throw new Exception('HTTP Request failed: ' . $response->get_error_message()); } $status_code = wp_remote_retrieve_response_code($response); $body = wp_remote_retrieve_body($response); // Try to decode JSON response $data = json_decode($body, true); if ($status_code >= 400) { $error_message = 'HTTP ' . $status_code; if ($data && isset($data['error'])) { if (is_string($data['error'])) { $error_message .= ': ' . $data['error']; } elseif (isset($data['error']['message'])) { $error_message .= ': ' . $data['error']['message']; } } else { $error_message .= ': ' . $body; } throw new Exception($error_message); } return $data; } /** * Helper method to create a simple chat message */ public function simple_chat($message, $system_prompt = null, $model = null) { $messages = array(); if ($system_prompt) { $messages[] = array('role' => 'system', 'content' => $system_prompt); } $messages[] = array('role' => 'user', 'content' => $message); $params = array('messages' => $messages); if ($model) { $params['model'] = $model; } return $this->chat_completion($params); } /** * Helper method to extract text from chat response */ public function extract_text($response) { if (isset($response['choices'][0]['message']['content'])) { return trim($response['choices'][0]['message']['content']); } if (isset($response['choices'][0]['text'])) { return trim($response['choices'][0]['text']); } throw new Exception('Unable to extract text from response'); } /** * Helper method for SEO-specific prompts */ public function generate_meta_description($content, $max_length = 155) { $prompt = "Generate an SEO-optimized meta description (maximum {$max_length} characters) for the following content. The description should be compelling, include relevant keywords, and encourage clicks:\n\n{$content}"; $response = $this->simple_chat($prompt, "You are an SEO expert specializing in creating compelling meta descriptions that improve search engine rankings and click-through rates."); return $this->extract_text($response); } /** * Helper method to generate SEO title */ public function generate_seo_title($content, $max_length = 60) { $prompt = "Generate an SEO-optimized title (maximum {$max_length} characters) for the following content. The title should be compelling, include relevant keywords, and be click-worthy:\n\n{$content}"; $response = $this->simple_chat($prompt, "You are an SEO expert specializing in creating compelling titles that improve search engine rankings and click-through rates."); return $this->extract_text($response); } /** * Helper method to extract keywords */ public function extract_keywords($content, $count = 10) { $prompt = "Extract the {$count} most important SEO keywords from the following content. Return only the keywords, separated by commas:\n\n{$content}"; $response = $this->simple_chat($prompt, "You are an SEO expert specializing in keyword research and content analysis."); $keywords = $this->extract_text($response); return array_map('trim', explode(',', $keywords)); } /** * Helper method to analyze content for SEO */ public function analyze_seo_content($content) { $prompt = "Analyze the following content for SEO optimization and provide specific recommendations:\n\n{$content}"; $response = $this->simple_chat($prompt, "You are an SEO expert. Analyze content and provide actionable SEO recommendations including keyword usage, content structure, readability, and technical SEO factors."); return $this->extract_text($response); } }