Eclipse-Senpai commited on
Commit
adacba8
·
verified ·
1 Parent(s): 054df1d

remove dev tooling + staging notes from package (tests, make_charts, UPLOAD, ARCHITECTURE-VIEWER, pycache, benchmark_table.md)

Browse files
Files changed (37) hide show
  1. ARCHITECTURE-VIEWER.md +0 -35
  2. UPLOAD.md +0 -83
  3. __pycache__/configuration_minspark.cpython-312.pyc +0 -0
  4. __pycache__/generate.cpython-312.pyc +0 -0
  5. __pycache__/meiosis.cpython-312.pyc +0 -0
  6. __pycache__/modeling_minspark.cpython-312.pyc +0 -0
  7. __pycache__/run_lmeval.cpython-312.pyc +0 -0
  8. charts/benchmark_table.md +0 -5
  9. make_charts.py +0 -104
  10. tests/__init__.py +0 -0
  11. tests/__pycache__/__init__.cpython-312.pyc +0 -0
  12. tests/__pycache__/conftest.cpython-312-pytest-9.1.1.pyc +0 -0
  13. tests/__pycache__/test_architecture.cpython-312-pytest-9.1.1.pyc +0 -0
  14. tests/__pycache__/test_charts.cpython-312-pytest-9.1.1.pyc +0 -0
  15. tests/__pycache__/test_config.cpython-312-pytest-9.1.1.pyc +0 -0
  16. tests/__pycache__/test_generate.cpython-312-pytest-9.1.1.pyc +0 -0
  17. tests/__pycache__/test_lmeval.cpython-312-pytest-9.1.1.pyc +0 -0
  18. tests/__pycache__/test_modeling.cpython-312-pytest-9.1.1.pyc +0 -0
  19. tests/__pycache__/test_pipeline.cpython-312-pytest-9.1.1.pyc +0 -0
  20. tests/__pycache__/test_provenance.cpython-312-pytest-9.1.1.pyc +0 -0
  21. tests/__pycache__/test_raw_path.cpython-312-pytest-9.1.1.pyc +0 -0
  22. tests/__pycache__/test_readme.cpython-312-pytest-9.1.1.pyc +0 -0
  23. tests/__pycache__/test_remote_code.cpython-312-pytest-9.1.1.pyc +0 -0
  24. tests/__pycache__/test_tokenizer.cpython-312-pytest-9.1.1.pyc +0 -0
  25. tests/conftest.py +0 -6
  26. tests/test_architecture.py +0 -19
  27. tests/test_charts.py +0 -35
  28. tests/test_config.py +0 -40
  29. tests/test_generate.py +0 -101
  30. tests/test_lmeval.py +0 -59
  31. tests/test_modeling.py +0 -115
  32. tests/test_pipeline.py +0 -34
  33. tests/test_provenance.py +0 -38
  34. tests/test_raw_path.py +0 -31
  35. tests/test_readme.py +0 -69
  36. tests/test_remote_code.py +0 -70
  37. tests/test_tokenizer.py +0 -60
