Files
enlace/tests/test_schedules.py
T
msaldain 4048936067 Corregir lo que reportó ruff, que nunca se había ejecutado
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.
2026-07-28 07:25:51 -03:00

55 lines
1.6 KiB
Python

"""Forma del schedule WSD."""
from __future__ import annotations
from enlace.config.schema import ScheduleConfig
from enlace.train.schedules import build_lr_fn
def _lr_fn(max_steps=1000, warmup=100, decay=200, min_ratio=0.0, base=1e-3):
cfg = ScheduleConfig(kind="wsd", warmup_steps=warmup, decay_steps=decay, min_lr_ratio=min_ratio)
return build_lr_fn(cfg, base, max_steps)
def test_warmup_sube_linealmente_desde_arriba_de_cero():
lr = _lr_fn()
assert lr(0) > 0.0 # el primer paso no se desperdicia con lr=0
assert lr(0) < lr(50) < lr(99)
assert lr(99) == 1e-3
def test_la_fase_estable_es_plana():
lr = _lr_fn()
assert lr(100) == lr(500) == lr(799) == 1e-3
def test_el_decay_baja_de_forma_monotona_hasta_cero():
lr = _lr_fn()
valores = [lr(s) for s in range(800, 1000)]
assert all(a >= b for a, b in zip(valores, valores[1:], strict=False))
assert valores[0] == 1e-3
assert valores[-1] < 1e-4
def test_min_lr_ratio_pone_un_piso():
lr = _lr_fn(min_ratio=0.1)
assert lr(999) >= 1e-4 * 0.99
def test_sin_decay_el_lr_queda_plano_hasta_el_final():
lr = _lr_fn(decay=0)
assert lr(999) == 1e-3
def test_extender_la_corrida_mueve_el_inicio_del_decay():
"""Documenta la trampa: max_steps define dónde empieza a decaer el LR.
Reanudar una corrida interrumpida exige el mismo max_steps; extenderla es
una decisión distinta, que hay que tomar ramificando desde un checkpoint
anterior al decay.
"""
corto = _lr_fn(max_steps=1000)
largo = _lr_fn(max_steps=2000)
assert corto(850) < corto(700) # ya está decayendo
assert largo(850) == largo(700) # todavía en la fase estable