From eb6bb8e7f369801a1b0dcd2f0164eb4e760e9b44 Mon Sep 17 00:00:00 2001 From: Lizandro Date: Tue, 14 Jul 2026 20:24:17 +0000 Subject: [PATCH] fix: move thinkingConfig to root level of Gemini request body thinkingConfig must be a top-level key in the request, NOT nested inside generationConfig. This is required for gemini-2.5-flash and newer models. Co-Authored-By: Claude Sonnet 4.6 --- .../Livewire/Chat/ShowConfiguracionChat.php | 8 +++--- app/Services/GeminiIntentService.php | 20 +++++++------ app/Services/GeminiVisionService.php | 28 ++++++++++--------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/app/Http/Livewire/Chat/ShowConfiguracionChat.php b/app/Http/Livewire/Chat/ShowConfiguracionChat.php index acb4ff4..11781ef 100755 --- a/app/Http/Livewire/Chat/ShowConfiguracionChat.php +++ b/app/Http/Livewire/Chat/ShowConfiguracionChat.php @@ -107,10 +107,10 @@ class ShowConfiguracionChat extends Component ->withHeaders(['Content-Type' => 'application/json']) ->post("{$url}?key={$key}", [ 'contents' => [['parts' => [['text' => 'Responde solo "ok"']]]], - 'generationConfig' => array_merge( - ['maxOutputTokens' => 5, 'temperature' => 0], - preg_match('/gemini-(2\.5|3[\.\d]*)/', $model) ? ['thinkingConfig' => ['thinkingBudget' => 0]] : [] - ), + 'generationConfig' => ['maxOutputTokens' => 5, 'temperature' => 0], + ...(preg_match('/gemini-(2\.5|3[\.\d]*)/', $model) + ? ['thinkingConfig' => ['thinkingBudget' => 0]] + : []), ]); $ms = (int) ((microtime(true) - $inicio) * 1000); diff --git a/app/Services/GeminiIntentService.php b/app/Services/GeminiIntentService.php index 1229bea..722f3fc 100644 --- a/app/Services/GeminiIntentService.php +++ b/app/Services/GeminiIntentService.php @@ -21,14 +21,17 @@ class GeminiIntentService $this->apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/{$this->model}:generateContent"; } - private function generationConfig(array $extra = []): array + private function buildRequest(array $contents, array $genConfig = []): array { - $config = array_merge(['temperature' => 0.1, 'maxOutputTokens' => 100], $extra); - // 2.5+ models require thinkingConfig to avoid response format issues + $body = [ + 'contents' => $contents, + 'generationConfig' => array_merge(['temperature' => 0.1, 'maxOutputTokens' => 100], $genConfig), + ]; + // thinkingConfig goes at root level (NOT inside generationConfig) for 2.5+ models if (preg_match('/gemini-(2\.5|3[\.\d]*)/', $this->model)) { - $config['thinkingConfig'] = ['thinkingBudget' => 0]; + $body['thinkingConfig'] = ['thinkingBudget' => 0]; } - return $config; + return $body; } /** @@ -47,10 +50,9 @@ class GeminiIntentService try { $response = Http::withHeaders(['Content-Type' => 'application/json']) ->timeout(8) - ->post("{$this->apiUrl}?key={$this->apiKey}", [ - 'contents' => [['parts' => [['text' => $prompt]]]], - 'generationConfig' => $this->generationConfig(), - ]); + ->post("{$this->apiUrl}?key={$this->apiKey}", + $this->buildRequest([['parts' => [['text' => $prompt]]]]) + ); $tiempoMs = (int) ((microtime(true) - $inicio) * 1000); diff --git a/app/Services/GeminiVisionService.php b/app/Services/GeminiVisionService.php index c2e2bc0..407fbcf 100644 --- a/app/Services/GeminiVisionService.php +++ b/app/Services/GeminiVisionService.php @@ -21,13 +21,16 @@ class GeminiVisionService $this->apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/{$this->model}:generateContent"; } - private function generationConfig(array $extra = []): array + private function buildRequest(array $contents, array $genConfig = []): array { - $config = array_merge(['temperature' => 0.1, 'maxOutputTokens' => 200], $extra); + $body = [ + 'contents' => $contents, + 'generationConfig' => array_merge(['temperature' => 0.1, 'maxOutputTokens' => 200], $genConfig), + ]; if (preg_match('/gemini-(2\.5|3[\.\d]*)/', $this->model)) { - $config['thinkingConfig'] = ['thinkingBudget' => 0]; + $body['thinkingConfig'] = ['thinkingBudget' => 0]; } - return $config; + return $body; } /** @@ -48,17 +51,16 @@ class GeminiVisionService $inicio = microtime(true); try { + $contents = [[ + 'parts' => [ + ['text' => $prompt], + ['inline_data' => ['mime_type' => $mimeType, 'data' => $base64]], + ], + ]]; + $response = Http::withHeaders(['Content-Type' => 'application/json']) ->timeout(15) - ->post("{$this->apiUrl}?key={$this->apiKey}", [ - 'contents' => [[ - 'parts' => [ - ['text' => $prompt], - ['inline_data' => ['mime_type' => $mimeType, 'data' => $base64]], - ], - ]], - 'generationConfig' => $this->generationConfig(), - ]); + ->post("{$this->apiUrl}?key={$this->apiKey}", $this->buildRequest($contents)); $tiempoMs = (int) ((microtime(true) - $inicio) * 1000);