ARCHITECTURE-VIEWER.md DELETED
@@ -1,35 +0,0 @@
1
- # Hugging Face native architecture viewer — investigation verdict
2
-
3
- **Question:** Does the Hugging Face model page render a native architecture viewer
4
- for a custom-model (`model_type: minspark`, `trust_remote_code`) private repo?
5
-
6
- **Verdict: No.** The Hub's model-page architecture display is driven by a curated
7
- mapping of *recognized* transformers architectures (Llama, Mistral, GPT-2, BERT,
8
- Qwen, …) plus `safetensors` parameter metadata. It does not:
9
-
10
- - derive a diagram from a custom `config.json` + `auto_map` remote-code model, or
11
- - compute a parameter/architecture readout for an unknown `model_type`.
12
-
13
- Sources consulted (2026-08-06):
14
-
15
- - `huggingface.js` `packages/tasks/src/model-data.ts` — `ModelData.config` is a
16
- passthrough of `architectures`/`model_type`/`auto_map`; no formula or per-arch
17
- computation, no unknown-model fallback.
18
- - `packages/tasks/src/model-libraries-snippets.ts` — snippet generation branches
19
- on `pipeline_tag`/tags, not on a custom `model_type`.
20
- - Hub model-card docs (`docs/hub/model-cards`) — the card renders metadata
21
- (license, pipeline_tag, library_name, eval results) and markdown images; there
22
- is no universal architecture diagram for arbitrary custom code.
23
- - transformers `PreTrainedModel.from_pretrained` internals — `trust_remote_code`
24
- loads the custom module for *inference*; nothing emits a Hub-side diagram.
25
-
26
- For a **private** repo the effect is even more pronounced: the model page shows
27
- limited metadata and no architecture visualization for any unrecognized
28
- architecture.
29
-
30
- **Shipping decision:** the model card embeds a hand-authored `architecture.svg`
31
- (horizontal dataflow diagram) as the robust fallback. If Hugging Face later
32
- adds native viewer support for custom remote-code models, the SVG remains a
33
- correct, dependency-free description of the architecture.
34
-
35
- (Staging-only note — excluded from the Hub upload.)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
UPLOAD.md DELETED
@@ -1,83 +0,0 @@
1
- # min-spark Upload Plan (staging-only — no upload performed)
2
-
3
- **Target repo:** `MinimaLabs/min-spark` — **PRIVATE**, `type=model`.
4
-
5
- > This document is the upload-ready summary. No `hf repos create`/`hf upload`
6
- > was run during staging. The user reviews the staged package and authorizes
7
- > the upload.
8
-
9
- ## Tooling verified
10
-
11
- - `hf` CLI version: **1.17.0** (`hf version`)
12
- - `huggingface_hub` in the packaging venv (`~/.venvs/pico-hf`): **1.26.0**
13
-
14
- ## Staging → Hub file mapping
15
-
16
- | Staging file | Hub path | Included? |
17
- |--------------|----------|-----------|
18
- | `model.safetensors` | `model.safetensors` | ✅ weights |
19
- | `tokenizer.json` | `tokenizer.json` | ✅ tokenizer |
20
- | `config.json` | `config.json` | ✅ |
21
- | `configuration_minspark.py` | `configuration_minspark.py` | ✅ |
22
- | `modeling_minspark.py` | `modeling_minspark.py` | ✅ |
23
- | `meiosis.py` | `meiosis.py` | ✅ vendored model |
24
- | `tokenizer_config.json` | `tokenizer_config.json` | ✅ |
25
- | `special_tokens_map.json` | `special_tokens_map.json` | ✅ |
26
- | `generation_config.json` | `generation_config.json` | ✅ |
27
- | `README.md` | `README.md` | ✅ model card |
28
- | `LICENSE` | `LICENSE` | ✅ Apache-2.0 |
29
- | `requirements.txt` | `requirements.txt` | ✅ |
30
- | `requirements-eval.txt` | `requirements-eval.txt` | ✅ |
31
- | `run_lmeval.py` | `run_lmeval.py` | ✅ reproduction |
32
- | `record_deltas.py` | `record_deltas.py` | ✅ |
33
- | `deltas.json` | `deltas.json` | ✅ measured deltas |
34
- | `charts/accuracy.svg` | `charts/accuracy.svg` | ✅ |
35
- | `charts/byteppl.svg` | `charts/byteppl.svg` | ✅ |
36
- | `architecture.svg` | `architecture.svg` | ✅ |
37
- | `make_charts.py` | — | ❌ dev tool |
38
- | `UPLOAD.md` | — | ❌ staging note |
39
- | `ARCHITECTURE-VIEWER.md` | — | ❌ staging note |
40
- | `tests/` | — | ❌ test suite |
41
- | `__pycache__/`, `*.pyc` | — | ❌ |
42
-
43
- ## Exact upload command
44
-
45
- ```bash
46
- cd models/2026-07-meiosis/hf/min-spark
47
-
48
- # 1. Create the PRIVATE model repo (user runs this)
49
- hf repos create MinimaLabs/min-spark --type model --private
50
-
51
- # 2. Upload the full staging dir, excluding dev tooling + staging notes
52
- # (model.safetensors + tokenizer.json ARE included — not in the exclude set)
53
- hf upload MinimaLabs/min-spark . \
54
- --include "*" \
55
- --exclude "tests/ make_charts.py UPLOAD.md ARCHITECTURE-VIEWER.md __pycache__/** *.pyc .*_cache/**"
56
- ```
57
-
58
- The `hf upload` uses `--include "*"` to pull everything in the staging dir, and
59
- the `--exclude` set removes the dev tooling and the two staging-only notes. The
60
- weights and tokenizer (gitignored in PICO git) are uploaded because they are
61
- not in the exclude set.
62
-
63
- > Note: `hf upload` excludes are space-separated globs. Verify the resulting
64
- > file list with `hf upload MinimaLabs/min-spark . --dry-run ...` (if supported)
65
- > before the real upload.
66
-
67
- ## Post-upload checklist (user verifies on the private page)
68
-
69
- - [ ] README renders — quickstart, effort table, benchmark table, charts, SVG.
70
- - [ ] Benchmark table values match `charts/benchmark_table.md` exactly.
71
- - [ ] `Use in Transformers` button shows the model card snippet.
72
- - [ ] "Use in Transformers" snippet works: `AutoModelForCausalLM.from_pretrained(
73
- "MinimaLabs/min-spark", trust_remote_code=True)`.
74
- - [ ] License badge shows Apache-2.0.
75
- - [ ] Architecture viewer verdict recorded (no native viewer for custom
76
- `model_type`; `architecture.svg` is the fallback).
77
- - [ ] `pipeline_tag: text-generation` shows the text-generation widget.
78
- - [ ] The repo is private (verified under the org).
79
-
80
- ## No upload was performed during staging
81
-
82
- The staging suite is fully green; the two integration paths are validated; the
83
- stock-HFLM deltas are measured. Upload awaits explicit user authorization.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
__pycache__/configuration_minspark.cpython-312.pyc DELETED
Binary file (5.05 kB)
 
__pycache__/generate.cpython-312.pyc DELETED
Binary file (5.26 kB)
 
__pycache__/meiosis.cpython-312.pyc DELETED
Binary file (25.5 kB)
 
__pycache__/modeling_minspark.cpython-312.pyc DELETED
Binary file (10.6 kB)
 
__pycache__/run_lmeval.cpython-312.pyc DELETED
Binary file (11.7 kB)
 
