Corrección de cascada LLM en AIService.php + entorno Docker completo para pruebas locales sin depender de tokens de nube.
⚠ BOT retornando "Un momento, estoy revisando eso para ti. 🙏" en TODOS los turnos
La sesión anterior solucionó la cascada del cliente simulado (test_generator.php), pero el BOT real (AIService::callGroqAPI()) continuaba usando el modelo premium openai/gpt-oss-120b sin ningún fallback. Al agotarse los tokens o alcanzar el rate-limit, el método devolvía el canned message inmediatamente.
Antes (problemático)
private $groqModel = 'openai/gpt-oss-120b'; // 1 modelo × N keys → canned fallback
Después (cascada)
4 modelos × N keys → Ollama → canned openai/gpt-oss-120b ← calidad llama-3.1-8b-instant ← alta cuota gemma2-9b-it ← cuota independiente llama-3.2-3b-preview ← emergencia
Reescritura de callGroqAPI(): doble bucle modelo×key, delay 150ms entre modelos, soporte Ollama vía OLLAMA_URL env.
_callOllamaCompat() — API compatible con OpenAIOLLAMA_MODEL configurable por env var (default: hermes3:latest)[AMR-AI] model=X HTTP=Y err=…PHP 8.2-Apache + extensiones pdo pdo_mysql pdo_sqlite mbstring zip curl. El Dockerfile de producción solo tenía pdo_sqlite.
Servicios: crm-db (MySQL 8.0 · puerto 3307) + crm-app (PHP · puerto 8090). Hot-reload via volume mount. host.docker.internal para alcanzar Ollama del Mac.
Esquema completo: contacts (con tags, lead_data, manual_takeover), conversations (con outcome, ai_profile_key), messages (con wamid, sender), ai_profiles, templates, dropshipping_products. Seed: 7 perfiles AI + 3 templates.
Config local: MySQL Docker, Ollama en host, keys de Groq/OpenRouter opcionales. Cubierto por .gitignore (.env.*).
callGroqAPI() / callLLMCascade()
├─ Tier 1: Groq API [4 modelos × N keys]
│ ├─ openai/gpt-oss-120b → calidad máxima (paid)
│ ├─ llama-3.1-8b-instant → free, +RPM
│ ├─ gemma2-9b-it → free, cuota independiente
│ └─ llama-3.2-3b-preview → emergencia ultra-ligero
│ delay 150ms entre modelos
│
├─ Tier 2: Ollama [local Mac o AMR Server]
│ └─ OLLAMA_URL + OLLAMA_MODEL (hermes3 / nous-hermes2 / llama3.2)
│ timeout 60s
│
└─ Tier 3: Canned Response [garantizado, nunca falla]
└─ "Un momento, estoy revisando eso para ti. 🙏" ← SOLO si todo falla
whatsapp-crm/.env.local — pegar claves Groq si deseas probar la cascada en nubeollama list — se necesita al menos un modelo (hermes3)cd whatsapp-crm docker compose -f docker-compose.local.yml up --build -d
docker logs crm_app_local | grep AMR-AIPara saber si los tokens están rate-limited (temporal) o agotados (quota mensual), ejecuta este curl desde el Mac:
curl -s https://api.groq.com/openai/v1/models \ -H "Authorization: Bearer $GROQ_API_KEY" | jq '.error // "OK - tokens válidos"'
✅ Respuesta OK
Los tokens siguen activos. El problema era solo rate-limit → la cascada lo resuelve automáticamente.
❌ Error 401 / quota_exceeded
Key agotada. Agregar nueva key en .env como GROQ_API_KEY_4 y reiniciar Apache.