Etapa 0: entorno, configuración validada, modelo y entrenador

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>
This commit is contained in:
2026-07-27 23:04:45 -03:00
commit 90ac2a6582
33 changed files with 2838 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
# Modelo diminuto a nivel de caracteres, solo para el smoke test de la Etapa 0.
#
# No produce nada útil: existe para validar en ~10 minutos que CUDA, el
# entrenador, el checkpointing, la reanudación y el flujo por SSH funcionan
# antes de comprometer días de cómputo.
name: char-smoke
vocab_size: 256 # se ajusta al vocabulario real del texto al cargar los datos
n_layer: 4
n_head: 4
n_kv_head: 2
d_model: 128
seq_len: 256
ffn_mult: 2.6667
ffn_multiple_of: 32
rope_theta: 10000.0
norm_eps: 1.0e-5
tie_embeddings: true
qk_norm: true
z_loss_weight: 1.0e-4
dropout: 0.0
init_std: 0.02
+30
View File
@@ -0,0 +1,30 @@
# ~50M parámetros. Primer modelo real, pensado para la 2060.
#
# Con vocab 32k y d_model 512, la tabla de embeddings sola son 16.7M
# parámetros: atarla con la capa de salida (tie_embeddings) ahorra un tercio
# del modelo. En modelos chicos esa decisión no es un detalle.
#
# seq_len 2048 y no 1024: el contexto recuperado de las bases del sistema se
# inyecta ahí, así que el presupuesto de contexto es un recurso de primer orden.
name: tiny-50m
vocab_size: 32768
n_layer: 12
n_head: 8
n_kv_head: 2 # GQA 4:1 — reduce la caché KV sin costo medible de calidad
d_model: 512
seq_len: 2048
ffn_mult: 2.6667 # 8/3, el habitual para SwiGLU (tres matrices en vez de dos)
ffn_multiple_of: 64
rope_theta: 10000.0
norm_eps: 1.0e-5
tie_embeddings: true
# qk_norm y z_loss no son opcionales entrenando en float16 en la 2060:
# son lo que evita que el loss explote a mitad de corrida.
qk_norm: true
z_loss_weight: 1.0e-4
dropout: 0.0 # con 3B tokens y 50M params no hay sobreajuste que combatir
init_std: 0.02