FOLIO: AUD-20260925-001 Secuencia: Auditoría #001 del día 2026-09-25
📅 2026-09-25 00:00:00 COT 👤 Auditor: Anderson Mares (AMR TECH) ● VIGENTE
🤖

AIService Cascade Fix + Docker Local CRM

Corrección de cascada LLM en AIService.php + entorno Docker completo para pruebas locales sin depender de tokens de nube.

PHP · AIService Docker Compose Groq Cascade Ollama Local

Problema Raíz Identificado

⚠ 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

Cambios Entregados

whatsapp-crm/src/AIService.php DESPLEGADO ✓

Reescritura de callGroqAPI(): doble bucle modelo×key, delay 150ms entre modelos, soporte Ollama vía OLLAMA_URL env.

  • Nuevo método privado _callOllamaCompat() — API compatible con OpenAI
  • OLLAMA_MODEL configurable por env var (default: hermes3:latest)
  • Logs estructurados: [AMR-AI] model=X HTTP=Y err=…
  • Garantía: si todos los LLMs fallan → canned response (no excepción fatal)
whatsapp-crm/Dockerfile.local NUEVO

PHP 8.2-Apache + extensiones pdo pdo_mysql pdo_sqlite mbstring zip curl. El Dockerfile de producción solo tenía pdo_sqlite.

whatsapp-crm/docker-compose.local.yml NUEVO

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.

whatsapp-crm/db/init-full.sql NUEVO

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.

whatsapp-crm/.env.local NUEVO · no commitear

Config local: MySQL Docker, Ollama en host, keys de Groq/OpenRouter opcionales. Cubierto por .gitignore (.env.*).

Diagrama: Cascada LLM (AIService + test_generator)

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

Levantar entorno local

  1. 1Editar whatsapp-crm/.env.local — pegar claves Groq si deseas probar la cascada en nube
  2. 2Verificar Ollama corriendo: ollama list — se necesita al menos un modelo (hermes3)
  3. 3Levantar stack:
    cd whatsapp-crm
    docker compose -f docker-compose.local.yml up --build -d
  4. 4Abrir CRM → http://localhost:8090
  5. 5Correr tests → http://localhost:8090/test_suite.php
  6. !Para ver los logs de cascada LLM: docker logs crm_app_local | grep AMR-AI

Verificar estado tokens Groq

Para 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.

⚡ AMR TECH™ · Desarrollado / Auditado por Anderson Mares  |  AUD-20260925-001  |  Generado automáticamente por Claude Code