Etapa 3 del plan. Se elige la Batch API sobre llamadas sueltas porque cuesta la mitad y generar un dataset no es sensible a la latencia: es exactamente su caso de uso. A cambio el trabajo es asincrónico y puede tardar horas, así que todo el estado vive en disco y es reanudable — matar el proceso, perder la conexión o reiniciar el servidor no pierde nada ni gasta de nuevo. Cuatro decisiones que sostienen eso: - El custom_id se deriva del hash del contenido del pedido. El trabajo queda idempotente: re-generar la misma especificación produce los mismos IDs, así que lo ya resuelto se reconoce y no se vuelve a pagar. - Los resultados se indexan por custom_id, nunca por posición. La API los devuelve en cualquier orden, y emparejarlos por índice mezcla las respuestas en silencio; un dataset mal alineado es peor que uno vacío porque parece correcto. El cliente falso de los tests los invierte a propósito. - Los fallos se registran en errors.jsonl con su motivo en vez de descartarse, y --retry-failed reenvía solo esos. - El prompt de sistema compartido va marcado para caché: es idéntico entre miles de pedidos, y a ~0,1x del precio de entrada deja de contar. Los lotes se persisten después de cada envío y no al final, para que una caída a mitad de camino no deje lotes huérfanos sin registrar. El SDK de anthropic se importa de forma perezosa y queda como extra opcional: el servidor de entrenamiento no lo necesita y el paquete importa sin él. 21 tests nuevos (92 en total), todos contra un cliente falso — lo que hay que verificar es el harness, no el SDK. 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