Python · 6205 bytes Raw Blame History
1 """Every curated entry is well-formed and passes the audit-02 F04/F21 rules."""
2
3 from __future__ import annotations
4
5 import re
6
7 import pytest
8
9 from dlm.base_models import BASE_MODELS, known_keys
10 from dlm.base_models.registry import _ENTRIES
11
12 _SHA_RE = re.compile(r"^[0-9a-f]{40}$")
13
14
15 class TestLaunchTen:
16 def test_minimum_launch_entries(self) -> None:
17 # The original launch ten + PaliGemma (Sprint 35 v1). Additional
18 # VL bases land in Sprint 35.3; this floor only enforces "don't
19 # regress below what we've shipped".
20 assert len(BASE_MODELS) >= 11
21 assert len(_ENTRIES) >= 11
22
23 def test_entries_keyed_by_key(self) -> None:
24 for entry in _ENTRIES:
25 assert BASE_MODELS[entry.key] is entry
26
27 def test_known_keys_stable_ordering(self) -> None:
28 keys = known_keys()
29 assert isinstance(keys, tuple)
30 assert list(keys) == list(BASE_MODELS.keys())
31
32
33 class TestRevisionPinning:
34 """Audit-02 F11: every registry entry has a real 40-char commit SHA."""
35
36 @pytest.mark.parametrize("entry", _ENTRIES, ids=lambda e: e.key)
37 def test_revision_is_40char_hex(self, entry: object) -> None:
38 assert _SHA_RE.fullmatch(entry.revision), ( # type: ignore[attr-defined]
39 f"{entry.key} has non-conforming revision {entry.revision!r}" # type: ignore[attr-defined]
40 )
41
42
43 class TestLicenseFields:
44 """Audit-02 F04 + F21: license + gating fields populated correctly."""
45
46 @pytest.mark.parametrize("entry", _ENTRIES, ids=lambda e: e.key)
47 def test_license_spdx_present(self, entry: object) -> None:
48 assert entry.license_spdx # type: ignore[attr-defined]
49
50 @pytest.mark.parametrize("entry", _ENTRIES, ids=lambda e: e.key)
51 def test_gated_entries_have_license_url(self, entry: object) -> None:
52 if entry.requires_acceptance: # type: ignore[attr-defined]
53 assert entry.license_url, ( # type: ignore[attr-defined]
54 f"{entry.key} is gated but has no license_url" # type: ignore[attr-defined]
55 )
56
57 def test_llama_entries_are_gated_and_nonredistributable(self) -> None:
58 """Explicit check: shipped Llama entries keep the Meta gating pattern."""
59 for key in ("llama-3.2-1b", "llama-3.2-3b", "llama-3.3-8b-instruct"):
60 entry = BASE_MODELS[key]
61 assert entry.requires_acceptance is True
62 assert entry.redistributable is False
63
64 def test_gemma2_entries_are_gated_and_nonredistributable(self) -> None:
65 for key in ("gemma-2-2b-it", "gemma-2-9b-it"):
66 entry = BASE_MODELS[key]
67 assert entry.requires_acceptance is True
68 assert entry.redistributable is False
69
70 def test_apache_entries_are_open_and_redistributable(self) -> None:
71 for key in (
72 "qwen2.5-0.5b",
73 "qwen2.5-1.5b",
74 "qwen2.5-coder-1.5b",
75 "qwen3-1.7b",
76 "qwen3-1.7b-thinking",
77 "qwen3-4b",
78 "qwen3-8b",
79 "mixtral-8x7b-instruct",
80 "smollm3-3b",
81 "olmo-2-7b-instruct",
82 "qwen2-audio-7b-instruct",
83 "smollm2-135m",
84 "smollm2-360m",
85 "smollm2-1.7b",
86 ):
87 entry = BASE_MODELS[key]
88 assert entry.license_spdx == "Apache-2.0"
89 assert entry.requires_acceptance is False
90 assert entry.redistributable is True
91
92 def test_phi_is_mit(self) -> None:
93 for key in ("phi-3.5-mini", "phi-4-mini-reasoning"):
94 assert BASE_MODELS[key].license_spdx == "MIT"
95
96
97 class TestArchitectureShapes:
98 """Templates, gguf_arch, and target_modules match the architecture family."""
99
100 def test_qwen25_entries_use_qwen2_gguf_arch(self) -> None:
101 for key, entry in BASE_MODELS.items():
102 # Audio-language Qwen2 variants carry a distinct gguf_arch
103 # (no llama.cpp converter support) and a multi-modal template.
104 if not key.startswith("qwen2.5") or entry.modality != "text":
105 continue
106 assert entry.gguf_arch == "qwen2"
107 assert entry.architecture == "Qwen2ForCausalLM"
108 assert entry.template == "chatml"
109
110 def test_llama_entries_use_llama_gguf_arch(self) -> None:
111 for key in ("llama-3.2-1b", "llama-3.2-3b", "llama-3.3-8b-instruct"):
112 entry = BASE_MODELS[key]
113 assert entry.gguf_arch == "llama"
114 assert entry.architecture == "LlamaForCausalLM"
115 assert entry.template == "llama3"
116
117 def test_phi_uses_fused_qkv_target_modules(self) -> None:
118 for key, template in (("phi-3.5-mini", "phi3"), ("phi-4-mini-reasoning", "phi4mini")):
119 entry = BASE_MODELS[key]
120 assert "qkv_proj" in entry.target_modules
121 assert entry.gguf_arch == "phi3"
122 assert entry.template == template
123
124 def test_olmo2_uses_olmo2_converter_path(self) -> None:
125 entry = BASE_MODELS["olmo-2-7b-instruct"]
126 assert entry.gguf_arch == "olmo2"
127 assert entry.architecture == "Olmo2ForCausalLM"
128 assert entry.template == "olmo2"
129
130 def test_gemma2_uses_gemma2_converter_path(self) -> None:
131 for key in ("gemma-2-2b-it", "gemma-2-9b-it"):
132 entry = BASE_MODELS[key]
133 assert entry.gguf_arch == "gemma2"
134 assert entry.architecture == "Gemma2ForCausalLM"
135 assert entry.template == "gemma2"
136
137 def test_size_gb_fp16_monotonic_within_family(self) -> None:
138 qwen_sizes = [
139 BASE_MODELS[k].size_gb_fp16 for k in ("qwen2.5-0.5b", "qwen2.5-1.5b", "qwen2.5-3b")
140 ]
141 assert qwen_sizes == sorted(qwen_sizes)
142 qwen3_sizes = [
143 BASE_MODELS[k].size_gb_fp16
144 for k in ("qwen3-1.7b", "qwen3-1.7b-thinking", "qwen3-4b", "qwen3-8b")
145 ]
146 assert qwen3_sizes == sorted(qwen3_sizes)
147 smol_sizes = [
148 BASE_MODELS[k].size_gb_fp16 for k in ("smollm2-135m", "smollm2-360m", "smollm2-1.7b")
149 ]
150 assert smol_sizes == sorted(smol_sizes)
151 gemma_sizes = [BASE_MODELS[k].size_gb_fp16 for k in ("gemma-2-2b-it", "gemma-2-9b-it")]
152 assert gemma_sizes == sorted(gemma_sizes)