scripts/remote.sh hace `source .env`, pero los procesos de Python no heredan eso: los SDKs leen variables de entorno, y nada cargaba el archivo. Una clave correctamente escrita en .env simplemente no existía para el proceso, y el síntoma —error de autenticación con el archivo bien configurado— es de los más molestos de diagnosticar. load_dotenv() se implementa a mano en vez de agregar python-dotenv: son veinte líneas y evita una dependencia más en el servidor de entrenamiento. Detalles que importan: - No pisa variables que ya existan en el entorno. Una variable exportada en la shell o inyectada por el orquestador gana sobre el archivo, que es lo que se espera en producción. - Ignora claves con valor vacío: una variable vacía autentica peor que una ausente, porque parece presente. - Acepta la forma `export FOO=bar`, porque el mismo archivo lo consume `source .env` desde remote.sh. - Devuelve nombres, nunca valores: estos archivos tienen secretos y no deben terminar en un log. Además, ClienteAnthropic ahora falla con un mensaje que dice qué hacer cuando no hay credencial, en vez de propagar el error del SDK. 10 tests nuevos (102 en total). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ENLACE
Modelo de lenguaje propio, entrenado desde cero, para asistencia general y familiar en español. No es fine-tuning de un modelo existente: tokenizer, datos y pesos son propios.
El plan completo — etapas, presupuestos de cómputo, arquitectura de datos y
criterios de verificación — está en docs/PLAN.md.
Estado
Etapa 0 (entorno y validación del stack) implementada y verificada:
- Capa de configuración validada, con composición por capas y perfiles de hardware.
- Arquitectura del modelo: RMSNorm, SwiGLU, RoPE, GQA, QK-norm, z-loss.
- Entrenador con WSD, precisión mixta, acumulación de gradiente y reanudación exacta.
- Cargadores de datos: bytes (smoke test) y shards
uint16(corpus real).
Primera tool del agente (Etapa 4), que no depende del modelo y ya funciona:
- Búsqueda web con DuckDuckGo, sin API key ni cuenta en ningún servicio.
.venv/bin/python -m enlace.agent.tools.search "que es home assistant"
71 tests, incluido el de reanudación exacta.
Pendiente: Etapa 1 en adelante (corpus, tokenizer, pretraining, post-training, agente, bases del sistema, memoria, snapshots).
Puesta en marcha
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
scripts/prepare_smoke_data.sh # texto en español de dominio público
.venv/bin/python -m enlace.train.train configs/runs/smoke-cpu.yaml
scripts/test.sh
En el servidor con GPU, por SSH (ver .env.example):
scripts/remote.sh sync
scripts/remote.sh run configs/runs/smoke-2060.yaml # smoke test, ~10 min
scripts/remote.sh run configs/runs/pretrain-2060.yaml # pretraining, 1-2 días
scripts/remote.sh logs
Toda corrida larga arranca bajo tmux: cortar el SSH no mata el entrenamiento.
Configuración
Ningún hiperparámetro vive en el código. Las configs se componen por capas:
# configs/runs/pretrain-2060.yaml
include:
hardware: hardware/turing-2060.yaml # dtype, backend de atención, batch
model: model/tiny-50m.yaml # capas, dimensiones, contexto
train: train/pretrain.yaml # LR, schedule, intervalos
data: data/corpus.yaml # de dónde salen los tokens
Overrides puntuales desde la línea de comandos, para probar variantes sin editar archivos:
.venv/bin/python -m enlace.train.train configs/runs/smoke-cpu.yaml train.seed=99
Una config inválida falla al arrancar con un mensaje concreto, no a las tres horas de entrenamiento.
Hardware
El perfil de hardware es la única capa que cambia al migrar de placa.
| Perfil | Placa | dtype | Atención | Notas |
|---|---|---|---|---|
turing-2060 |
RTX 2060 12 GB (sm_75) | float16 + GradScaler | mem_efficient | Turing no soporta bfloat16 ni FlashAttention-2 |
blackwell-5090 |
RTX 5090 32 GB (sm_120) | bfloat16 | flash | Requiere PyTorch ≥ 2.7 con CUDA 12.8 |
cpu |
— | float32 | math | Solo desarrollo y tests |
enlace/train/backends.py es el único archivo del entrenamiento que conoce
diferencias entre placas, y valida el perfil contra la GPU real antes de
empezar: pedir bfloat16 en Turing falla de inmediato en vez de degradarse en
silencio.
Estructura
enlace/config/ Esquemas pydantic y composición de YAML
enlace/model/ Transformer decoder-only y selección de backend de atención
enlace/train/ Bucle, schedules, checkpointing, detección de hardware
enlace/data/ Cargadores con reanudación exacta
configs/ hardware × model × train × data, compuestos en configs/runs/
scripts/ Utilidades: remote.sh, test.sh, prepare_smoke_data.sh
tests/ Suite completa; test_resume.py es el crítico