From af80ffdb14f2ffcafcd68cc60c5fab5971ea9bfd Mon Sep 17 00:00:00 2001 From: Niek Rabelink Date: Sat, 12 Sep 2026 16:49:51 +0200 Subject: [PATCH] Dev nieuw --- admin.php | 52 ++++++++++++++++++++++++++++-- auth/login.php | 2 +- includes/ai.php | 56 +++++++++++++++++++++++++------- includes/settings.php | 75 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+), 15 deletions(-) diff --git a/admin.php b/admin.php index 37c1cbc..0f07c06 100644 --- a/admin.php +++ b/admin.php @@ -438,6 +438,7 @@ $appConfig = microsoft_get_app_config(); $companyJiraDomain = jira_get_company_domain(); $workdaySettings = get_workday_settings(); $aiSettings = get_ai_settings(); +$aiUsageStats = get_ai_usage_stats(); $sessionIdleTimeout = get_session_idle_timeout(); $calendarBlockReasons = get_calendar_block_reasons(); $brainstormCategories = get_brainstorm_categories(); @@ -1539,8 +1540,7 @@ require_once __DIR__ . '/includes/header.php';
-

AI & Brainstorm Co-Pilot (Google Gemini Pro)

-

Intelligente assistentie voor post-it ontleding, categorisatie, ideegeneratie en slimme planning

+

AI-Co-pilot

