Update: 2026-05-07 18:32:31

This commit is contained in:
Hamza-Ayed
2026-05-07 18:32:31 +03:00
parent 10432e7b81
commit 3cdab9dccc

View File

@@ -98,7 +98,7 @@ function detectAudioMimeType(string $path, string $fallback, string $fileName =
function extractIntentFromAudio(string $base64Audio, string $mimeType, string $apiKey): array function extractIntentFromAudio(string $base64Audio, string $mimeType, string $apiKey): array
{ {
$model = env('GEMINI_VOICE_MODEL', env('GEMINI_MODEL', 'gemini-2.5-flash')); $model = env('GEMINI_VOICE_MODEL', 'gemini-2.5-flash');
$systemPrompt = <<<PROMPT $systemPrompt = <<<PROMPT
أنت مساعد أوامر صوتية عربي لمنصة "مُصادَق" للفوترة الأردنية. أنت مساعد أوامر صوتية عربي لمنصة "مُصادَق" للفوترة الأردنية.
@@ -159,28 +159,35 @@ PROMPT;
], ],
]; ];
$url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$apiKey}"; $result = callGeminiGenerateContent($model, $payload, $apiKey);
$ch = curl_init($url); // Some Gemini model/API combinations reject JSON mode for multimodal audio.
curl_setopt_array($ch, [ // Retry once with prompt-only JSON enforcement before failing the request.
CURLOPT_POST => true, if ($result['http_code'] !== 200 || !$result['body']) {
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE), $fallbackPayload = $payload;
CURLOPT_RETURNTRANSFER => true, unset($fallbackPayload['generationConfig']['responseMimeType']);
CURLOPT_HTTPHEADER => ['Content-Type: application/json'], $result = callGeminiGenerateContent($model, $fallbackPayload, $apiKey);
CURLOPT_TIMEOUT => 45,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($httpCode !== 200 || !$response) {
error_log("Voice Gemini Error: HTTP {$httpCode} | {$error} | {$response}");
json_error('فشل تحليل الصوت بواسطة Gemini', 500);
} }
$respData = json_decode($response, true); if ($result['http_code'] !== 200 || !$result['body']) {
$geminiError = parseGeminiError($result['body']);
error_log(
"Voice Gemini Error: HTTP {$result['http_code']} | {$result['curl_error']} | {$result['body']}"
);
json_error(
'فشل تحليل الصوت بواسطة Gemini: ' . $geminiError['message'],
502,
[
'gemini_http_code' => $result['http_code'],
'gemini_status' => $geminiError['status'],
'gemini_model' => $model,
'audio_mime_type' => $mimeType,
]
);
}
$respData = json_decode($result['body'], true);
if (!is_array($respData)) { if (!is_array($respData)) {
json_error('تعذر قراءة رد Gemini', 500); json_error('تعذر قراءة رد Gemini', 500);
} }
@@ -217,6 +224,52 @@ PROMPT;
]; ];
} }
function callGeminiGenerateContent(string $model, array $payload, string $apiKey): array
{
$url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent";
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'x-goog-api-key: ' . $apiKey,
],
CURLOPT_TIMEOUT => 45,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
return [
'body' => is_string($response) ? $response : '',
'http_code' => (int)$httpCode,
'curl_error' => $error ?: '',
];
}
function parseGeminiError(string $response): array
{
$decoded = json_decode($response, true);
$error = is_array($decoded) ? ($decoded['error'] ?? null) : null;
if (is_array($error)) {
return [
'message' => (string)($error['message'] ?? 'رد غير معروف من Gemini'),
'status' => (string)($error['status'] ?? ''),
];
}
return [
'message' => 'رد غير معروف من Gemini',
'status' => '',
];
}
function decodeModelJson(string $rawText): ?array function decodeModelJson(string $rawText): ?array
{ {
$text = trim($rawText); $text = trim($rawText);