Contexto
En CreaRack Pro existen múltiples callsites que invocan proveedores de IA (Gemma 4 vía google-genai SDK, Claude Haiku/Sonnet vía Anthropic). Antes de la sesión 61 (s61), los nombres de modelo estaban dispersos como literales hardcoded en 9 puntos del código de runtime:
| Callsite (antes de s61) | Literal hardcoded |
|---|---|
monitoring/services/ai_providers/google_genai.py | DEFAULT_MODEL = "gemma-4-26b-a4b-it" |
core/services/ai_providers/router.py | DEFAULT_GOOGLE_GENAI_MODEL + DEFAULT_CLAUDE_MODEL |
core/services/ai_operations.py | AIOperations.MODEL = "gemma-4-26b-a4b-it" |
blueprints/services/google_genai_driver.py | 4× os.environ.get("GEMMA4_GENAI_*") con defaults inline |
monitoring/services/ai_providers/claude.py | CLAUDE_MODEL = "claude-haiku-4-5-20251001" |
monitoring/services/tutor_service.py | model="claude-haiku-4-5-20251001" |
monitoring/services/explain_service.py | 2× model="claude-haiku-4-5-20251001" |
La Regla 8 de CLAUDE.md establecía “modelo único por proveedor”, pero su aplicación dependía de disciplina humana: cambiar de modelo requería encontrar y editar los 9 sitios sin omitir ninguno — drift inevitable.
Decisión
Todos los model strings del runtime de la aplicación Django viven exclusivamente en config/settings/base.py. Los callsites leen settings.NOMBRE_SETTING; nunca literales, nunca os.environ.get() directo en código de aplicación.
Settings nuevas añadidas (s61)
# config/settings/base.py
ANTHROPIC_HAIKU_MODEL = os.getenv("ANTHROPIC_HAIKU_MODEL", "claude-haiku-4-5-20251001")
ANTHROPIC_SONNET_MODEL = os.getenv("ANTHROPIC_SONNET_MODEL", "claude-sonnet-4-6")
# (ya existían: GEMMA4_GENAI_MODEL, EDGE_AI_GOOGLE_GENAI_MODEL, GEMMA4_GENAI_SEED, ...)
Excepción legítima documentada
scripts/test_*.py— los model strings son el input bajo prueba en regression tests; no deben leer settings..github/scripts/bib_ingest.py— script CI que no carga Django; usaos.getenv("BIB_INGEST_TRIAGE_MODEL", "claude-haiku-4-5")yos.getenv("BIB_INGEST_DEEP_MODEL", "claude-sonnet-4-6")directamente.
Consecuencias
Positivas
- Cambiar de modelo = 1 env var + redeploy (~2 min en Dokploy panel). No hay búsqueda en el código.
- Drift imposible: si no hay literales que cambiar, no hay forma de dejar un callsite con el modelo antiguo.
- Rollback trivial: revertir la env var en Dokploy restaura el modelo anterior sin ningún deploy de código.
- Defaults idénticos: comportamiento PROD invariante tras el merge — pure refactor.
Negativas / trade-offs
settings.ANTHROPIC_HAIKU_MODELno es obvio para quien lee el callsite por primera vez sin conocer el contexto; requiere consultarconfig/settings/base.pyocontext/AI_CONFIG.md.- El script CI (
bib_ingest.py) mantiene su propia gestión de modelos por imposibilidad técnica (no carga Django) — excepción documentada, no una contradicción.
Fuente de verdad operacional
context/AI_CONFIG.md (añadido en s61) contiene:
- Tabla completa env var → callsite → propósito (10 filas).
- Procedimiento paso a paso para cambio de modelo en STAGE → PROD → rollback.
- Restricciones inviolables de provider (whitelist Regla 8).
- Historial de decisiones AI desde s49.
Procedimiento para futuros cambios de modelo
- Verificar que el modelo cumple Regla 8 (Google AI Studio Paid Tier o Anthropic, GDPR EU).
- Probar en local con
.envy luego en STAGE via Dokploy panel. - Validar ≥ 24 h sin regresión → desplegar en PROD.
- Si el nuevo modelo lleva ≥ 30 días en PROD sin incidencias, actualizar el default en
settings/base.py, este ADR y Regla 8 deCLAUDE.md.
Detalle completo: context/AI_CONFIG.md §3.
Estado actual de providers (post-s61)
| Provider | Estado | Setting |
|---|---|---|
Google AI Studio — Gemma 4 (google-genai SDK) | ✅ Canónico | GEMMA4_GENAI_MODEL, EDGE_AI_GOOGLE_GENAI_MODEL |
| Anthropic Claude Haiku 4.5 | ✅ Alternativo CNS/Tutor/Explain | ANTHROPIC_HAIKU_MODEL |
| Anthropic Claude Sonnet 4.6 | ✅ Reservado (CI + runtime futuro) | ANTHROPIC_SONNET_MODEL |
| OpenRouter | ❌ Retirado s55 | — |
| Vertex AI directo | ⏸️ Postpuesto s50 | — |
| Free tiers / GPT-* / Gemini Flash | ❌ Excluidos | — |
Lección sistémica
La política “modelo único” (Regla 8) no se sostiene con disciplina humana cuando el código tiene N callsites con literales. La aplicación tiene que ser estructural: si no hay literales que cambiar, no hay drift posible.
Aplicable a futuros tokens centralizables: URLs de servicio, claves de caché, timeouts AI — cualquier constante que aparezca en ≥ 3 callsites merece su propio setting.
Véase también
- [[concept—ai—monoproveedor-regla-8]]
- [[feature—monitoring—cns-ai-providers]]
- [[feature—blueprints—autoplan-google-genai]]
- [[entity—core—service—ai-operations]]
- [[entity—core—service—ai-provider-router]]