Fix
This commit is contained in:
+75
-30
@@ -83,7 +83,7 @@ function fociz_ai_enforce_privacy_firewall(array &$messages): array {
|
||||
*/
|
||||
function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings): array {
|
||||
$apiKey = trim((string)($aiSettings['ai_api_key'] ?? ''));
|
||||
$model = !empty($aiSettings['ai_model']) ? trim((string)$aiSettings['ai_model']) : 'gemini-3.6-flash';
|
||||
$model = !empty($aiSettings['ai_model']) ? trim((string)$aiSettings['ai_model']) : 'gemini-2.0-flash';
|
||||
$temperature = $options['temperature'] ?? 0.3;
|
||||
$maxTokens = max(512, (int)($options['max_tokens'] ?? 2048));
|
||||
$jsonMode = !empty($options['json_mode']);
|
||||
@@ -157,35 +157,34 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings
|
||||
return trim($txt);
|
||||
};
|
||||
|
||||
// Bepaal fallback volgorde van endpoints/versies voor maximale compatibiliteit met alle Google AI Studio accounts
|
||||
// Normaliseer modelnaam en stel geldige kandidatenlijst op
|
||||
$candidateUrls = [];
|
||||
if (str_contains($cleanModel, '3.6-flash')) {
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.6-flash:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1/models/gemini-3.6-flash:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent";
|
||||
} elseif (str_contains($cleanModel, '2.0-flash')) {
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.6-flash:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent";
|
||||
} elseif (str_contains($cleanModel, '1.5-flash')) {
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.6-flash:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1/models/gemini-1.5-flash:generateContent";
|
||||
} elseif (str_contains($cleanModel, '1.5-pro')) {
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1/models/gemini-1.5-pro:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.6-flash:generateContent";
|
||||
} else {
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/{$cleanModel}:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.6-flash:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent";
|
||||
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1/models/{$cleanModel}:generateContent";
|
||||
|
||||
// Helper om endpoints op te bouwen voor v1beta en v1
|
||||
$addCandidatesFor = function(string $m) use (&$candidateUrls) {
|
||||
$m = preg_replace('#^models/#', '', trim($m));
|
||||
if ($m === '') return;
|
||||
$v1beta = "https://generativelanguage.googleapis.com/v1beta/models/{$m}:generateContent";
|
||||
$v1 = "https://generativelanguage.googleapis.com/v1/models/{$m}:generateContent";
|
||||
if (!in_array($v1beta, $candidateUrls, true)) {
|
||||
$candidateUrls[] = $v1beta;
|
||||
}
|
||||
if (!in_array($v1, $candidateUrls, true)) {
|
||||
$candidateUrls[] = $v1;
|
||||
}
|
||||
};
|
||||
|
||||
// Voeg het geconfigureerde model toe als eerste kandidaat (tenzij het een niet-bestaand/fictief model is)
|
||||
if (!empty($cleanModel) && !str_contains($cleanModel, '3.6-flash')) {
|
||||
$addCandidatesFor($cleanModel);
|
||||
}
|
||||
|
||||
// Voeg altijd de stabiele, snelle Google AI modellen toe als betrouwbare fallbacks/standaarden
|
||||
$addCandidatesFor('gemini-2.0-flash');
|
||||
$addCandidatesFor('gemini-1.5-flash');
|
||||
$addCandidatesFor('gemini-1.5-pro');
|
||||
$addCandidatesFor('gemini-2.5-flash');
|
||||
|
||||
$response = null;
|
||||
$lastError = null;
|
||||
$successfulModel = $cleanModel;
|
||||
@@ -335,6 +334,14 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings
|
||||
// Poging 2: json decode met raw
|
||||
$parsedJson = json_decode($rawContent, true);
|
||||
}
|
||||
// Poging 3: extraheer JSON substring {...} of [...] indien AI conversatietekst heeft toegevoegd
|
||||
if ($parsedJson === null) {
|
||||
if (preg_match('/\{(?:[^{}]|(?R))*\}/s', $cleanContent, $matchJson)) {
|
||||
$parsedJson = json_decode($matchJson[0], true);
|
||||
} elseif (preg_match('/\[(?:[^\[\]]|(?R))*\]/s', $cleanContent, $matchJson)) {
|
||||
$parsedJson = json_decode($matchJson[0], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$promptTokens = (int)($response['json']['usageMetadata']['promptTokenCount'] ?? 0);
|
||||
@@ -540,17 +547,55 @@ function fociz_ai_breakdown_idea(string $ideaContent, string $sessionTitle = '',
|
||||
'user_id' => $userId,
|
||||
]);
|
||||
|
||||
if (!$aiRes['success'] || empty($aiRes['json']['items'])) {
|
||||
if (!$aiRes['success']) {
|
||||
error_log("[fociz_ai_breakdown_idea] AI request failed: " . ($aiRes['error'] ?? 'Unknown error'));
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $aiRes['error'] ?? 'Kon het idee niet ontleden in taken via AI.',
|
||||
];
|
||||
}
|
||||
|
||||
$parsed = $aiRes['json'] ?? null;
|
||||
$items = [];
|
||||
$summary = '';
|
||||
|
||||
if (is_array($parsed)) {
|
||||
if (!empty($parsed['items']) && is_array($parsed['items'])) {
|
||||
$items = $parsed['items'];
|
||||
} elseif (!empty($parsed['tasks']) && is_array($parsed['tasks'])) {
|
||||
$items = $parsed['tasks'];
|
||||
} elseif (!empty($parsed['taken']) && is_array($parsed['taken'])) {
|
||||
$items = $parsed['taken'];
|
||||
} elseif (!empty($parsed['cards']) && is_array($parsed['cards'])) {
|
||||
$items = $parsed['cards'];
|
||||
} elseif (array_is_list($parsed)) {
|
||||
$items = $parsed;
|
||||
}
|
||||
$summary = (string)($parsed['summary'] ?? '');
|
||||
}
|
||||
|
||||
// Als JSON parsing toch leeg was, probeer regex fallback op ruwe content
|
||||
if (empty($items) && !empty($aiRes['content'])) {
|
||||
if (preg_match('/\[\s*\{.*\}\s*\]/s', $aiRes['content'], $mArr)) {
|
||||
$decodedArr = json_decode($mArr[0], true);
|
||||
if (is_array($decodedArr)) {
|
||||
$items = $decodedArr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($items)) {
|
||||
error_log("[fociz_ai_breakdown_idea] Geen geldige items gevonden in response: " . substr((string)($aiRes['content'] ?? ''), 0, 500));
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'De AI gaf een antwoord maar kon de taken niet structureren. Probeer het nogmaals.',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'summary' => $aiRes['json']['summary'] ?? '',
|
||||
'items' => $aiRes['json']['items'],
|
||||
'summary' => $summary ?: 'Dit idee is opgesplitst in behapbare deeltaken.',
|
||||
'items' => $items,
|
||||
'model' => $aiRes['model'] ?? 'Gemini Pro',
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user