'Profile ID is missing.']); exit; } $profile = null; try { $pdo = db(); $stmt = $pdo->prepare("SELECT * FROM gtm_profiles WHERE id = ?"); $stmt->execute([$profile_id]); $profile = $stmt->fetch(PDO::FETCH_ASSOC); } catch (PDOException $e) { error_log($e->getMessage()); echo json_encode(['error' => 'Database error while fetching profile.']); exit; } if (!$profile) { echo json_encode(['error' => 'Profile not found.']); exit; } // --- Prompt Engineering --- $profile_details = " - Ideal Customer Profile (ICP): {$profile['icp']} - Market Size: {$profile['market_size']} - Sales Motions: {$profile['sales_motions']} - Organization Size: {$profile['org_size']} - Sells What: {$profile['sells_what']} - Business Name: {$profile['business_name']} "; $prompt = "You are an expert Go-To-Market strategist. Based on the following company profile, generate a clear, customized GTM process flow diagram using Mermaid.js syntax. Company Profile: {$profile_details} Instructions: 1. The diagram should visualize the ideal GTM workflow from customer acquisition to retention/upselling. 2. The output MUST be a valid Mermaid.js graph, starting with 'graph TD;'. 3. Use the format: A[\"Step 1\"] --> B[\"Step 2\"] --> C[\"Step 3\"]; 4. **Crucially, node text MUST be enclosed in double quotes**, like A[\"This is a node\"]; 5. The steps should be logical and tailored to the company's profile (e.g., a product-led motion should have steps like 'Free Tier Signup', while an enterprise motion should have 'SDR Touchpoint'). 6. Make the flow concise, with 5 to 7 key steps. 7. Do not include any explanation, just the Mermaid.js code. Example: graph TD; A[\"Lead Gen via Social Media\"] --> B[\"Free Tier Signup (Product-Led)\"]; B --> C[\"Auto-Onboarding Email\"]; C --> D[\"SDR Touchpoint\"]; D --> E[\"Upsell via Partner Integration\"];"; // --- API Call via cURL --- $payload = [ 'model' => 'gpt-4o', 'messages' => [ ['role' => 'system', 'content' => 'You are a GTM strategy expert that only outputs Mermaid.js code.'], ['role' => 'user', 'content' => $prompt] ], 'max_tokens' => 300, 'temperature' => 0.5, ]; $ch = curl_init($openai_api_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Authorization: Bearer ' . $openai_api_key ]); $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // --- Process Response --- if ($http_code !== 200 || $response === false) { error_log("OpenAI API Error: HTTP {$http_code} - " . $response); echo json_encode(['error' => 'Failed to generate diagram from AI. The API returned an error.']); exit; } $result = json_decode($response, true); $diagram = $result['choices'][0]['message']['content'] ?? 'graph TD; A[Error: Could not parse AI response];'; // --- Log the raw AI response for debugging --- $log_file = __DIR__ . '/../ai_responses.log'; $log_entry = "---" . date('Y-m-d H:i:s') . " --- " . $diagram . "\n\n"; file_put_contents($log_file, $log_entry, FILE_APPEND); // Clean up the response and extract the Mermaid code $diagram = trim($diagram); // Regex to find Mermaid code block, with or without backticks and optional "mermaid" label if (preg_match('/```(?:mermaid)?\s*(graph\s(TD|LR|BT|RL);?[\s\S]*?)```|^(graph\s(TD|LR|BT|RL);?[\s\S]*)/', $diagram, $matches)) { // We have two possible capture groups for the main content $mermaid_code = !empty($matches[1]) ? $matches[1] : $matches[3]; $diagram = trim($mermaid_code); } else { // If no match, log the bad response and set an error for the user error_log("Invalid AI response format: " . $diagram); $diagram = "graph TD; A[Error: Invalid AI response format.];"; } echo json_encode(['diagram' => $diagram]);