File size: 7,547 Bytes
185a43d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1e1940b
185a43d
 
 
 
 
 
 
1e1940b
185a43d
 
 
1e1940b
185a43d
 
 
 
1e1940b
185a43d
 
 
 
1e1940b
185a43d
 
 
 
1e1940b
185a43d
 
 
 
1e1940b
185a43d
1e1940b
185a43d
 
1e1940b
185a43d
 
 
1e1940b
185a43d
 
 
1e1940b
185a43d
 
 
1e1940b
185a43d
 
 
1e1940b
185a43d
 
 
1e1940b
185a43d
 
 
1e1940b
185a43d
 
 
1e1940b
185a43d
fa34482
 
 
 
1e1940b
fa34482
 
 
 
1e1940b
 
 
 
 
 
185a43d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1e1940b
185a43d
 
 
 
 
1e1940b
 
185a43d
 
 
 
 
 
1e1940b
 
185a43d
1e1940b
 
185a43d
1e1940b
 
185a43d
 
1e1940b
185a43d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/usr/bin/env python3
"""Golden geometry — regression net for the allocator.

Two agents edit this tree (see AGENTS.md). Any change to classifier.py /
constants.py / config_generator.py moves the tier map, and until today
nothing noticed: the 1D/F32 fix silently reshaped every distribution in the
lab, and the only reason it was caught at all was the pre-flight audit I
happened to add. A golden fixture is cheaper than that argument.

Golden values were recorded from the artefacts on 2026-09-28, AFTER the
1D/F32 law landed, and the ZOO row is the stand the README quotes. If a row
fails, either the allocator changed (say so in the commit and re-record
deliberately) or something broke (that is the bug).

Models are gitignored and move around, so a missing model is a skip, never a
failure. No GPU, no network, no writes outside stdout.

    python tests/test_geometry.py
"""
import os
import sys
import warnings

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT)
warnings.simplefilter("ignore")

from llama_inspect import read_model
from imatrix_reader import (read_imatrix, combine_imatrix, detect_tied_groups,
                            build_importance_table)
from classifier import optimal_classify, optimal_classify_topdown, compute_stats

DL = "/mnt/Vsio/Downloads"
PROG = "/mnt/Vsio/shq-program/models"

# (label, model, imatrix, size_mib, utility, top_down, allow_q3, golden)
CASES = [
    ("zoo-stand 1.7B @1000 mse  (README-ZOO baseline)",
     f"{DL}/Spark-X2.5-1.7B-BF16.gguf", f"{PROG}/Spark-X2.5-1.7B-imatrix.gguf",
     1000, "mse", False, False,
     {"F32": 57, "Q4_K": 105, "Q5_K": 8, "Q6_K": 56}),

    ("MiniCPM5-2B @1700 mse    (bottom-up default)",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1700, "mse", False, False,
     {"F32": 85, "IQ4_XS": 40, "Q4_K": 19, "Q5_K": 71, "Q6_K": 45, "Q8_0": 121}),

    ("MiniCPM5-2B @1700 smse   (blend lens)",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1700, "smse", False, False,
     {"F32": 85, "IQ4_XS": 40, "Q4_K": 19, "Q5_K": 71, "Q6_K": 45, "Q8_0": 121}),

    ("MiniCPM5-2B @1400 top-down",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1400, "mse", True, False,
     {"F32": 85, "IQ4_XS": 39, "Q4_K": 255, "Q5_K": 2}),

    ("MiniCPM5-2B @1200 smse allow-q3",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1200, "smse", False, True, None),   # None = recorded on first run

    # --- archived lenses (LEGACY.md): reproduction fixtures only -----------
    ("MiniCPM5-2B @1700 smape  (barbell lens)",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1700, "smape", False, False, None),

    ("MiniCPM5-2B @1700 rmse   (perfectionist rescale)",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1700, "rmse", False, False, None),

    ("MiniCPM5-2B @1700 srmse  (SMAPE x RMSE)",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1700, "srmse", False, False, None),

    ("MiniCPM5-2B @1700 mix    (per-group kings/junk)",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1700, "mix", False, False, None),

    ("MiniCPM5-2B @1700 logcosh (gain reshaper)",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1700, "logcosh", False, False, None),

    ("MiniCPM5-2B @1700 top-down smape  (TD barbell)",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     1700, "smape", True, False, None),

    ("MiniCPM5-2B @2500 squeeze (dungeon/palace binary)",
     f"{DL}/MiniCPM5-2B-BF16.gguf", f"{DL}/MiniCPM5-2B.imatrix.gguf",
     2500, "mse", False, False, None),

    ("RINIQ-M2 @5100 mse       (qwen35 hybrid + MTP)",
     f"{DL}/RINIQ-M2-BF16.gguf", f"{DL}/RINIQ-M2-qwen38.imatrix.gguf",
     5100, "mse", False, False,
     {"F32": 177, "Q4_K": 216, "Q5_K": 34}),

    ("Mellum2.1 @7500 smse     (mellum2 MoE, routers F16)",
     f"{DL}/Mellum2.1-12B-A2.5B-Thinking-BF16.gguf",
     f"{DL}/Mellum2.1-12B-A2.5B-Thinking-imatrix.gguf",
     7500, "smse", False, False, None),

    ("Mellum2.1 @7500 huber    (MoE fat middle vs smse pyramid)",
     f"{DL}/Mellum2.1-12B-A2.5B-Thinking-BF16.gguf",
     f"{DL}/Mellum2.1-12B-A2.5B-Thinking-imatrix.gguf",
     7500, "huber", False, False, None),

    ("Ling-3.0-tiny @5100 gnom (top-down, netpred)",
     "/mnt/Vsio/assets/models/Ling-3.0-tiny-bf16.gguf",
     f"{PROG}/Ling-3.0-tiny-imatrix.gguf",
     5100, "gnom", True, False, None),
]