@@ -1555,6 +1555,54 @@ require_once __DIR__ . '/includes/header.php';
+ +
+
+
+ + AI Verbruik +
+ + Laatst gebruikt: + + Nog geen verbruik geregistreerd + +
+ +
+
+ Totaal Aanroepen + +
+ +
+ Totaal Tokens + +
+ +
+ Prompt / Invoer + +
+ +
+ Output / Gegenereerd + +
+
+ + +
+ Per model: + $mCount): ?> + + : x + + +
+ +
+
diff --git a/auth/login.php b/auth/login.php index bad2905..078d228 100644 --- a/auth/login.php +++ b/auth/login.php @@ -34,7 +34,7 @@ if ($currentUser) { $error = null; $infoMessage = null; if (isset($_GET['expired'])) { - $infoMessage = "Uw sessie is beeïndigd. Log opnieuw in om verder te gaan."; + $infoMessage = "Uw sessie is beeïndigd"; } if (isset($_GET['revoked'])) { $infoMessage = "Uw sessie is op afstand beëindigd of ingetrokken. Log opnieuw in om verder te gaan."; diff --git a/includes/ai.php b/includes/ai.php index 240812a..0e0a810 100644 --- a/includes/ai.php +++ b/includes/ai.php @@ -337,12 +337,23 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings } } + $promptTokens = (int)($response['json']['usageMetadata']['promptTokenCount'] ?? 0); + $completionTokens = (int)($response['json']['usageMetadata']['candidatesTokenCount'] ?? 0); + if ($promptTokens === 0 && $completionTokens === 0) { + // Schatting obv lengte indien niet geretourneerd + $promptTokens = max(1, (int)(strlen(json_encode($payload)) / 4)); + $completionTokens = max(1, (int)(strlen($cleanContent) / 4)); + } + return [ - 'success' => true, - 'content' => $cleanContent, - 'json' => $parsedJson, - 'model' => $successfulModel, - 'provider' => 'gemini', + 'success' => true, + 'content' => $cleanContent, + 'json' => $parsedJson, + 'model' => $successfulModel, + 'provider' => 'gemini', + 'prompt_tokens' => $promptTokens, + 'completion_tokens' => $completionTokens, + 'total_tokens' => ($promptTokens + $completionTokens), ]; } @@ -414,12 +425,22 @@ function fociz_ai_chat_openai(array $messages, array $options, array $aiSettings $parsedJson = json_decode($rawContent, true); } + $promptTokens = (int)($response['json']['usage']['prompt_tokens'] ?? 0); + $completionTokens = (int)($response['json']['usage']['completion_tokens'] ?? 0); + if ($promptTokens === 0 && $completionTokens === 0) { + $promptTokens = max(1, (int)(strlen(json_encode($payload)) / 4)); + $completionTokens = max(1, (int)(strlen($rawContent) / 4)); + } + return [ - 'success' => true, - 'content' => $rawContent, - 'json' => $parsedJson, - 'model' => $response['json']['model'] ?? $model, - 'provider' => 'openai', + 'success' => true, + 'content' => $rawContent, + 'json' => $parsedJson, + 'model' => $response['json']['model'] ?? $model, + 'provider' => 'openai', + 'prompt_tokens' => $promptTokens, + 'completion_tokens' => $completionTokens, + 'total_tokens' => ($promptTokens + $completionTokens), ]; } @@ -452,10 +473,21 @@ function fociz_ai_chat(array $messages, array $options = []): array { // Routering: als provider gemini is of model gemini bevat, stuur naar Google Gemini if ($provider === 'gemini' || strpos($model, 'gemini') !== false) { - return fociz_ai_chat_gemini($messages, $options, $aiSettings); + $res = fociz_ai_chat_gemini($messages, $options, $aiSettings); + } else { + $res = fociz_ai_chat_openai($messages, $options, $aiSettings); } - return fociz_ai_chat_openai($messages, $options, $aiSettings); + // Verbruiksstatistieken registreren bij geslaagde aanroep + if (!empty($res['success'])) { + $usedProvider = $res['provider'] ?? $provider; + $usedModel = $res['model'] ?? $model; + $pTokens = (int)($res['prompt_tokens'] ?? 0); + $cTokens = (int)($res['completion_tokens'] ?? 0); + record_ai_usage($usedProvider, $usedModel, $pTokens, $cTokens, $userId); + } + + return $res; } /** diff --git a/includes/settings.php b/includes/settings.php index 2b325b0..8179abc 100644 --- a/includes/settings.php +++ b/includes/settings.php @@ -259,4 +259,79 @@ function get_brainstorm_categories(): array { return $defaultCategories; } +/** + * Registreert AI verbruiksstatistieken (aanroepen, tokens, provider/model) + */ +function record_ai_usage(string $provider, string $model, int $promptTokens = 0, int $completionTokens = 0, ?int $userId = null): void { + try { + $stats = get_system_setting('ai_usage_stats', [ + 'total_requests' => 0, + 'total_prompt_tokens' => 0, + 'total_completion_tokens' => 0, + 'total_tokens' => 0, + 'last_used_at' => null, + 'by_provider' => [], + 'by_model' => [], + 'by_date' => [], + ]); + + $stats['total_requests'] = (int)($stats['total_requests'] ?? 0) + 1; + $stats['total_prompt_tokens'] = (int)($stats['total_prompt_tokens'] ?? 0) + $promptTokens; + $stats['total_completion_tokens'] = (int)($stats['total_completion_tokens'] ?? 0) + $completionTokens; + $stats['total_tokens'] = (int)($stats['total_tokens'] ?? 0) + ($promptTokens + $completionTokens); + $stats['last_used_at'] = date('Y-m-d H:i:s'); + + // Per provider + if (!isset($stats['by_provider'][$provider])) { + $stats['by_provider'][$provider] = 0; + } + $stats['by_provider'][$provider]++; + + // Per model + if (!isset($stats['by_model'][$model])) { + $stats['by_model'][$model] = 0; + } + $stats['by_model'][$model]++; + + // Per datum + $today = date('Y-m-d'); + if (!isset($stats['by_date'][$today])) { + $stats['by_date'][$today] = ['requests' => 0, 'tokens' => 0]; + } + $stats['by_date'][$today]['requests']++; + $stats['by_date'][$today]['tokens'] += ($promptTokens + $completionTokens); + + // Maximaal 30 dagen historiek + if (count($stats['by_date']) > 30) { + ksort($stats['by_date']); + $stats['by_date'] = array_slice($stats['by_date'], -30, 30, true); + } + + set_system_setting('ai_usage_stats', $stats); + } catch (Throwable $e) { + error_log("record_ai_usage fout: " . $e->getMessage()); + } +} + +/** + * Haalt de AI verbruiksstatistieken op + */ +function get_ai_usage_stats(): array { + $stats = get_system_setting('ai_usage_stats', null); + if (!is_array($stats)) { + return [ + 'total_requests' => 0, + 'total_prompt_tokens' => 0, + 'total_completion_tokens' => 0, + 'total_tokens' => 0, + 'last_used_at' => null, + 'by_provider' => [], + 'by_model' => [], + 'by_date' => [], + ]; + } + return $stats; +} + + -- 2.52.0