false,'error'=>'POST only']); exit; } $input = json_decode(file_get_contents('php://input'), true); $query = trim($input['query'] ?? $input['topic'] ?? ''); $dialect = $input['dialect'] ?? 'postgresql'; if (strlen($query) < 3) { echo json_encode(['ok'=>false,'error'=>'query too short']); exit; } $query = substr($query, 0, 800); $prompt = "Expert SQL $dialect. Traduis la demande en langue naturelle en SQL:\n\n\"$query\"\n\n" . "Retourne UNIQUEMENT un JSON:\n" . "{\n" . " \"sql\": \"SELECT ... FROM ... WHERE ...;\",\n" . " \"explanation\": \"Bref explication de ce que fait la requete\",\n" . " \"tables_needed\": [\"table1\",\"table2\"],\n" . " \"dialect\": \"$dialect\",\n" . " \"complexity\": \"simple|medium|complex\",\n" . " \"suggested_indexes\": [\"CREATE INDEX ...\"]\n" . "}\n\n" . "IMPORTANT:\n" . "- SQL valide et optimise\n" . "- Utiliser jointures appropriees (INNER/LEFT/RIGHT)\n" . "- Mettre ORDER BY si sens\n" . "- Preciser LIMIT si pertinent\n" . "- Si agrecation, utiliser GROUP BY + HAVING\n" . "- Explanation en francais\n" . "- JSON UNIQUEMENT, aucun texte avant/apres"; $ch = curl_init('http://127.0.0.1:4000/v1/chat/completions'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_POSTFIELDS => json_encode([ 'model' => 'auto', 'messages' => [['role'=>'user', 'content'=>$prompt]], 'max_tokens' => 2000, 'temperature' => 0.3 ]), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_TIMEOUT => 60, ]); $resp = curl_exec($ch); $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($http !== 200) { echo json_encode(['ok'=>false,'error'=>"LLM HTTP $http"]); exit; } $data = json_decode($resp, true); $content_raw = $data['choices'][0]['message']['content'] ?? ''; // Balanced JSON extract if (preg_match('/```(?:json)?\s*\n?(.*?)\n?```/s', $content_raw, $m)) { $content_raw = $m[1]; } $jstart = strpos($content_raw, '{'); if ($jstart !== false) { $depth = 0; $jend = -1; for ($i = $jstart; $i < strlen($content_raw); $i++) { if ($content_raw[$i] === '{') $depth++; elseif ($content_raw[$i] === '}') { $depth--; if ($depth === 0) { $jend = $i; break; } } } if ($jend > $jstart) $content_raw = substr($content_raw, $jstart, $jend - $jstart + 1); } $result = json_decode($content_raw, true); if (!$result || !isset($result['sql'])) { echo json_encode(['ok'=>false,'error'=>'invalid JSON','raw'=>substr($content_raw,0,300)]); exit; } echo json_encode([ 'ok' => true, 'sql' => $result['sql'], 'explanation' => $result['explanation'] ?? '', 'tables_needed' => $result['tables_needed'] ?? [], 'dialect' => $result['dialect'] ?? $dialect, 'complexity' => $result['complexity'] ?? 'medium', 'suggested_indexes' => $result['suggested_indexes'] ?? [], 'result' => $result['sql'], // for inline kind render ]);