Files
html/api/ambre-tool-translate-code.php
Opus b2379f004a
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
perf(generators-OPT_V2_RETRY): max_tokens reduit + timeout cushion + retry-once on 503 with simpler model
OPTIMIZATIONS per API:
- docx: 4000->2800 tokens timeout 60s
- xlsx: 4500->3200 tokens timeout 70s
- pptx: 4500->3500 tokens timeout 75s
- react: 6000->4500 tokens timeout 90s
- 3d: 6000->4500 tokens timeout 90s
- dataviz: 7000->5000 tokens timeout 100s
- site: 12000->8000 tokens timeout 120s
- sql: 2000->1500 tokens timeout 40s
- brainstorm: 1200->800 tokens timeout 30s
- translate-code: 3500->2500 tokens timeout 60s

RETRY HELPER:
- wvia_llm_retry_once() avec llama-3.3-70b fallback
- Active si curl 503 sovereign
- 1 retry max (latency cushion)

TESTED LIVE:
- DOCX: 38KB 7 sections OK
- SQL: PostgreSQL array_agg LIMIT GROUP BY OK
- Gallery: 1 doc tracked auto
2026-04-25 01:40:26 +02:00

121 lines
4.5 KiB
PHP

<?php
/**
* ambre-tool-translate-code.php — Translate code JS->Python, Python->JS, etc.
*/
header('Content-Type: application/json');
/* OPT_V2_RETRY - retry once on 503 with simpler model */
if (!function_exists('wvia_llm_retry_once')) {
function wvia_llm_retry_once($payload) {
$payload['model'] = 'llama-3.3-70b';
$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($payload),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_TIMEOUT => 60,
]);
$r = curl_exec($ch);
$c = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [$c, $r];
}
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['ok'=>false,'error'=>'POST only']); exit; }
$input = json_decode(file_get_contents('php://input'), true);
$code = trim($input['code'] ?? '');
$from_lang = $input['from'] ?? 'auto';
$to_lang = $input['to'] ?? 'python';
// If topic was sent instead (from intent router), parse "translate X from Y to Z"
if (!$code && isset($input['topic'])) {
$topic = $input['topic'];
// Try extract code block if present
if (preg_match('/```(?:\w+)?\s*\n(.*?)\n```/s', $topic, $m)) {
$code = $m[1];
} else {
$code = $topic; // treat topic as code
}
// Detect to_lang
foreach (['python','javascript','typescript','go','rust','java','csharp','php','ruby','kotlin','swift'] as $lang) {
if (stripos($topic, $lang) !== false) { $to_lang = $lang; break; }
}
}
if (strlen($code) < 5) { echo json_encode(['ok'=>false,'error'=>'code too short']); exit; }
$code = substr($code, 0, 4000);
$prompt = "Expert polyglot programmer. Traduis ce code" . ($from_lang !== 'auto' ? " de $from_lang" : "") . " vers $to_lang:\n\n"
. "```\n$code\n```\n\n"
. "Retourne UNIQUEMENT un JSON:\n"
. "{\n"
. " \"from\": \"langue detectee\",\n"
. " \"to\": \"$to_lang\",\n"
. " \"code\": \"<code traduit complet>\",\n"
. " \"notes\": \"Notes sur differences idiomatiques importantes\",\n"
. " \"dependencies\": [\"package1\", \"package2\"]\n"
. "}\n\n"
. "IMPORTANT:\n"
. "- Code traduit IDIOMATIQUE dans la langue cible (pas traduction literale)\n"
. "- Utiliser les conventions modernes (ES2024/Python3.12/Go1.22/etc)\n"
. "- Preserver les commentaires si presents, traduits en FR\n"
. "- JSON valide uniquement, aucun texte avant/apres\n"
. "- dependencies = liste des libs a installer";
$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' => 2500, 'temperature' => 0.3
]),
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) {
/* OPT_V2_RETRY - try once with simpler model */
list($http, $resp) = wvia_llm_retry_once([
'messages' => [['role'=>'user', 'content'=>$prompt]],
'max_tokens' => 2500,
'temperature' => 0.6
]);
if ($http !== 200) {
echo json_encode(['ok'=>false,'error'=>"LLM HTTP $http (after retry)"]);
exit;
}
}
$data = json_decode($resp, true);
$content_raw = $data['choices'][0]['message']['content'] ?? '';
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['code'])) {
echo json_encode(['ok'=>false,'error'=>'invalid JSON','raw'=>substr($content_raw,0,300)]); exit;
}
echo json_encode([
'ok' => true,
'from' => $result['from'] ?? $from_lang,
'to' => $result['to'] ?? $to_lang,
'code' => $result['code'],
'notes' => $result['notes'] ?? '',
'dependencies' => $result['dependencies'] ?? [],
'result' => $result['code'], // for inline render
]);