GOLDEN_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                           "geometry_golden.json")


def load_golden():
    if os.path.exists(GOLDEN_FILE):
        import json
        return json.load(open(GOLDEN_FILE))
    return {}


def save_golden(g):
    import json
    with open(GOLDEN_FILE, "w") as f:
        json.dump(g, f, indent=2, sort_keys=True)


def geometry(case):
    (_label, model, imat, size, util, td, q3, _gold) = case
    m = read_model(model)
    im = combine_imatrix([read_imatrix(imat)])
    tg = detect_tied_groups(im)
    it = build_importance_table(im, m)
    uopt = {"mode": util, "mix_base": "smape"}
    if util == "gnom":
        uopt["netpred"] = os.path.join(ROOT, "models", "netpred_ling_groups.json")
    if util == "mix":
        # main.py ranks kings by importance and freezes the top fraction once
        scored = sorted(((it[n]["importance_mean"], n) for n in it), reverse=True)
        k = max(1, int(len(scored) * 0.2))
        uopt["mix_top"] = frozenset(rep for _, rep in scored[:k])
    if td:
        a, padded = optimal_classify_topdown(it, tg, m, target_size_mib=size,
                                             uopt=uopt)
    elif "squeeze" in _label:
        a, padded = optimal_classify(it, tg, m, target_size_mib=size, uopt=uopt,
                                     allowed_tiers=["IQ1_S", "F16"])
    else:
        a, padded = optimal_classify(it, tg, m, target_size_mib=size, allow_q3=q3,
                                     uopt=uopt)
    ne = {k: v["n_elements"] for k, v in m["tensors"].items()}
    from classifier import _f32_map
    st = compute_stats(a, ne, padded, _f32_map(m["tensors"]))
    return {k: v for k, v in st["by_tier_count"].items() if v}, st["total_mib"]


def main():
    golden = load_golden()
    failures = skipped = 0
    for case in CASES:
        label = case[0]
        if not (os.path.exists(case[1]) and os.path.exists(case[2])):
            print(f"SKIP  {label}  (model or imatrix not on this box)")
            skipped += 1
            continue
        got, total = geometry(case)
        key = label
        if key not in golden:
            golden[key] = {"tiers": got, "total_mib": round(total, 1)}
            save_golden(golden)
            print(f"REC   {label}  -> {got} ({total:.1f} MiB)")
            continue
        want = golden[key]["tiers"]
        if got == want:
            print(f"ok    {label}  ({total:.1f} MiB)")
        else:
            failures += 1
            print(f"FAIL  {label}")
            print(f"        want {want}")
            print(f"        got  {got}")
            for t in sorted(set(want) | set(got)):
                if want.get(t) != got.get(t):
                    print(f"        {t}: {want.get(t, 0)} -> {got.get(t, 0)}")
    print(f"\n{len(CASES) - skipped - failures} ok, {failures} failed, "
          f"{skipped} skipped")
    return 1 if failures else 0


if __name__ == "__main__":
    sys.exit(main())