File size: 1,786 Bytes
89bd096
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""Phase 0 — vérifie que les tailles de modèle annoncées dans les docs sont vraies.

Un chiffre de paramètres écrit dans la documentation peut dériver : ce test
recalcule les valeurs à partir de `configs/model.yaml` et échoue en cas d'écart.
"""

from pathlib import Path

import pytest

yaml = pytest.importorskip("yaml")

ROOT = Path(__file__).resolve().parents[1]


@pytest.fixture(scope="module")
def cfg():
    return yaml.safe_load((ROOT / "configs" / "model.yaml").read_text(encoding="utf-8"))


def count_params(vocab: int, n_embd: int, n_layer: int, tie: bool, ffn_mult: int = 4) -> int:
    """Compte les paramètres d'un transformer decoder-only pre-norm sans biais."""
    embed = vocab * n_embd
    per_layer = 4 * n_embd * n_embd + 2 * n_embd * (ffn_mult * n_embd) + 2 * n_embd
    total = embed + n_layer * per_layer + n_embd
    if not tie:
        total += vocab * n_embd
    return total


def test_default_profile_matches_documented_size(cfg):
    tm, tk = cfg["text_model"], cfg["tokenizer"]
    n = count_params(tk["vocab_size"], tm["n_embd"], tm["n_layer"], tm["tie_embeddings"])
    assert round(n / 1e6, 1) == 22.9, f"profil défaut = {n/1e6:.1f}M, attendu 22.9M"


def test_50m_profile_is_actually_about_50m(cfg):
    tm, tk = cfg["text_model_50m"], cfg["tokenizer"]
    n = count_params(tk["vocab_size"], tm["n_embd"], tm["n_layer"], tm["tie_embeddings"])
    assert 48e6 <= n <= 53e6, f"profil 50m = {n/1e6:.1f}M, hors de la cible ~50M"


def test_docs_state_the_real_default_size(cfg):
    arch = (ROOT / "docs" / "architecture.md").read_text(encoding="utf-8")
    assert "22.9 M" in arch, "architecture.md doit annoncer la vraie taille du profil défaut"
    assert "51.6 M" in arch, "architecture.md doit annoncer la vraie taille du profil 50M"