Files
html/api/ambre-tool-image.php

205 lines
8.4 KiB
PHP

<?php
/**
* V176 · ambre-tool-image.php · Upgraded with quality cascade
* Yacine: "IMAGE POURRI MET A LOUVER QWEN IMAGE POUR AMELOIRER"
*
* Cascade (order by QUALITY):
* 1. Gemini 3 Pro Image Preview (best quality, free tier via GEMINI_KEY) - PRIMARY
* 2. Qwen-Image via DashScope (requires ALIBABA_KEY with credits)
* 3. Pollinations flux (free, 1024x1024)
* 4. Pollinations sana (free, 768x768 fast fallback)
*
* Keep backward compat: same response schema as before
*/
header("Content-Type: application/json; charset=utf-8");
set_time_limit(90);
$raw = file_get_contents("php://input");
$in = json_decode($raw, true) ?: $_POST ?: $_GET;
$prompt = trim($in["prompt"] ?? $in["q"] ?? "");
if (!$prompt) { echo json_encode(["error"=>"prompt required"]); exit; }
// Clean prompt (keep unicode)
$clean = preg_replace('/[^\p{L}\p{N}\s,.\-!?]/u', '', $prompt);
$clean = mb_substr(trim($clean), 0, 400);
// Load secrets
$secrets = [];
foreach (file("/etc/weval/secrets.env") ?: [] as $line) {
$line = trim($line);
if (!$line || $line[0] === "#" || strpos($line, "=") === false) continue;
list($k, $v) = explode("=", $line, 2);
$secrets[trim($k)] = trim($v, " \"'");
}
$GEMINI_KEY = $secrets["GEMINI_KEY"] ?? "";
$ALIBABA_KEY = $secrets["ALIBABA_KEY"] ?? "";
// File naming (shared across cascade)
$dir = "/var/www/html/generated";
if (!is_dir($dir)) @mkdir($dir, 0755, true);
$slug = preg_replace('/[^a-z0-9]+/', '-', strtolower($clean));
$slug = substr(trim($slug, "-"), 0, 50);
$ts = date("Ymd-His");
$rand = bin2hex(random_bytes(3));
$t0 = microtime(true);
$result = null;
// ========== TIER 1: Gemini 3 Pro Image Preview (best quality, free) ==========
if ($GEMINI_KEY) {
$gurl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image-preview:generateContent?key=" . $GEMINI_KEY;
$body = json_encode([
"contents" => [["parts" => [["text" => $clean]]]],
"generationConfig" => ["responseModalities" => ["IMAGE", "TEXT"]],
]);
$ctx = stream_context_create([
"http" => [
"method" => "POST",
"header" => "Content-Type: application/json\r\n",
"content" => $body,
"timeout" => 60,
"ignore_errors" => true,
],
]);
$resp = @file_get_contents($gurl, false, $ctx);
if ($resp) {
$d = @json_decode($resp, true);
if (isset($d["candidates"][0]["content"]["parts"])) {
foreach ($d["candidates"][0]["content"]["parts"] as $p) {
if (isset($p["inlineData"]["data"])) {
$mime = $p["inlineData"]["mimeType"] ?? "image/jpeg";
$ext = strpos($mime, "png") !== false ? "png" : "jpg";
$filename = "wevia-img-gemini-{$slug}-{$ts}-{$rand}.{$ext}";
$path = "$dir/$filename";
$img = base64_decode($p["inlineData"]["data"]);
if ($img && strlen($img) > 5000) {
file_put_contents($path, $img);
$result = [
"success" => true,
"prompt" => $clean,
"url" => "https://weval-consulting.com/generated/$filename",
"size_kb" => round(strlen($img)/1024, 1),
"elapsed_ms" => round((microtime(true)-$t0)*1000),
"provider" => "Gemini 3 Pro Image Preview",
"quality" => "premium",
"engine" => "gemini-3-pro",
];
}
break;
}
}
}
}
}
// ========== TIER 2: Qwen-Image via DashScope (if Gemini failed + ALIBABA_KEY) ==========
if (!$result && $ALIBABA_KEY) {
// Create async task
$submit_ctx = stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer $ALIBABA_KEY\r\nContent-Type: application/json\r\nX-DashScope-Async: enable\r\n",
"content" => json_encode([
"model" => "qwen-image",
"input" => ["prompt" => $clean],
"parameters" => ["size" => "1024*1024", "n" => 1],
]),
"timeout" => 15,
"ignore_errors" => true,
],
]);
$submit_resp = @file_get_contents("https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis", false, $submit_ctx);
$submit_d = @json_decode($submit_resp, true);
$task_id = $submit_d["output"]["task_id"] ?? "";
if ($task_id) {
// Poll
for ($i = 0; $i < 20; $i++) {
sleep(2);
$pctx = stream_context_create(["http"=>["header"=>"Authorization: Bearer $ALIBABA_KEY\r\n","timeout"=>10]]);
$pr = @file_get_contents("https://dashscope-intl.aliyuncs.com/api/v1/tasks/$task_id", false, $pctx);
$pd = @json_decode($pr, true);
$status = $pd["output"]["task_status"] ?? "";
if ($status === "SUCCEEDED") {
$img_url = $pd["output"]["results"][0]["url"] ?? "";
if ($img_url) {
$img = @file_get_contents($img_url);
if ($img && strlen($img) > 5000) {
$filename = "wevia-img-qwen-{$slug}-{$ts}-{$rand}.png";
$path = "$dir/$filename";
file_put_contents($path, $img);
$result = [
"success" => true,
"prompt" => $clean,
"url" => "https://weval-consulting.com/generated/$filename",
"size_kb" => round(strlen($img)/1024, 1),
"elapsed_ms" => round((microtime(true)-$t0)*1000),
"provider" => "Qwen-Image (Alibaba DashScope)",
"quality" => "premium",
"engine" => "qwen-image",
];
}
}
break;
}
if ($status === "FAILED" || $status === "UNKNOWN") break;
}
}
}
// ========== TIER 3: Pollinations flux (free 1024x1024) ==========
if (!$result) {
$seed = rand(1, 99999);
$encoded = urlencode($clean);
// Try with flux model hint (even though list shows only sana, try anyway)
$flux_url = "https://image.pollinations.ai/prompt/$encoded?width=1024&height=1024&seed=$seed&nologo=true&enhance=true&model=flux";
$ctx2 = stream_context_create(["http"=>["timeout"=>30,"header"=>"User-Agent: WEVIA/2.0\r\n"]]);
$img = @file_get_contents($flux_url, false, $ctx2);
if ($img && strlen($img) > 5000) {
$filename = "wevia-img-flux-{$slug}-{$ts}-{$rand}.jpg";
$path = "$dir/$filename";
file_put_contents($path, $img);
$result = [
"success" => true,
"prompt" => $clean,
"url" => "https://weval-consulting.com/generated/$filename",
"size_kb" => round(strlen($img)/1024, 1),
"elapsed_ms" => round((microtime(true)-$t0)*1000),
"provider" => "Pollinations flux (fallback)",
"quality" => "standard",
"engine" => "pollinations-flux",
];
}
}
// ========== TIER 4: Pollinations sana (last resort) ==========
if (!$result) {
$seed = rand(1, 99999);
$encoded = urlencode($clean);
$sana_url = "https://image.pollinations.ai/prompt/$encoded?width=1024&height=1024&seed=$seed&nologo=true&enhance=true";
$ctx3 = stream_context_create(["http"=>["timeout"=>30,"header"=>"User-Agent: WEVIA/2.0\r\n"]]);
$img = @file_get_contents($sana_url, false, $ctx3);
if ($img && strlen($img) > 5000) {
$filename = "wevia-img-sana-{$slug}-{$ts}-{$rand}.jpg";
$path = "$dir/$filename";
file_put_contents($path, $img);
$result = [
"success" => true,
"prompt" => $clean,
"url" => "https://weval-consulting.com/generated/$filename",
"size_kb" => round(strlen($img)/1024, 1),
"elapsed_ms" => round((microtime(true)-$t0)*1000),
"provider" => "WEVIA Image Engine (sana)",
"quality" => "basic",
"engine" => "pollinations-sana",
];
}
}
if (!$result) {
echo json_encode(["error"=>"all image providers failed","prompt"=>$clean]);
exit;
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);