charts/benchmark_table.md DELETED
@@ -1,5 +0,0 @@
1
- | Effort | BLiMP | ARC-Easy | ARC-Challenge | HellaSwag | PIQA | WikiText-2 byte-ppl |
2
- |--------|-------|----------|---------------|-----------|------|---------------------|
3
- | min-spark-low | 67.11% | 35.10% | 23.21% | 27.91% | 54.13% | 2.8783 |
4
- | min-spark-medium | 69.19% | 37.08% | 22.78% | 27.92% | 54.30% | 2.7747 |
5
- | min-spark-high | 69.18% | 37.08% | 22.87% | 27.91% | 54.35% | 2.7747 |
 
 
 
 
 
 
make_charts.py DELETED
@@ -1,104 +0,0 @@
1
- """Generate model-card charts from results_all_k.json (staging-only tool).
2
-
3
- Reads the AGGREGATE `blimp` key (top-level "blimp" -> "acc,none"), never the
4
- mean of the 67 blimp_* subtasks. Accuracy tasks use acc_norm,none
5
- (arc_easy/arc_challenge/hellaswag/piqa); byte-perplexity uses
6
- byte_perplexity,none. Effort colors are fixed across every chart.
7
- Also writes charts/benchmark_table.md (the source-of-truth table).
8
- """
9
- from __future__ import annotations
10
-
11
- import json
12
- from pathlib import Path
13
-
14
- import matplotlib
15
- matplotlib.use("Agg")
16
- # Real <text> elements (not glyph paths) so labels are inspectable in the SVG
17
- # and the model-card renders them as selectable text.
18
- matplotlib.rcParams["svg.fonttype"] = "none"
19
- import matplotlib.pyplot as plt
20
-
21
- HERE = Path(__file__).resolve().parent
22
- RESULTS = (HERE / ".." / ".." / "results" / "decay-p09" / "results_all_k.json").resolve()
23
- OUT = HERE / "charts"
24
-
25
- EFFORTS = ["2", "3", "4"]
26
- EFFORT_LABELS = ["min-spark-low", "min-spark-medium", "min-spark-high"]
27
- EFFORT_COLORS = {"2": "#4C72B0", "3": "#DD8452", "4": "#55A868"}
28
- ACC_TASKS = [
29
- ("BLiMP", "blimp", "acc,none"),
30
- ("ARC-Easy", "arc_easy", "acc_norm,none"),
31
- ("ARC-Challenge", "arc_challenge", "acc_norm,none"),
32
- ("HellaSwag", "hellaswag", "acc_norm,none"),
33
- ("PIQA", "piqa", "acc_norm,none"),
34
- ]
35
- KEY = "acc_norm,none"
36
-
37
-
38
- def load() -> dict:
39
- return json.loads(RESULTS.read_text())
40
-
41
-
42
- def make_accuracy(data: dict) -> None:
43
- fig, ax = plt.subplots(figsize=(9, 4.6))
44
- x = range(len(ACC_TASKS))
45
- width = 0.26
46
- for i, k in enumerate(EFFORTS):
47
- vals = [data[k][jkey][key] * 100 for _, jkey, key in ACC_TASKS]
48
- ax.bar([xi + (i - 1) * width for xi in x], vals, width,
49
- label=EFFORT_LABELS[i], color=EFFORT_COLORS[k])
50
- ax.set_ylabel("Accuracy (%)")
51
- ax.set_ylim(0, 100)
52
- ax.set_xticks(list(x))
53
- ax.set_xticklabels([t for t, _, _ in ACC_TASKS])
54
- ax.legend(frameon=False)
55
- ax.set_title("min-spark accuracy by effort")
56
- fig.tight_layout()
57
- fig.savefig(OUT / "accuracy.svg")
58
- plt.close(fig)
59
-
60
-
61
- def make_byteppl(data: dict) -> None:
62
- fig, ax = plt.subplots(figsize=(6, 4))
63
- vals = [data[k]["wikitext"]["byte_perplexity,none"] for k in EFFORTS]
64
- ax.bar(EFFORT_LABELS, vals, color=[EFFORT_COLORS[k] for k in EFFORTS])
65
- ax.set_ylabel("WikiText-2 byte perplexity (lower is better)")
66
- for i, v in enumerate(vals):
67
- ax.text(i, v + 0.01, f"{v:.4f}", ha="center")
68
- ax.set_title("min-spark byte perplexity by effort")
69
- fig.tight_layout()
70
- fig.savefig(OUT / "byteppl.svg")
71
- plt.close(fig)
72
-
73
-
74
- def make_table(data: dict) -> str:
75
- lines = [
76
- "| Effort | BLiMP | ARC-Easy | ARC-Challenge | HellaSwag | PIQA | WikiText-2 byte-ppl |",
77
- "|--------|-------|----------|---------------|-----------|------|---------------------|",
78
- ]
79
- for k in EFFORTS:
80
- e = data[k]
81
- row = (
82
- f"| {EFFORT_LABELS[int(k)-2]} "
83
- f"| {e['blimp']['acc,none']*100:.2f}% "
84
- f"| {e['arc_easy']['acc_norm,none']*100:.2f}% "
85
- f"| {e['arc_challenge']['acc_norm,none']*100:.2f}% "
86
- f"| {e['hellaswag']['acc_norm,none']*100:.2f}% "
87
- f"| {e['piqa']['acc_norm,none']*100:.2f}% "
88
- f"| {e['wikitext']['byte_perplexity,none']:.4f} |"
89
- )
90
- lines.append(row)
91
- return "\n".join(lines) + "\n"
92
-
93
-
94
- def main() -> None:
95
- OUT.mkdir(parents=True, exist_ok=True)
96
- data = load()
97
- make_accuracy(data)
98
- make_byteppl(data)
99
- (OUT / "benchmark_table.md").write_text(make_table(data))
100
- print(f"wrote {OUT/'accuracy.svg'}, {OUT/'byteppl.svg'}, {OUT/'benchmark_table.md'}")
101
-
102
-
103
- if __name__ == "__main__":
104
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/__init__.py DELETED
File without changes
tests/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (178 Bytes)
 
tests/__pycache__/conftest.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (659 Bytes)
 
tests/__pycache__/test_architecture.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (5.21 kB)
 
tests/__pycache__/test_charts.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (10.9 kB)
 
tests/__pycache__/test_config.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (14.8 kB)
 
tests/__pycache__/test_generate.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (15.3 kB)
 
tests/__pycache__/test_lmeval.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (10.6 kB)
 
tests/__pycache__/test_modeling.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (11.7 kB)
 
tests/__pycache__/test_pipeline.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (5.08 kB)
 
tests/__pycache__/test_provenance.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (7.73 kB)
 
tests/__pycache__/test_raw_path.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (3.16 kB)
 
tests/__pycache__/test_readme.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (15 kB)
 
tests/__pycache__/test_remote_code.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (9.73 kB)
 
tests/__pycache__/test_tokenizer.cpython-312-pytest-9.1.1.pyc DELETED
Binary file (15.2 kB)
 
tests/conftest.py DELETED
@@ -1,6 +0,0 @@
1
- import sys
2
- from pathlib import Path
3
-
4
- STAGING = Path(__file__).resolve().parents[1]
5
- if str(STAGING) not in sys.path:
6
- sys.path.insert(0, str(STAGING))
 
 
 
 
 
 
 
