From 75eddd16a664b914d5620b05109a4e42ca575809 Mon Sep 17 00:00:00 2001 From: Lizandro Date: Tue, 14 Jul 2026 20:11:32 +0000 Subject: [PATCH] feat: make Gemini model configurable + auto-list available models on error - gemini_model is now a saved config field (default: gemini-2.0-flash) - Config panel shows a text input to set the model name - probarGemini() reads the configured model and on error calls ListModels to show exactly which model names are available for the account's API key - GeminiIntentService and GeminiVisionService build the URL from config at runtime Co-Authored-By: Claude Sonnet 4.6 --- .../Livewire/Chat/ShowConfiguracionChat.php | 33 ++++++++++++++----- app/Services/GeminiIntentService.php | 4 ++- app/Services/GeminiVisionService.php | 4 ++- .../chat/show-configuracion-chat.blade.php | 6 ++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/app/Http/Livewire/Chat/ShowConfiguracionChat.php b/app/Http/Livewire/Chat/ShowConfiguracionChat.php index 6d9dc4f..dfe885b 100755 --- a/app/Http/Livewire/Chat/ShowConfiguracionChat.php +++ b/app/Http/Livewire/Chat/ShowConfiguracionChat.php @@ -21,6 +21,7 @@ class ShowConfiguracionChat extends Component // ── Gemini IA ───────────────────────────────────────────── public string $gemini_api_key = ''; + public string $gemini_model = 'gemini-2.0-flash'; public string $gemini_habilitado = '0'; public string $gemini_prompt_extra = ''; @@ -43,7 +44,7 @@ class ShowConfiguracionChat extends Component { $keys = [ 'telegram_token', 'mensaje_bienvenida', 'mensaje_transferencia', - 'gemini_api_key', 'gemini_habilitado', 'gemini_prompt_extra', + 'gemini_api_key', 'gemini_model', 'gemini_habilitado', 'gemini_prompt_extra', 'validacion_foto_habilitada', 'validacion_accion_auto', 'validacion_monto_tolerancia', 'whisper_url', 'whisper_token', 'whisper_habilitado', 'recarga_banco_nombre', 'recarga_banco_llave', 'recarga_banco_titular', @@ -54,6 +55,7 @@ class ShowConfiguracionChat extends Component 'mensaje_transferencia' => 'Un agente se comunicara contigo en breve. Por favor espera.', 'validacion_accion_auto' => 'solo_notificar', 'validacion_monto_tolerancia' => '0', + 'gemini_model' => 'gemini-2.0-flash', ]; foreach ($keys as $key) { @@ -74,7 +76,7 @@ class ShowConfiguracionChat extends Component $keys = [ 'telegram_token', 'mensaje_bienvenida', 'mensaje_transferencia', - 'gemini_api_key', 'gemini_habilitado', 'gemini_prompt_extra', + 'gemini_api_key', 'gemini_model', 'gemini_habilitado', 'gemini_prompt_extra', 'validacion_foto_habilitada', 'validacion_accion_auto', 'validacion_monto_tolerancia', 'whisper_url', 'whisper_token', 'whisper_habilitado', 'recarga_banco_nombre', 'recarga_banco_llave', 'recarga_banco_titular', @@ -89,18 +91,19 @@ class ShowConfiguracionChat extends Component public function probarGemini(): void { - $key = trim($this->gemini_api_key ?: \App\Models\ChatConfig::get('gemini_api_key')); + $key = trim($this->gemini_api_key ?: \App\Models\ChatConfig::get('gemini_api_key')); + $model = trim($this->gemini_model ?: \App\Models\ChatConfig::get('gemini_model', 'gemini-2.0-flash')); if (! $key) { $this->geminiResult = '⚠️ La API Key de Gemini está vacía.'; return; } - $url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent'; + $url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent"; try { $inicio = microtime(true); - $response = Http::timeout(10) + $response = Http::timeout(15) ->withHeaders(['Content-Type' => 'application/json']) ->post("{$url}?key={$key}", [ 'contents' => [['parts' => [['text' => 'Responde solo "ok"']]]], @@ -111,13 +114,27 @@ class ShowConfiguracionChat extends Component $data = $response->json(); if (! $response->successful() || isset($data['error'])) { - $msg = $data['error']['message'] ?? ('HTTP ' . $response->status()); - $this->geminiResult = "❌ Gemini respondió con error: {$msg}"; + $apiMsg = $data['error']['message'] ?? ('HTTP ' . $response->status()); + + // Listar modelos disponibles para ayudar a elegir el correcto + $lista = Http::timeout(10) + ->get("https://generativelanguage.googleapis.com/v1beta/models?key={$key}"); + + if ($lista->successful()) { + $nombres = collect($lista->json('models', [])) + ->filter(fn ($m) => str_contains($m['name'] ?? '', 'gemini')) + ->pluck('name') + ->map(fn ($n) => str_replace('models/', '', $n)) + ->values()->implode(', '); + $this->geminiResult = "❌ Modelo \"{$model}\" no disponible. Modelos en tu cuenta: {$nombres}"; + } else { + $this->geminiResult = "❌ Error: {$apiMsg}"; + } return; } $texto = $data['candidates'][0]['content']['parts'][0]['text'] ?? '(sin texto)'; - $this->geminiResult = "✅ Gemini OK ({$ms}ms) — respuesta: \"{$texto}\""; + $this->geminiResult = "✅ Gemini OK — modelo: {$model} — ({$ms}ms) — respuesta: \"{$texto}\""; } catch (\Throwable $e) { $this->geminiResult = '❌ No se pudo conectar con Gemini: ' . $e->getMessage(); diff --git a/app/Services/GeminiIntentService.php b/app/Services/GeminiIntentService.php index 0bc5166..4a1f319 100644 --- a/app/Services/GeminiIntentService.php +++ b/app/Services/GeminiIntentService.php @@ -10,11 +10,13 @@ use Illuminate\Support\Facades\Log; class GeminiIntentService { private string $apiKey; - private string $apiUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent'; + private string $apiUrl; public function __construct() { $this->apiKey = ChatConfig::get('gemini_api_key', ''); + $model = ChatConfig::get('gemini_model', 'gemini-2.0-flash'); + $this->apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent"; } /** diff --git a/app/Services/GeminiVisionService.php b/app/Services/GeminiVisionService.php index 1a9c09d..8811825 100644 --- a/app/Services/GeminiVisionService.php +++ b/app/Services/GeminiVisionService.php @@ -10,11 +10,13 @@ use Illuminate\Support\Facades\Log; class GeminiVisionService { private string $apiKey; - private string $apiUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent'; + private string $apiUrl; public function __construct() { $this->apiKey = ChatConfig::get('gemini_api_key', ''); + $model = ChatConfig::get('gemini_model', 'gemini-2.0-flash'); + $this->apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent"; } /** diff --git a/resources/views/livewire/chat/show-configuracion-chat.blade.php b/resources/views/livewire/chat/show-configuracion-chat.blade.php index e8b8d6c..de82a85 100755 --- a/resources/views/livewire/chat/show-configuracion-chat.blade.php +++ b/resources/views/livewire/chat/show-configuracion-chat.blade.php @@ -69,6 +69,12 @@ +
+ +

Usa "Probar conexión" para ver los modelos disponibles en tu cuenta si no sabes cuál poner.

+ +