Aanpassingen planner en ai

This commit is contained in:
2026-09-12 13:24:00 +02:00
parent bc33c0bd1a
commit 8714038db2
5 changed files with 1173 additions and 142 deletions
+49 -18
View File
@@ -83,9 +83,9 @@ 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-1.5-pro';
$model = !empty($aiSettings['ai_model']) ? trim((string)$aiSettings['ai_model']) : 'gemini-3.6-flash';
$temperature = $options['temperature'] ?? 0.3;
$maxTokens = $options['max_tokens'] ?? 2048;
$maxTokens = max(512, (int)($options['max_tokens'] ?? 2048));
$jsonMode = !empty($options['json_mode']);
if (empty($apiKey)) {
@@ -140,34 +140,56 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings
$cleanModel = preg_replace('#^models/#', '', $model);
// Helper om tekst uit Gemini candidate te extraheren
$extractCandidateText = function(?array $candidate): string {
if (!$candidate || empty($candidate['content']['parts'])) {
return '';
}
$txt = '';
foreach ($candidate['content']['parts'] as $part) {
if (!empty($part['text']) && empty($part['thought'])) {
$txt .= $part['text'];
}
}
if ($txt === '' && !empty($candidate['content']['parts'][0]['text'])) {
$txt = $candidate['content']['parts'][0]['text'];
}
return trim($txt);
};
// Bepaal fallback volgorde van endpoints/versies voor maximale compatibiliteit met alle Google AI Studio accounts
$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";
} elseif (str_contains($cleanModel, '2.0-flash')) {
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/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-2.0-flash-exp:generateContent";
} elseif (str_contains($cleanModel, '1.5-flash')) {
$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";
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-001:generateContent";
$candidateUrls[] = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-002: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";
}
$response = null;
$lastError = null;
$successfulModel = $cleanModel;
$finalText = '';
for ($i = 0; $i < count($candidateUrls); $i++) {
$baseUrl = $candidateUrls[$i];
@@ -182,12 +204,17 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings
'timeout' => 20,
]);
if ($res['status'] === 200 && !empty($res['json']['candidates'][0]['content']['parts'][0]['text'])) {
$response = $res;
if (preg_match('#/models/([^:]+)#', $baseUrl, $mName)) {
$successfulModel = $mName[1];
if ($res['status'] === 200 && !empty($res['json']['candidates'][0])) {
$extracted = $extractCandidateText($res['json']['candidates'][0]);
// Als er tekst is, of finishReason is geldig (bijv. STOP of MAX_TOKENS)
if ($extracted !== '' || !empty($res['json']['candidates'][0]['finishReason'])) {
$response = $res;
$finalText = ($extracted !== '') ? $extracted : 'OK';
if (preg_match('#/models/([^:]+)#', $baseUrl, $mName)) {
$successfulModel = $mName[1];
}
break;
}
break;
}
$msg = $res['json']['error']['message'] ?? ($res['error'] ?? '');
@@ -260,9 +287,13 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings
'timeout' => 20,
]);
if ($dynRes['status'] === 200 && !empty($dynRes['json']['candidates'][0]['content']['parts'][0]['text'])) {
$response = $dynRes;
$successfulModel = $fallbackModel;
if ($dynRes['status'] === 200 && !empty($dynRes['json']['candidates'][0])) {
$extracted = $extractCandidateText($dynRes['json']['candidates'][0]);
if ($extracted !== '' || !empty($dynRes['json']['candidates'][0]['finishReason'])) {
$response = $dynRes;
$finalText = ($extracted !== '') ? $extracted : 'OK';
$successfulModel = $fallbackModel;
}
} else {
$response = $dynRes;
}
@@ -270,7 +301,7 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings
}
}
if (!$response || $response['status'] !== 200 || empty($response['json']['candidates'][0]['content']['parts'][0]['text'])) {
if (!$response || $response['status'] !== 200 || $finalText === '') {
$errMsg = null;
if (!empty($response['json']['error']['message'])) {
$errMsg = $response['json']['error']['message'];
@@ -288,7 +319,7 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings
];
}
$rawContent = trim($response['json']['candidates'][0]['content']['parts'][0]['text']);
$rawContent = $finalText;
// Indien Gemini het als markdown code block wrapped heeft (bv. ```json ... ```), schoon dit op
if (preg_match('/^```(?:json)?\s*(.*?)\s*```$/s', $rawContent, $m)) {