ruff estaba configurado en pyproject.toml desde el primer commit y jamás se
había corrido. Tenía 15 hallazgos. Dos importan más allá del estilo:
- zip() sin strict= trunca en silencio al más corto. En las comparaciones de
lotes eso significa que un test podía pasar sin haber comparado todo. Donde
los largos deben coincidir ahora es strict=True; donde difieren a propósito
(pares consecutivos) queda strict=False, que documenta la intención.
- Un import sin usar delataba algo peor: BraveBackend se había escrito sin una
sola prueba. Se agregan ocho, contra una respuesta con la forma que devuelve
la API, incluidas la limpieza de etiquetas, el caso de límite de tasa —que
tiene que distinguirse de 'no respondió'— y que la credencial viaje en la
cabecera y nunca en la URL. El respaldo tiene que funcionar justo cuando el
primario ya falló; merecía la misma cobertura.
El resto es orden de imports, collections.abc y líneas largas.
Base del proyecto ENLACE: un modelo de lenguaje propio entrenado desde cero,
en español, para asistencia general y familiar. El plan completo está en
docs/PLAN.md.
Esta etapa establece el andamiaje y lo verifica de punta a punta:
- Configuración por capas (hardware × model × train × data) validada con
pydantic. Ningún hiperparámetro vive en el código y una config inválida
falla al arrancar, no a las tres horas de entrenamiento.
- Perfiles de hardware que aíslan el salto de GPU: la RTX 2060 (Turing) no
soporta bfloat16 ni FlashAttention-2, así que entrena en float16 con
GradScaler y backend mem_efficient; el perfil de la 5090 ya está escrito.
backends.py valida el perfil contra la GPU real antes de empezar.
- Transformer decoder-only estilo Llama: RMSNorm, SwiGLU, RoPE, GQA,
embeddings atados, QK-norm y z-loss. Los dos últimos son lo que mantiene
estable el entrenamiento en float16.
- Entrenador con schedule WSD, acumulación de gradiente, precisión mixta,
checkpointing atómico y reanudación exacta.
- Cargadores de datos con estado serializable: bytes para el smoke test y
shards uint16 para el corpus real.
48 tests, entre ellos el crítico: reanudar desde un checkpoint reproduce los
pesos de una corrida ininterrumpida, parámetro por parámetro.
Verificado en CPU: 300 pasos sobre texto en español, loss 3.07 -> 1.63.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>