103 lines
4.1 KiB
PHP
103 lines
4.1 KiB
PHP
<?php
|
|
/**
|
|
* ambre-tool-pptx.php - Premium PowerPoint generation
|
|
* Input: JSON {topic}
|
|
* Output: JSON {ok, url, slides, title}
|
|
*/
|
|
header('Content-Type: application/json');
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
echo json_encode(['ok'=>false, 'error'=>'POST only']); exit;
|
|
}
|
|
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$topic = trim($input['topic'] ?? '');
|
|
if (strlen($topic) < 3) {
|
|
echo json_encode(['ok'=>false, 'error'=>'topic too short']); exit;
|
|
}
|
|
$topic = substr($topic, 0, 500);
|
|
|
|
$prompt = "Genere une presentation PowerPoint professionnelle sur: \"$topic\"\n\n"
|
|
. "Retourne UNIQUEMENT du JSON valide:\n"
|
|
. "{\n"
|
|
. " \"title\": \"Titre principal\",\n"
|
|
. " \"subtitle\": \"Sous-titre\",\n"
|
|
. " \"author\": \"WEVAL Consulting\",\n"
|
|
. " \"slides\": [\n"
|
|
. " {\"type\":\"title\", \"title\":\"Titre\", \"subtitle\":\"...\"},\n"
|
|
. " {\"type\":\"content\", \"title\":\"Section 1\", \"bullets\":[\"Point 1\", \"Point 2\"]},\n"
|
|
. " {\"type\":\"two_column\", \"title\":\"Comparaison\", \"left\":{\"heading\":\"Avant\", \"items\":[...]}, \"right\":{\"heading\":\"Apres\", \"items\":[...]}},\n"
|
|
. " {\"type\":\"stats\", \"title\":\"Chiffres cles\", \"stats\":[{\"value\":\"80%\", \"label\":\"Libelle\"}]},\n"
|
|
. " {\"type\":\"table\", \"title\":\"Tableau\", \"headers\":[\"A\",\"B\"], \"rows\":[[\"v1\",\"v2\"]]},\n"
|
|
. " {\"type\":\"conclusion\", \"title\":\"Conclusion\", \"text\":\"...\", \"bullets\":[...]}\n"
|
|
. " ]\n"
|
|
. "}\n\n"
|
|
. "IMPORTANT:\n"
|
|
. "- 8 a 12 slides au total (commencant par 'title' et finissant par 'conclusion')\n"
|
|
. "- Varier les types: content / two_column / stats / table / content\n"
|
|
. "- Bullets concis et percutants (10-15 mots chacun)\n"
|
|
. "- Stats: 3-4 chiffres avec valeur + libelle court\n"
|
|
. "- Francais pro, pas d'info confidentielle WEVAL\n"
|
|
. "- JSON valide uniquement";
|
|
|
|
$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' => 4500, 'temperature' => 0.7
|
|
]),
|
|
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
|
CURLOPT_TIMEOUT => 90,
|
|
]);
|
|
$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_V2 */
|
|
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);
|
|
}
|
|
$deck = json_decode($content_raw, true);
|
|
if (!$deck || !isset($deck['title'])) {
|
|
echo json_encode(['ok'=>false, 'error'=>'LLM invalid JSON', 'raw'=>substr($content_raw,0,500)]); exit;
|
|
}
|
|
|
|
$tmpjson = tempnam('/tmp', 'pptx_') . '.json';
|
|
file_put_contents($tmpjson, json_encode($deck));
|
|
|
|
$filename = 'weval-' . substr(md5($topic . microtime(true)), 0, 10) . '.pptx';
|
|
$outpath = '/var/www/html/files/' . $filename;
|
|
if (!is_dir('/var/www/html/files')) { mkdir('/var/www/html/files', 0755, true); }
|
|
|
|
$pyScript = '/var/www/html/api/ambre-tool-pptx-render.py';
|
|
$cmd = "python3 " . escapeshellarg($pyScript) . " " . escapeshellarg($tmpjson) . " " . escapeshellarg($outpath) . " 2>&1";
|
|
$out = shell_exec($cmd);
|
|
@unlink($tmpjson);
|
|
|
|
if (!file_exists($outpath)) {
|
|
echo json_encode(['ok'=>false, 'error'=>'pptx render failed', 'py_out'=>substr($out, 0, 500)]); exit;
|
|
}
|
|
|
|
echo json_encode([
|
|
'ok' => true,
|
|
'url' => '/files/' . $filename,
|
|
'title' => $deck['title'],
|
|
'slides' => count($deck['slides'] ?? []),
|
|
'size' => filesize($outpath),
|
|
'size_kb' => round(filesize($outpath)/1024, 1),
|
|
]);
|