tests/test_architecture.py DELETED
@@ -1,19 +0,0 @@
1
- import xml.etree.ElementTree as ET
2
- from pathlib import Path
3
-
4
- STAGING = Path(__file__).resolve().parents[1]
5
-
6
-
7
- def test_architecture_svg_is_valid_and_complete():
8
- p = STAGING / "architecture.svg"
9
- tree = ET.parse(p)
10
- root = tree.getroot()
11
- text = ET.tostring(root, encoding="unicode")
12
- for label in ["embed", "prelude", "body", "loop", "coda", "unembed"]:
13
- assert label.lower() in text.lower(), label
14
-
15
-
16
- def test_viewer_note_records_verdict():
17
- note = (STAGING / "ARCHITECTURE-VIEWER.md").read_text()
18
- assert "native" in note.lower() or "viewer" in note.lower()
19
- assert "private" in note.lower()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_charts.py DELETED
@@ -1,35 +0,0 @@
1
- import json
2
- from pathlib import Path
3
-
4
- STAGING = Path(__file__).resolve().parents[1]
5
-
6
-
7
- def test_charts_generated():
8
- import subprocess, sys
9
- out = subprocess.run([sys.executable, str(STAGING / "make_charts.py")],
10
- capture_output=True, text=True, cwd=str(STAGING), timeout=120)
11
- assert out.returncode == 0, out.stderr[-1000:]
12
- assert (STAGING / "charts" / "accuracy.svg").exists()
13
- assert (STAGING / "charts" / "byteppl.svg").exists()
14
- assert (STAGING / "charts" / "benchmark_table.md").exists()
15
-
16
-
17
- def test_table_uses_aggregate_blimp_and_exact_keys():
18
- table = (STAGING / "charts" / "benchmark_table.md").read_text()
19
- # aggregate BLiMP values (NOT an average of the 67 subtasks)
20
- assert "67.11" in table and "69.19" in table
21
- # byte-perplexity values
22
- assert "2.8783" in table and "2.7747" in table
23
- # effort names, not K labels, in headings
24
- assert "min-spark-low" in table and "min-spark-medium" in table and "min-spark-high" in table
25
-
26
-
27
- def test_accuracy_chart_has_single_0_100_axis():
28
- import xml.etree.ElementTree as ET
29
- svg = (STAGING / "charts" / "accuracy.svg").read_text()
30
- root = ET.fromstring(svg)
31
- labels = [t.text for t in root.iter() if t.tag.endswith("text") and t.text]
32
- assert "Accuracy (%)" in labels
33
- # 0-100 axis: y-axis tick labels reach 100, not a 0-1 fraction axis
34
- assert any(lbl.strip() == "100" for lbl in labels)
35
- assert not any(lbl.strip().startswith("0.") for lbl in labels) # no 0.7x fractions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_config.py DELETED
@@ -1,40 +0,0 @@
1
- import json
2
- from pathlib import Path
3
-
4
- STAGING = Path(__file__).resolve().parents[1]
5
-
6
-
7
- def test_config_json_round_trips():
8
- from configuration_minspark import MinSparkConfig
9
- raw = json.loads((STAGING / "config.json").read_text())
10
- cfg = MinSparkConfig.from_dict(raw)
11
- assert cfg.vocab_size == 4096 and cfg.dim == 288 and cfg.max_loops == 4
12
- assert cfg.effort == "medium" and cfg.use_cache is False
13
- assert cfg.max_position_embeddings == 512
14
- back = json.loads(cfg.to_json_string())
15
- assert back["model_type"] == "minspark"
16
- assert back["doc_mask_eos"] == 2 and abs(back["ddl_k_eps"] - 0.01) < 1e-9
17
-
18
-
19
- def test_to_meiosis_preserves_training_fields():
20
- from configuration_minspark import MinSparkConfig
21
- from meiosis import MeiosisConfig
22
- cfg = MinSparkConfig.from_dict(json.loads((STAGING / "config.json").read_text()))
23
- m = cfg.to_meiosis()
24
- assert isinstance(m, MeiosisConfig)
25
- assert m.max_seq_len == 512 and m.doc_mask_eos == 2
26
- assert abs(m.ddl_k_eps - 1e-2) < 1e-9
27
- assert m.n_kv_heads == 2
28
-
29
-
30
- def test_max_position_embeddings_derived_from_max_seq_len():
31
- from configuration_minspark import MinSparkConfig
32
- cfg = MinSparkConfig()
33
- assert cfg.max_position_embeddings == cfg.max_seq_len == 512
34
- cfg2 = MinSparkConfig(max_seq_len=1024)
35
- assert cfg2.max_position_embeddings == 1024
36
-
37
-
38
- def test_effort_default_and_validation_source():
39
- from configuration_minspark import MinSparkConfig
40
- assert MinSparkConfig().effort == "medium"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_generate.py DELETED
@@ -1,101 +0,0 @@
1
- import torch
2
- import pytest
3
-
4
- STAGING = None
5
-
6
-
7
- @pytest.fixture(scope="module", autouse=True)
8
- def setup():
9
- global STAGING
10
- from pathlib import Path
11
- STAGING = Path(__file__).resolve().parents[1]
12
- return
13
-
14
-
15
- @pytest.fixture(scope="module")
16
- def model():
17
- from modeling_minspark import MinSparkForCausalLM
18
- import json
19
- from configuration_minspark import MinSparkConfig
20
- from safetensors.torch import load_file
21
- m = MinSparkForCausalLM(MinSparkConfig.from_dict(json.loads((STAGING / "config.json").read_text())))
22
- m.model.load_state_dict(load_file(str(STAGING / "model.safetensors")), strict=False)
23
- m.eval()
24
- return m
25
-
26
-
27
- def test_generate_shape_and_stop(model):
28
- ids = torch.tensor([[2, 3, 4, 5]])
29
- out = model.generate(ids, max_new_tokens=8, do_sample=False)
30
- assert out.ndim == 2 and out.shape[0] == 1
31
- # stops at eos or hits max_new; never exceeds input+8
32
- assert out.shape[1] <= ids.shape[1] + 8
33
-
34
-
35
- def test_generate_effort_passthrough(model):
36
- # Deterministic: effort="low" must reproduce the loops=2 run EXACTLY (and
37
- # high == loops=4). Equality, not inequality — greedy decoding is exact, and
38
- # an inequality check could flake when two loop counts coincide on a few
39
- # tokens or, worse, pass while effort is silently ignored.
40
- ids = torch.tensor([[2, 3, 4, 5]])
41
- with torch.no_grad():
42
- a = model.generate(ids, effort="low", max_new_tokens=4, do_sample=False)
43
- b = model.generate(ids, loops=2, max_new_tokens=4, do_sample=False)
44
- c = model.generate(ids, effort="high", max_new_tokens=4, do_sample=False)
45
- d = model.generate(ids, loops=4, max_new_tokens=4, do_sample=False)
46
- assert torch.equal(a, b)
47
- assert torch.equal(c, d)
48
-
49
-
50
- def test_generate_batched_raises(model):
51
- ids = torch.tensor([[2, 3, 4, 5], [2, 6, 7, 8]])
52
- with pytest.raises(ValueError, match="batched generation"):
53
- model.generate(ids, max_new_tokens=2)
54
-
55
-
56
- def test_generate_invalid_effort_raises(model):
57
- ids = torch.tensor([[2, 3, 4, 5]])
58
- with pytest.raises(ValueError):
59
- model.generate(ids, effort="turbo", max_new_tokens=2)
60
-
61
-
62
- def test_prepare_prepends_eos_then_truncates_to_last_512(model):
63
- # Short prompt: the EOS prefix survives.
64
- short = torch.tensor([[7, 8, 9]])
65
- prep = model.prepare_inputs_for_generation(short)
66
- assert prep["input_ids"].tolist() == [[2, 7, 8, 9]]
67
- # Long prompt: [EOS] + 600 tokens -> last 512 of the concatenation, so the
68
- # EOS drops off the front. Exact infer.py/loader.py parity (spec: "including
69
- # the >512 edge where EOS drops").
70
- long = torch.randint(0, 4096, (1, 600))
71
- prep = model.prepare_inputs_for_generation(long)
72
- ids = prep["input_ids"]
73
- assert ids.shape[1] == 512
74
- eos = torch.full((1, 1), 2, dtype=long.dtype)
75
- assert torch.equal(ids, torch.cat([eos, long], dim=1)[:, -512:])
76
-
77
-
78
- def test_prepare_keeps_attention_mask_in_sync(model):
79
- # generate may hand prepare a mask (tokenizer output in the quickstart, or
80
- # an auto-created all-ones mask); after the EOS prepend it must still match
81
- # input_ids in length, or forward's shape validation raises.
82
- ids = torch.tensor([[2, 3, 4, 5]])
83
- prep = model.prepare_inputs_for_generation(ids, attention_mask=torch.ones_like(ids))
84
- assert prep["attention_mask"].shape == prep["input_ids"].shape
85
- assert prep["attention_mask"].tolist() == [[1, 1, 1, 1, 1]]
86
-
87
-
88
- def test_generate_does_not_leak_machinery(model):
89
- # If prepare echoed cache_position/position_ids/use_cache, forward would
90
- # raise TypeError (it has no **kwargs). A clean generate is the proof.
91
- # Bounded, not exact, length: eos_token_id=2 may stop greedy decoding early.
92
- ids = torch.tensor([[2, 3, 4, 5]])
93
- out = model.generate(ids, max_new_tokens=3, do_sample=False)
94
- assert ids.shape[1] < out.shape[1] <= ids.shape[1] + 3
95
-
96
-
97
- def test_generation_config_matches_contract():
98
- import json
99
- gc = json.loads((STAGING / "generation_config.json").read_text())
100
- assert gc["eos_token_id"] == 2 and gc["pad_token_id"] == 0 and gc["bos_token_id"] == 1
101
- assert gc["use_cache"] is False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_lmeval.py DELETED
@@ -1,59 +0,0 @@
1
- import json
2
- import subprocess
3
- import sys
4
- from pathlib import Path
5
-
6
- import pytest
7
-
8
- STAGING = Path(__file__).resolve().parents[1]
9
- PY = Path(sys.executable)
10
-
11
- PUBLISHED = {
12
- "arc_easy": {"key": "acc_norm,none", "value": 0.3707912457912458},
13
- "wikitext": {"key": "byte_perplexity,none", "value": 2.7746719015990515},
14
- }
15
- TOL = {"acc_norm,none": 0.002, "byte_perplexity,none": 0.01}
16
-
17
-
18
- def test_run_lmeval_reproduces_arc_easy_k3():
19
- # --effort medium reproduces the K=3 published value (K=3/K=4 happen to be
20
- # bit-identical for arc_easy, so --effort high would pass by coincidence).
21
- out = subprocess.run(
22
- [str(PY), str(STAGING / "run_lmeval.py"), "--effort", "medium", "--tasks", "arc_easy", "--json"],
23
- capture_output=True, text=True, cwd=str(STAGING), timeout=2400,
24
- )
25
- assert out.returncode == 0, out.stderr[-2000:]
26
- # --json prints results["results"] (task -> metrics), not the full envelope
27
- res = json.loads(out.stdout)["arc_easy"]
28
- assert abs(res["acc_norm,none"] - PUBLISHED["arc_easy"]["value"]) <= TOL["acc_norm,none"]
29
-
30
-
31
- def test_run_lmeval_reproduces_wikitext_byteppl_k3():
32
- out = subprocess.run(
33
- [str(PY), str(STAGING / "run_lmeval.py"), "--effort", "medium", "--tasks", "wikitext", "--json"],
34
- capture_output=True, text=True, cwd=str(STAGING), timeout=2400,
35
- )
36
- assert out.returncode == 0, out.stderr[-2000:]
37
- res = json.loads(out.stdout)["wikitext"]
38
- assert abs(res["byte_perplexity,none"] - PUBLISHED["wikitext"]["value"]) <= TOL["byte_perplexity,none"]
39
-
40
-
41
- def test_minspark_lm_instantiates():
42
- # Catches the LM-vs-TemplateLM abstract-property mistake at construction
43
- # time, before any scoring runs.
44
- from run_lmeval import MinSparkLM
45
- lm = MinSparkLM("medium")
46
- assert lm.eot_token_id == 2 and lm.max_length == 512
47
-
48
-
49
- def test_stock_hflm_smoke_and_deltas():
50
- # Stock --model hf must run a long-context task without crashing (R3), and
51
- # record per-task deltas vs the SAME-subset run_lmeval value into deltas.json.
52
- out = subprocess.run(
53
- [str(PY), str(STAGING / "record_deltas.py"), "--tasks", "arc_easy,wikitext", "--limit", "200"],
54
- capture_output=True, text=True, cwd=str(STAGING), timeout=2400,
55
- )
56
- assert out.returncode == 0, out.stderr[-2000:]
57
- deltas = json.loads((STAGING / "deltas.json").read_text())
58
- assert "arc_easy" in deltas and "wikitext" in deltas
59
- assert "delta" in deltas["arc_easy"] and "delta" in deltas["wikitext"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_modeling.py DELETED
@@ -1,115 +0,0 @@
1
- import torch
2
- import pytest
3
-
4
- STAGING = None # set in fixture
5
-
6
-
7
- @pytest.fixture(scope="module", autouse=True)
8
- def setup():
9
- global STAGING
10
- from pathlib import Path
11
- STAGING = Path(__file__).resolve().parents[1]
12
- return
13
-
14
-
15
- def load_raw():
16
- from safetensors.torch import load_file
17
- from meiosis import Meiosis, MeiosisConfig
18
- model = Meiosis(MeiosisConfig())
19
- model.load_state_dict(load_file(str(STAGING / "model.safetensors")), strict=False)
20
- model.eval()
21
- return model
22
-
23
-
24
- def load_wrapper():
25
- from modeling_minspark import MinSparkForCausalLM
26
- from configuration_minspark import MinSparkConfig
27
- import json
28
- model = MinSparkForCausalLM(MinSparkConfig.from_dict(json.loads((STAGING / "config.json").read_text())))
29
- from safetensors.torch import load_file
30
- model.model.load_state_dict(load_file(str(STAGING / "model.safetensors")), strict=False)
31
- model.eval()
32
- return model
33
-
34
-
35
- @pytest.fixture(scope="module")
36
- def tokens():
37
- from tokenizers import Tokenizer
38
- tok = Tokenizer.from_file(str(STAGING / "tokenizer.json"))
39
- ids = [2] + tok.encode("The quick brown fox jumps over the lazy dog.").ids
40
- return torch.tensor([ids])
41
-
42
-
43
- def test_logits_parity_all_efforts(tokens):
44
- raw, wrap = load_raw(), load_wrapper()
45
- for loops in (2, 3, 4):
46
- with torch.no_grad():
47
- a = raw(tokens, loops=loops)
48
- b = wrap(tokens, loops=loops).logits
49
- assert torch.allclose(a, b, atol=1e-6), loops
50
-
51
-
52
- def test_effort_maps_to_loops(tokens):
53
- wrap = load_wrapper()
54
- with torch.no_grad():
55
- low = wrap(tokens, effort="low").logits
56
- med = wrap(tokens, effort="medium").logits
57
- assert not torch.allclose(low, med)
58
-
59
-
60
- def test_invalid_effort_and_loops_raise(tokens):
61
- wrap = load_wrapper()
62
- with pytest.raises(ValueError):
63
- wrap(tokens, effort="turbo")
64
- with pytest.raises(ValueError):
65
- wrap(tokens, loops=0)
66
- with pytest.raises(ValueError):
67
- wrap(tokens, loops=5) # > max_loops
68
-
69
-
70
- def test_use_cache_raises(tokens):
71
- wrap = load_wrapper()
72
- with pytest.raises(NotImplementedError, match="KV cache"):
73
- wrap(tokens, use_cache=True)
74
- with pytest.raises(NotImplementedError, match="KV cache"):
75
- wrap(tokens, past_key_values=("x",))
76
-
77
-
78
- def test_labels_loss_matches_shifted_ce(tokens):
79
- wrap = load_wrapper()
80
- labels = torch.randint(0, 4096, tokens.shape)
81
- out = wrap(tokens, labels=labels)
82
- import torch.nn.functional as F
83
- logits = wrap(tokens).logits
84
- shift_logits = logits[:, :-1, :].contiguous()
85
- shift_labels = labels[:, 1:].contiguous()
86
- expected = F.cross_entropy(shift_logits.view(-1, 4096), shift_labels.view(-1), ignore_index=-100)
87
- assert torch.allclose(out.loss, expected, atol=1e-6)
88
-
89
-
90
- def test_padding_guards(tokens):
91
- wrap = load_wrapper()
92
- b = torch.tensor([[2, 5, 6, 0], [2, 5, 6, 7]]) # left pad
93
- with pytest.raises(ValueError, match="left-padded"):
94
- wrap(b, attention_mask=torch.tensor([[0, 1, 1, 1], [1, 1, 1, 1]]))
95
- interior = torch.tensor([[2, 5, 6, 7]])
96
- with pytest.raises(ValueError, match="suffix"):
97
- wrap(interior, attention_mask=torch.tensor([[1, 1, 0, 1]]))
98
-
99
-
100
- def test_right_padded_scoring_matches_unbatched(tokens):
101
- # Real right-padding: a PAD TOKEN (id 0) sits in position 3. The guard must
102
- # pass it, and logits at the REAL positions must equal the unpadded forward.
103
- # Tolerance is atol=1e-4, not 1e-6: cross-length comparison (4 vs 3 columns)
104
- # changes SDPA's softmax reduction order, producing ~2.6e-5 fp noise even with
105
- # the doc-mask OFF (measured). A pad-token LEAK would be O(1) in the logits —
106
- # same-length pad-vs-nonpad token comparison is bit-exact (0.0), proving the
107
- # mask/causal logic is correct and the residual diff is shape noise.
108
- wrap = load_wrapper()
109
- padded = torch.tensor([[2, 5, 6, 0]]) # token 0 = <pad> in the tail
110
- mask = torch.tensor([[1, 1, 1, 0]])
111
- unpadded = torch.tensor([[2, 5, 6]])
112
- with torch.no_grad():
113
- a = wrap(padded, attention_mask=mask).logits # real positions 0..2
114
- b = wrap(unpadded).logits # unpadded reference, 3 tokens
115
- assert torch.allclose(a[:, :3], b[:, :3], atol=1e-4)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_pipeline.py DELETED
@@ -1,34 +0,0 @@
1
- import pytest
2
-
3
- STAGING = None
4
-
5
-
6
- @pytest.fixture(scope="module", autouse=True)
7
- def setup():
8
- global STAGING
9
- from pathlib import Path
10
- STAGING = Path(__file__).resolve().parents[1]
11
- return
12
-
13
-
14
- @pytest.fixture(scope="module")
15
- def pipe():
16
- from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
17
- model = AutoModelForCausalLM.from_pretrained(str(STAGING), trust_remote_code=True)
18
- tok = AutoTokenizer.from_pretrained(str(STAGING), trust_remote_code=True)
19
- return pipeline("text-generation", model=model, tokenizer=tok)
20
-
21
-
22
- def test_pipeline_generates_text(pipe):
23
- out = pipe("Hello,", max_new_tokens=6, do_sample=False)
24
- assert isinstance(out, list) and len(out) == 1
25
- assert out[0]["generated_text"].strip()
26
-
27
-
28
- def test_pipeline_effort_passthrough(pipe):
29
- # Equality-based: effort="low" must reproduce the loops=2 run exactly. An
30
- # inequality check could pass while effort is silently ignored, or flake
31
- # when two loop counts coincide on a few greedy tokens.
32
- a = pipe("The cat", effort="low", max_new_tokens=4, do_sample=False)[0]["generated_text"]
33
- b = pipe("The cat", loops=2, max_new_tokens=4, do_sample=False)[0]["generated_text"]
34
- assert a == b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_provenance.py DELETED
@@ -1,38 +0,0 @@
1
- import hashlib
2
- from pathlib import Path
3
-
4
- import pytest
5
- import torch
6
-
7
- STAGING = Path(__file__).resolve().parents[1]
8
- EXPECT = {
9
- "meiosis.py": "81aeb026c7ea1b7e8a7961e74c81441706b0ff5a00bd49c02099a1ff28b963c3",
10
- "tokenizer.json": "d671f013ebdb06a55e48d047f12621c3311310fdcc344683d434d294a909ac51",
11
- "model.safetensors": "a121c6a316e54e490918d93d3d265460d45addbdad49b8448c514e5f61232c41",
12
- }
13
-
14
-
15
- def sha256(p: Path) -> str:
16
- return hashlib.sha256(p.read_bytes()).hexdigest()
17
-
18
-
19
- def test_artifact_shas_match_sources():
20
- for name, expected in EXPECT.items():
21
- assert sha256(STAGING / name) == expected, name
22
-
23
-
24
- def test_safetensors_is_raw_meiosis_state():
25
- from safetensors.torch import load_file
26
- state = load_file(str(STAGING / "model.safetensors"))
27
- assert len(state) == 81
28
- assert not any(k.startswith("model.") for k in state)
29
- assert not any("embed_tokens" in k or "lm_head" in k for k in state)
30
- assert not any(k.endswith(("rope_cos", "rope_sin", "last_loop_rms")) for k in state)
31
-
32
-
33
- def test_vendored_meiosis_loads_with_strict_false():
34
- from meiosis import Meiosis, MeiosisConfig
35
- from safetensors.torch import load_file
36
- model = Meiosis(MeiosisConfig())
37
- model.load_state_dict(load_file(str(STAGING / "model.safetensors")), strict=False)
38
- assert sum(p.numel() for p in model.parameters()) == 5_758_572
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_raw_path.py DELETED
@@ -1,31 +0,0 @@
1
- import sys
2
- from pathlib import Path
3
-
4
- import torch
5
-
6
- REPO = Path(__file__).resolve().parents[5] # PICO/ (parents[4] is models/)
7
- STAGING = Path(__file__).resolve().parents[1]
8
-
9
-
10
- def test_generate_py_matches_space_loader_under_fixed_seed():
11
- sys.path.insert(0, str(STAGING))
12
- from generate import generate as staged_gen, load_model as staged_load
13
- from tokenizers import Tokenizer
14
-
15
- # Space loader (imports its own vendored meiosis from assets)
16
- sys.path.insert(0, str(REPO / "spaces" / "min-spark-preview"))
17
- sys.path.insert(0, str(REPO / "spaces" / "min-spark-preview" / "assets"))
18
- from loader import generate as space_gen
19
- from loader import load_model as space_load
20
-
21
- tok = Tokenizer.from_file(str(STAGING / "tokenizer.json"))
22
- prompt = "The meaning of life is"
23
- kw = dict(loops=3, max_new=20, temperature=0.8, top_k=50, device="cpu")
24
-
25
- torch.manual_seed(42)
26
- out_a = "".join(staged_gen(staged_load(str(STAGING / "model.safetensors"), "cpu"),
27
- tok, prompt, **kw))
28
- torch.manual_seed(42)
29
- out_b = "".join(c for c, _n, _t in space_gen(space_load("cpu"), tok, prompt, **kw))
30
-
31
- assert out_a == out_b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_readme.py DELETED
@@ -1,69 +0,0 @@
1
- import json
2
- from pathlib import Path
3
-
4
- STAGING = Path(__file__).resolve().parents[1]
5
-
6
-
7
- def test_frontmatter_present():
8
- text = (STAGING / "README.md").read_text()
9
- assert "license: apache-2.0" in text
10
- assert "pipeline_tag: text-generation" in text
11
- assert "library_name: transformers" in text
12
- assert "custom_code" in text
13
-
14
-
15
- def test_benchmark_table_values_match_json():
16
- table = (STAGING / "charts" / "benchmark_table.md").read_text()
17
- # results_all_k.json lives at models/2026-07-meiosis/results/decay-p09/
18
- results = Path(__file__).resolve().parents[3] / "results" / "decay-p09" / "results_all_k.json"
19
- data = json.loads(results.read_text())
20
- for k in ("2", "3", "4"):
21
- assert f"{data[k]['blimp']['acc,none']*100:.2f}%" in table
22
- assert f"{data[k]['wikitext']['byte_perplexity,none']:.4f}" in table
23
-
24
-
25
- def test_readme_body_inlines_table_no_placeholders():
26
- readme = (STAGING / "README.md").read_text()
27
- table = (STAGING / "charts" / "benchmark_table.md").read_text()
28
- # No unresolved {embed}/{replace} scaffolding leaks into the card.
29
- # (Precise markers only — a bare "{" would be false-positive on any
30
- # legitimate code snippet with braces, e.g. {"key": ...}.)
31
- assert "{embed" not in readme and "replace with:" not in readme
32
- # The table content is actually inline (real rows, real values).
33
- for line in table.strip().splitlines():
34
- if line.startswith("|"):
35
- assert line in readme, f"README is missing table row: {line}"
36
-
37
-
38
- def test_no_k_in_user_facing_benchmark_copy():
39
- text = (STAGING / "README.md").read_text()
40
- # effort names everywhere user-facing
41
- assert "min-spark-low" in text and "min-spark-high" in text
42
- # K loop-counts may appear ONLY in the technical note section.
43
- # Gate the ENTIRE card minus the technical note block — including sections
44
- # AFTER it (Provenance, License) which a "everything before technical note"
45
- # check would miss.
46
- tech = text.split("## Technical note")[1].split("## ")[0]
47
- non_tech = text.replace("## Technical note" + tech, "")
48
- # non_tech is the whole card with the technical note body removed
49
- assert "K=" not in non_tech
50
- assert ("K=" in tech) or ("loop" in tech.lower())
51
-
52
-
53
- def test_provenance_and_single_sequence_notes():
54
- text = (STAGING / "README.md").read_text()
55
- assert "meiosis-decay-p09" in text
56
- assert "a121c6a316e54e490918d93d3d265460d45addbdad49b8448c514e5f61232c41" in text
57
- assert "single-sequence" in text
58
-
59
-
60
- def test_license_is_apache_2():
61
- lic = (STAGING / "LICENSE").read_text()
62
- assert "Apache License" in lic and "Version 2.0" in lic
63
-
64
-
65
- def test_requirements_floor_match_installed():
66
- reqs = (STAGING / "requirements.txt").read_text()
67
- import transformers, tokenizers
68
- assert f"transformers>={'.'.join(transformers.__version__.split('.')[:2])}" in reqs
69
- assert f"tokenizers>={tokenizers.__version__.split('.')[0]}" in reqs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_remote_code.py DELETED
@@ -1,70 +0,0 @@
1
- import logging
2
- import shutil
3
- import tempfile
4
- import warnings
5
- from pathlib import Path
6
-
7
- import torch
8
- import pytest
9
-
10
- STAGING = Path(__file__).resolve().parents[1]
11
- # Mirrors the Hub-upload exclude set (UPLOAD.md), plus charts/deltas which are
12
- # unneeded for the load test and keep the temp snapshot small.
13
- _EXCLUDE = {"tests", "__pycache__", "make_charts.py", "benchmark_table.md",
14
- "deltas.json", "charts", "UPLOAD.md", "ARCHITECTURE-VIEWER.md"}
15
-
16
-
17
- @pytest.fixture(scope="module")
18
- def snapshot():
19
- with tempfile.TemporaryDirectory() as td:
20
- dst = Path(td)
21
- for item in STAGING.iterdir():
22
- if item.name in _EXCLUDE:
23
- continue
24
- shutil.copytree(item, dst / item.name) if item.is_dir() else shutil.copy2(item, dst / item.name)
25
- yield dst
26
-
27
-
28
- def load_snapshot(snapshot):
29
- from transformers import AutoModelForCausalLM, AutoTokenizer
30
- with warnings.catch_warnings(record=True) as caught:
31
- warnings.simplefilter("always")
32
- tok = AutoTokenizer.from_pretrained(str(snapshot), trust_remote_code=True)
33
- model = AutoModelForCausalLM.from_pretrained(str(snapshot), trust_remote_code=True)
34
- model.eval()
35
- return tok, model, caught
36
-
37
-
38
- def test_remote_code_loads_clean(snapshot):
39
- tok, model, caught = load_snapshot(snapshot)
40
- # No phantom keys, no dropped params: transformers warns on both.
41
- bad = [str(w.message) for w in caught if "were not used" in str(w.message) or "not initialized" in str(w.message)]
42
- assert bad == [], bad
43
- # Weights actually loaded (not zero/random-init)
44
- assert model.model.embed.weight.abs().sum().item() > 1e-6
45
-
46
-
47
- def test_remote_code_logits_match_raw(snapshot):
48
- from tokenizers import Tokenizer
49
- from safetensors.torch import load_file
50
- from meiosis import Meiosis, MeiosisConfig
51
- tok, model, _ = load_snapshot(snapshot)
52
-
53
- raw = Meiosis(MeiosisConfig())
54
- raw.load_state_dict(load_file(str(STAGING / "model.safetensors")), strict=False)
55
- raw.eval()
56
-
57
- ids = torch.tensor([[2] + tok.encode("The quick brown fox jumps over the lazy dog.")])
58
- with torch.no_grad():
59
- a = raw(ids, loops=3)
60
- b = model(ids, effort="medium").logits
61
- assert torch.allclose(a, b, atol=1e-6)
62
-
63
-
64
- def test_remote_code_tokenizer_matches_raw(snapshot):
65
- from tokenizers import Tokenizer
66
- from transformers import AutoTokenizer
67
- tok = AutoTokenizer.from_pretrained(str(snapshot), trust_remote_code=True)
68
- raw = Tokenizer.from_file(str(STAGING / "tokenizer.json"))
69
- for text in ["hello world", "Ünïcode 你好 123", " spaced "]:
70
- assert tok.encode(text) == raw.encode(text).ids
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_tokenizer.py DELETED
@@ -1,60 +0,0 @@
1
- import json
2
- from pathlib import Path
3
-
4
- import pytest
5
-
6
- STAGING = Path(__file__).resolve().parents[1]
7
-
8
- BATTERY = [
9
- "",
10
- "hello world",
11
- "The meaning of life is 42.",
12
- "Ünïcode 你好, mixed 12345",
13
- " leading and trailing spaces ",
14
- "a\tb\nc",
15
- "x" * 700, # longer than max_seq_len; encode must still work
16
- ]
17
-
18
- RAW_TOK = None
19
- HF_TOK = None
20
-
21
-
22
- @pytest.fixture(scope="module", autouse=True)
23
- def loaders():
24
- global RAW_TOK, HF_TOK
25
- from tokenizers import Tokenizer
26
- from transformers import AutoTokenizer
27
- RAW_TOK = Tokenizer.from_file(str(STAGING / "tokenizer.json"))
28
- # trust_remote_code=True: config.json's auto_map marks the repo as custom
29
- # code; the tokenizer is stock but without this the interactive prompt
30
- # fires (and pollutes captured stdout in subprocess tests).
31
- HF_TOK = AutoTokenizer.from_pretrained(str(STAGING), trust_remote_code=True)
32
- return
33
-
34
-
35
- def test_specials_and_model_max_length():
36
- tc = json.loads((STAGING / "tokenizer_config.json").read_text())
37
- assert tc["pad_token"] == "<pad>" and tc["bos_token"] == "<bos>" and tc["eos_token"] == "<eos>"
38
- assert tc["add_bos_token"] is False and tc["add_eos_token"] is False
39
- assert tc["model_max_length"] == 512
40
- assert HF_TOK.pad_token_id == 0 and HF_TOK.bos_token_id == 1 and HF_TOK.eos_token_id == 2
41
- assert HF_TOK.model_max_length == 512
42
-
43
-
44
- def test_encode_ids_match_raw_tokenizer():
45
- for text in BATTERY:
46
- assert HF_TOK.encode(text) == RAW_TOK.encode(text).ids, repr(text)
47
-
48
-
49
- def test_decode_round_trips_byte_level():
50
- for text in BATTERY:
51
- if not text:
52
- continue
53
- ids = RAW_TOK.encode(text).ids
54
- assert HF_TOK.decode(ids) == RAW_TOK.decode(ids), repr(text)
55
-
56
-
57
- def test_no_auto_added_specials():
58
- # A bare encode must not inject <bos>/<eos> (matches training/eval).
59
- assert HF_TOK.encode("hi") == RAW_TOK.encode("hi").ids
60
- assert HF_TOK.encode("hi", add_special_tokens=False) == HF_TOK.encode("hi")