quantik-models 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. quantik_models-1.0.0/AGENTS.md +46 -0
  2. quantik_models-1.0.0/CHANGELOG.md +107 -0
  3. quantik_models-1.0.0/LICENSE +21 -0
  4. quantik_models-1.0.0/MANIFEST.in +26 -0
  5. quantik_models-1.0.0/PKG-INFO +294 -0
  6. quantik_models-1.0.0/README.md +242 -0
  7. quantik_models-1.0.0/pyproject.toml +156 -0
  8. quantik_models-1.0.0/setup.cfg +4 -0
  9. quantik_models-1.0.0/src/quantik_models/__init__.py +12 -0
  10. quantik_models-1.0.0/src/quantik_models/arena/__init__.py +25 -0
  11. quantik_models-1.0.0/src/quantik_models/arena/agents.py +305 -0
  12. quantik_models-1.0.0/src/quantik_models/arena/autoplay.py +379 -0
  13. quantik_models-1.0.0/src/quantik_models/arena/match.py +232 -0
  14. quantik_models-1.0.0/src/quantik_models/arena/pack.py +406 -0
  15. quantik_models-1.0.0/src/quantik_models/arena/parallel.py +97 -0
  16. quantik_models-1.0.0/src/quantik_models/arena/probe.py +149 -0
  17. quantik_models-1.0.0/src/quantik_models/arena/registry.py +213 -0
  18. quantik_models-1.0.0/src/quantik_models/data/__init__.py +5 -0
  19. quantik_models-1.0.0/src/quantik_models/data/dataset.py +171 -0
  20. quantik_models-1.0.0/src/quantik_models/data/exact_corpus.py +153 -0
  21. quantik_models-1.0.0/src/quantik_models/data/labels.py +44 -0
  22. quantik_models-1.0.0/src/quantik_models/data/materialize.py +242 -0
  23. quantik_models-1.0.0/src/quantik_models/data/merge_corpus.py +158 -0
  24. quantik_models-1.0.0/src/quantik_models/env/__init__.py +21 -0
  25. quantik_models-1.0.0/src/quantik_models/env/fastboard.py +414 -0
  26. quantik_models-1.0.0/src/quantik_models/eval/__init__.py +1 -0
  27. quantik_models-1.0.0/src/quantik_models/eval/shift.py +379 -0
  28. quantik_models-1.0.0/src/quantik_models/export/__init__.py +1 -0
  29. quantik_models-1.0.0/src/quantik_models/export/cards.py +113 -0
  30. quantik_models-1.0.0/src/quantik_models/export/checkpoint.py +205 -0
  31. quantik_models-1.0.0/src/quantik_models/export/devdata.py +571 -0
  32. quantik_models-1.0.0/src/quantik_models/export/digest.py +22 -0
  33. quantik_models-1.0.0/src/quantik_models/export/huggingface.py +923 -0
  34. quantik_models-1.0.0/src/quantik_models/hub.py +526 -0
  35. quantik_models-1.0.0/src/quantik_models/model/__init__.py +1 -0
  36. quantik_models-1.0.0/src/quantik_models/model/attention_net.py +147 -0
  37. quantik_models-1.0.0/src/quantik_models/model/constraint_pool_net.py +220 -0
  38. quantik_models-1.0.0/src/quantik_models/model/mlp_net.py +107 -0
  39. quantik_models-1.0.0/src/quantik_models/model/policy_value_net.py +114 -0
  40. quantik_models-1.0.0/src/quantik_models/model/registry.py +191 -0
  41. quantik_models-1.0.0/src/quantik_models/model/spec.py +68 -0
  42. quantik_models-1.0.0/src/quantik_models/model_spec.py +9 -0
  43. quantik_models-1.0.0/src/quantik_models/play/__init__.py +32 -0
  44. quantik_models-1.0.0/src/quantik_models/play/__main__.py +132 -0
  45. quantik_models-1.0.0/src/quantik_models/play/export.py +128 -0
  46. quantik_models-1.0.0/src/quantik_models/play/opponents.py +216 -0
  47. quantik_models-1.0.0/src/quantik_models/play/puzzles.py +275 -0
  48. quantik_models-1.0.0/src/quantik_models/play/record.py +244 -0
  49. quantik_models-1.0.0/src/quantik_models/play/registry.py +187 -0
  50. quantik_models-1.0.0/src/quantik_models/play/server.py +311 -0
  51. quantik_models-1.0.0/src/quantik_models/play/service.py +479 -0
  52. quantik_models-1.0.0/src/quantik_models/play/store.py +348 -0
  53. quantik_models-1.0.0/src/quantik_models/py.typed +0 -0
  54. quantik_models-1.0.0/src/quantik_models/report/__init__.py +1 -0
  55. quantik_models-1.0.0/src/quantik_models/report/build_figures.py +144 -0
  56. quantik_models-1.0.0/src/quantik_models/report/figures.py +419 -0
  57. quantik_models-1.0.0/src/quantik_models/selfplay/__init__.py +12 -0
  58. quantik_models-1.0.0/src/quantik_models/selfplay/duel.py +90 -0
  59. quantik_models-1.0.0/src/quantik_models/selfplay/evaluator.py +125 -0
  60. quantik_models-1.0.0/src/quantik_models/selfplay/generate.py +155 -0
  61. quantik_models-1.0.0/src/quantik_models/selfplay/mcts.py +330 -0
  62. quantik_models-1.0.0/src/quantik_models/train/__init__.py +1 -0
  63. quantik_models-1.0.0/src/quantik_models/train/alphazero.py +330 -0
  64. quantik_models-1.0.0/src/quantik_models/train/convergence.py +25 -0
  65. quantik_models-1.0.0/src/quantik_models/train/freezing.py +131 -0
  66. quantik_models-1.0.0/src/quantik_models/train/metrics.py +25 -0
  67. quantik_models-1.0.0/src/quantik_models/train/preflight.py +345 -0
  68. quantik_models-1.0.0/src/quantik_models/train/provenance.py +172 -0
  69. quantik_models-1.0.0/src/quantik_models/train/supervised.py +437 -0
  70. quantik_models-1.0.0/src/quantik_models/train/trainer.py +304 -0
  71. quantik_models-1.0.0/src/quantik_models.egg-info/PKG-INFO +294 -0
  72. quantik_models-1.0.0/src/quantik_models.egg-info/SOURCES.txt +127 -0
  73. quantik_models-1.0.0/src/quantik_models.egg-info/dependency_links.txt +1 -0
  74. quantik_models-1.0.0/src/quantik_models.egg-info/entry_points.txt +7 -0
  75. quantik_models-1.0.0/src/quantik_models.egg-info/requires.txt +32 -0
  76. quantik_models-1.0.0/src/quantik_models.egg-info/top_level.txt +1 -0
  77. quantik_models-1.0.0/tests/boards.py +41 -0
  78. quantik_models-1.0.0/tests/fixtures/checkpoints/smoke-best/manifest.json +21 -0
  79. quantik_models-1.0.0/tests/fixtures/checkpoints/smoke-best/training-report.json +22 -0
  80. quantik_models-1.0.0/tests/fixtures/checkpoints/smoke-best/weights.safetensors +0 -0
  81. quantik_models-1.0.0/tests/fixtures/puzzle-corpus.json +425 -0
  82. quantik_models-1.0.0/tests/test_action_layout.py +56 -0
  83. quantik_models-1.0.0/tests/test_agent_temperature.py +187 -0
  84. quantik_models-1.0.0/tests/test_architecture_registry.py +160 -0
  85. quantik_models-1.0.0/tests/test_arena.py +171 -0
  86. quantik_models-1.0.0/tests/test_arena_pack.py +342 -0
  87. quantik_models-1.0.0/tests/test_autoplay.py +171 -0
  88. quantik_models-1.0.0/tests/test_batched_mcts.py +226 -0
  89. quantik_models-1.0.0/tests/test_checkpoint_fixture.py +45 -0
  90. quantik_models-1.0.0/tests/test_checkpoint_roundtrip.py +87 -0
  91. quantik_models-1.0.0/tests/test_constraint_groups.py +60 -0
  92. quantik_models-1.0.0/tests/test_convergence_budget.py +144 -0
  93. quantik_models-1.0.0/tests/test_dataset.py +78 -0
  94. quantik_models-1.0.0/tests/test_devdata_staging.py +159 -0
  95. quantik_models-1.0.0/tests/test_docs_crossrefs.py +171 -0
  96. quantik_models-1.0.0/tests/test_documented_snippets.py +121 -0
  97. quantik_models-1.0.0/tests/test_export_checkpoint.py +89 -0
  98. quantik_models-1.0.0/tests/test_fastboard.py +251 -0
  99. quantik_models-1.0.0/tests/test_finetune_cli.py +100 -0
  100. quantik_models-1.0.0/tests/test_freezing.py +127 -0
  101. quantik_models-1.0.0/tests/test_hub.py +513 -0
  102. quantik_models-1.0.0/tests/test_huggingface_export.py +336 -0
  103. quantik_models-1.0.0/tests/test_learning_rate_resolution.py +142 -0
  104. quantik_models-1.0.0/tests/test_materialize.py +108 -0
  105. quantik_models-1.0.0/tests/test_merge_corpus.py +124 -0
  106. quantik_models-1.0.0/tests/test_occupancy_split.py +115 -0
  107. quantik_models-1.0.0/tests/test_onnx_evaluator_agreement.py +114 -0
  108. quantik_models-1.0.0/tests/test_oracle_corpus.py +144 -0
  109. quantik_models-1.0.0/tests/test_packaging.py +148 -0
  110. quantik_models-1.0.0/tests/test_parameter_matching.py +59 -0
  111. quantik_models-1.0.0/tests/test_play_analysis.py +146 -0
  112. quantik_models-1.0.0/tests/test_play_export.py +176 -0
  113. quantik_models-1.0.0/tests/test_play_puzzles.py +144 -0
  114. quantik_models-1.0.0/tests/test_play_record.py +216 -0
  115. quantik_models-1.0.0/tests/test_play_registry.py +217 -0
  116. quantik_models-1.0.0/tests/test_play_server.py +308 -0
  117. quantik_models-1.0.0/tests/test_play_service.py +275 -0
  118. quantik_models-1.0.0/tests/test_play_store.py +283 -0
  119. quantik_models-1.0.0/tests/test_policy_value_net.py +58 -0
  120. quantik_models-1.0.0/tests/test_preflight.py +121 -0
  121. quantik_models-1.0.0/tests/test_probe.py +108 -0
  122. quantik_models-1.0.0/tests/test_report_figures.py +304 -0
  123. quantik_models-1.0.0/tests/test_selfplay.py +197 -0
  124. quantik_models-1.0.0/tests/test_shift_evaluation.py +159 -0
  125. quantik_models-1.0.0/tests/test_solve_opening.py +105 -0
  126. quantik_models-1.0.0/tests/test_split_leakage.py +119 -0
  127. quantik_models-1.0.0/tests/test_trainer.py +100 -0
  128. quantik_models-1.0.0/tests/test_training_provenance.py +147 -0
  129. quantik_models-1.0.0/tests/test_uniform_mcts_control.py +53 -0
@@ -0,0 +1,46 @@
1
+ # AGENTS.md
2
+
3
+ Instructions for humans and AI agents working in this repository.
4
+
5
+ ## Read these first, in this order
6
+
7
+ | | |
8
+ |---|---|
9
+ | [`README.md`](README.md) | what the package is and how it is used |
10
+ | [`DEVELOPMENT.md`](DEVELOPMENT.md) | **environment, tests, CI, the release process, and the non-negotiable invariants.** Everything about working on this repository is there. |
11
+ | [`docs/README.md`](docs/README.md) | the reading order for `docs/` |
12
+
13
+ **Do not grep your way in.** This repository's hard-won conclusions are
14
+ written down, and most of them are not derivable from the code — several are
15
+ about measurements that turned out to be wrong. `DEVELOPMENT.md`'s
16
+ "Invariants that are not negotiable" is the shortest path to not repeating
17
+ one.
18
+
19
+ ## What is specific to working here as an agent
20
+
21
+ **Verify before anything expensive.** Training runs and arenas cost hours,
22
+ and this repository has paid more than once for skipping the smoke test.
23
+ `DEVELOPMENT.md` has the rules; the shortest version is that a timing taken
24
+ under load is an upper bound, often a wild one, and an average from a
25
+ differently-shaped workload does not transfer.
26
+
27
+ **Say what you actually ran.** `mypy` is a gate now, but claiming a check
28
+ passed without running it has happened here. So has drawing a 16-epoch
29
+ conclusion from one epoch of evidence, and publishing a plausible, detailed,
30
+ statistically significant story that was entirely an artifact of a
31
+ hyperparameter inherited from another architecture.
32
+
33
+ **When you recommend something, write down what you rejected.** Both
34
+ architecture decision records in `docs/decisions/` are structured that way,
35
+ and the rejected options are the part that has aged best.
36
+
37
+ **A measurement disagreeing with an earlier one is the interesting case.**
38
+ Do not split the difference. Held-out accuracy has failed to predict play
39
+ strength four separate times; when it disagrees with the arena, say so.
40
+
41
+ ## Where work is tracked
42
+
43
+ `quantik-workspace` is the control plane and the source of truth for what
44
+ work exists — initiatives under `tasks/active/QW-NNN/`, repository packets
45
+ under `context/repositories/`, decisions under `docs/adr/`. It is a sibling
46
+ checkout, not part of this repository.
@@ -0,0 +1,107 @@
1
+ # Changelog
2
+
3
+ All notable changes to `quantik-models` are documented here.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+ What counts as a breaking change here is written down in
8
+ [`docs/decisions/0002-versioning-and-release.md`](docs/decisions/0002-versioning-and-release.md).
9
+
10
+ ## Unreleased
11
+
12
+ ## 1.0.0 - 2026-09-05
13
+
14
+ First release on PyPI. The package has been usable from a checkout for
15
+ months; what changes is that it is now installable, versioned and documented
16
+ as a library rather than as this workspace's training directory.
17
+
18
+ ### Added
19
+
20
+ - **`quantik_models.hub`** — load the four published networks from the
21
+ Hugging Face Hub in one call:
22
+
23
+ ```python
24
+ from quantik_models import hub
25
+ evaluator = hub.load_evaluator("cpool") # torch
26
+ evaluator = hub.load_evaluator("cpool", runtime="onnx") # no torch
27
+ ```
28
+
29
+ Short names resolve through a table of the published repo ids rather than
30
+ a Hub query, a full `owner/repo` passes through unresolved so a fork needs
31
+ no code change, and the downloaded artifact is checked against the digest
32
+ in `manifest.json` for the runtime that will load it — `weights_hash` for
33
+ safetensors, `onnx_hash` for the graph. The module is importable without
34
+ torch.
35
+
36
+ Every fetch failure is re-raised as `hub.HubError` carrying the remedy —
37
+ the cache path and the command to run when offline with a cold cache, the
38
+ terms link for a gated repo, the valid names for a typo, the commit list
39
+ for an unknown revision — with the Hub's own exception kept as `__cause__`.
40
+ A digest mismatch is re-fetched once before it is raised, because the usual
41
+ cause is a truncated cache entry that would otherwise fail identically
42
+ forever. `resolve()` reports the commit `main` resolved to, so a run made
43
+ without an explicit `revision` is still reproducible.
44
+ - **`quantik-models-fetch` console script** (`hub.prefetch()` from Python) —
45
+ fills the Hugging Face cache without loading anything, so a container build
46
+ or an air-gapped host can be prepared before torch or onnxruntime exist.
47
+ - **`hub` extra** (`pip install 'quantik-models[hub]'`) carrying
48
+ `huggingface-hub`. Kept out of the base install because nothing in
49
+ training, evaluation or the arena fetches anything.
50
+ - **`quantik-models-play` console script**, so the play service starts the
51
+ same way from an installed package as from a checkout.
52
+ - **`py.typed`**: the package now ships its type information.
53
+ - **`arena.registry.weights_path`**, the resolver behind the loader fix
54
+ below.
55
+ - **[`DEVELOPMENT.md`](DEVELOPMENT.md)**, [`CHANGELOG.md`](CHANGELOG.md), and
56
+ [`docs/models.md`](docs/models.md) — the published models, their numbers,
57
+ and how to load them.
58
+
59
+ ### Fixed
60
+
61
+ - **`load_evaluator` could not read a downloaded Hub repository.** It
62
+ required `weights.safetensors`; `export.huggingface.stage` renames the
63
+ file to `model.safetensors` on the way to the Hub, and that is the name in
64
+ all four published repositories. The result was that the primary Python
65
+ snippet on every published model card raised `FileNotFoundError`. The
66
+ loader now resolves both names and, when it finds neither, says so naming
67
+ both candidates instead of pointing at a file that was never meant to
68
+ exist.
69
+ - **The build declared `setuptools>=68` while using PEP 639 metadata that
70
+ needs 77.** A resolver that honoured the stated floor produced a wheel
71
+ with no licence, or failed outright.
72
+ - **The generated model cards told readers `quantik-models` was not on PyPI**
73
+ and to install from a git ref. They now name the release.
74
+ - **The card's Python snippet called a method that does not exist.**
75
+ `evaluator.evaluate(boards)` is wrong twice over — an evaluator is
76
+ callable, and the legality mask is a required argument with no default —
77
+ so a reader following the card got an `AttributeError` on the one line the
78
+ card exists to provide. Both live snippets were verified against a real
79
+ download from the Hub before this release, and
80
+ `tests/test_documented_snippets.py` now executes the documented call and
81
+ fails if `Evaluator.__call__` and the documents disagree.
82
+
83
+ ### Changed
84
+
85
+ - Version **0.1.0 → 1.0.0**. The package's public surface — the `(B, 9, 4, 4)`
86
+ mover-relative input contract, the 64-logit policy and tanh value output,
87
+ the architecture registry and the checkpoint manifest — has been stable
88
+ across four trained architectures and four published model repositories.
89
+ `0.1.0` understated that, and semantic versioning only says anything once
90
+ the first stable release exists.
91
+ - `quantik-core` dependency pinned to `>=1.2,<2` rather than `>=1.2`, so a
92
+ future major release of the core cannot silently satisfy this constraint.
93
+ - `mypy` is now configured in `pyproject.toml` and **enforced in CI**. It was
94
+ previously declared in the `dev` extra and wired into nothing.
95
+ - Packaging metadata filled in: authors, classifiers, keywords, project URLs
96
+ (including the Hub namespace), and a `MANIFEST.in` that ships the tests
97
+ with the fixtures they need and excludes `runs/`, `docs/` and `staging/`.
98
+
99
+ ### Documentation
100
+
101
+ - `README.md` is now about using the library and the models. Everything
102
+ about checking out the workspace, the smoke pipeline, the corpora and the
103
+ release process moved to `DEVELOPMENT.md`.
104
+ - The twenty-three documents in `docs/` were consolidated. Superseded
105
+ narrative and dated working journals were removed in favour of the
106
+ standing conclusions, which are what a reader can act on. See
107
+ `docs/README.md`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mauro Berlanda
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,26 @@
1
+ # What ships in the sdist beyond the package itself.
2
+ #
3
+ # The rule: an sdist must be enough to build the wheel *and* verify it. That
4
+ # means the tests and the 80 KB smoke checkpoint they load — shipping
5
+ # `tests/` without `tests/fixtures/` gives a source distribution whose test
6
+ # suite cannot run, which is worse than shipping neither.
7
+ include LICENSE
8
+ include CHANGELOG.md
9
+ include AGENTS.md
10
+ recursive-include tests *.py *.json *.safetensors
11
+
12
+ # Everything below is deliberately excluded.
13
+ #
14
+ # `runs/` is gitignored and holds every corpus and checkpoint — tens of GB,
15
+ # none of it publishable, and the reason this list is explicit rather than
16
+ # implicit. `docs/` is 664 KB of Markdown and figures that are one link away
17
+ # on GitHub. `docker/staging/` is materialized weights.
18
+ prune runs
19
+ prune docs
20
+ prune docker
21
+ prune experiments
22
+ prune examples
23
+ prune scripts
24
+ prune staging
25
+ global-exclude *.pyc *.npz *.parquet *.jsonl
26
+ global-exclude .DS_Store
@@ -0,0 +1,294 @@
1
+ Metadata-Version: 2.4
2
+ Name: quantik-models
3
+ Version: 1.0.0
4
+ Summary: Policy/value networks, training and evaluation for the Quantik board game
5
+ Author-email: Mauro Berlanda <mauro.berlanda@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/mberlanda/quantik-models-py
8
+ Project-URL: Repository, https://github.com/mberlanda/quantik-models-py
9
+ Project-URL: Documentation, https://github.com/mberlanda/quantik-models-py#readme
10
+ Project-URL: Changelog, https://github.com/mberlanda/quantik-models-py/blob/main/CHANGELOG.md
11
+ Project-URL: Bug Tracker, https://github.com/mberlanda/quantik-models-py/issues
12
+ Project-URL: Model Weights, https://huggingface.co/brpoplpush
13
+ Keywords: quantik,board-games,game-ai,policy-value-network,reinforcement-learning,mcts,alphazero,onnx,pytorch
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Games/Entertainment :: Board Games
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.12
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: numpy<3,>=2.0
28
+ Requires-Dist: quantik-core<2,>=1.2
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest<10,>=8; extra == "dev"
31
+ Requires-Dist: mypy<3,>=1.8; extra == "dev"
32
+ Requires-Dist: build<2,>=1; extra == "dev"
33
+ Requires-Dist: twine<7,>=6; extra == "dev"
34
+ Provides-Extra: arrow
35
+ Requires-Dist: pyarrow<22,>=16; extra == "arrow"
36
+ Provides-Extra: torch
37
+ Requires-Dist: torch>=2.4; extra == "torch"
38
+ Requires-Dist: safetensors>=0.4; extra == "torch"
39
+ Provides-Extra: onnx
40
+ Requires-Dist: onnx>=1.16; extra == "onnx"
41
+ Requires-Dist: onnxscript>=0.1; extra == "onnx"
42
+ Requires-Dist: onnxruntime>=1.18; extra == "onnx"
43
+ Provides-Extra: serve
44
+ Requires-Dist: onnxruntime>=1.18; extra == "serve"
45
+ Provides-Extra: hub
46
+ Requires-Dist: huggingface-hub>=0.34; extra == "hub"
47
+ Provides-Extra: viz
48
+ Requires-Dist: matplotlib>=3.8; extra == "viz"
49
+ Provides-Extra: all
50
+ Requires-Dist: quantik-models[arrow,dev,hub,onnx,serve,torch,viz]; extra == "all"
51
+ Dynamic: license-file
52
+
53
+ # quantik-models
54
+
55
+ [![PyPI](https://img.shields.io/pypi/v/quantik-models.svg)](https://pypi.org/project/quantik-models/)
56
+ [![Python](https://img.shields.io/pypi/pyversions/quantik-models.svg)](https://pypi.org/project/quantik-models/)
57
+ [![License](https://img.shields.io/pypi/l/quantik-models.svg)](LICENSE)
58
+
59
+ Policy/value networks for **Quantik**, and the training, evaluation and play
60
+ tooling behind them. Four architectures, parameter-matched, trained on
61
+ positions labelled by an exact solver — and four sets of weights published on
62
+ the Hugging Face Hub.
63
+
64
+ Quantik is a 4×4 board game with a group-wise placement rule: you may not
65
+ place a shape in a row, column or 2×2 zone where your *opponent* already has
66
+ that shape, and you win by completing a line of four different shapes in
67
+ either colour. It is small enough to solve exactly, which is what makes it a
68
+ useful place to ask whether an architectural prior is worth having — the
69
+ ground truth is available to check the answer against.
70
+
71
+ ```bash
72
+ pip install 'quantik-models[torch,hub]'
73
+ ```
74
+
75
+ ```python
76
+ from quantik_models import hub
77
+ from quantik_models.env import fastboard as fb
78
+
79
+ evaluator = hub.load_evaluator("cpool") # downloads and verifies the weights
80
+
81
+ boards = fb.empty_boards(1) # (1, 8) uint16
82
+ legal = fb.legal_masks(boards) # (1, 64) bool
83
+ policy, value = evaluator(boards, legal) # masked priors, value in [-1, 1]
84
+ ```
85
+
86
+ Working *on* this package rather than with it: **[DEVELOPMENT.md](DEVELOPMENT.md)**.
87
+
88
+ ## Install
89
+
90
+ | you want | install |
91
+ |---|---|
92
+ | the published models, on torch | `pip install 'quantik-models[torch,hub]'` |
93
+ | the published models, no torch | `pip install 'quantik-models[serve,hub]'` |
94
+ | to train your own | `pip install 'quantik-models[torch,onnx]'` |
95
+ | the library only | `pip install quantik-models` |
96
+
97
+ The base install is `numpy` and `quantik-core` and nothing else. torch is a
98
+ 529 MB dependency and onnxruntime is 80 MB; neither is imposed on someone who
99
+ does not need it. The full table is in
100
+ [DEVELOPMENT.md](DEVELOPMENT.md#environment).
101
+
102
+ Python 3.12+.
103
+
104
+ ## Getting the weights
105
+
106
+ The weights are not in the wheel. They are ~7 MB each, they carry a different
107
+ licence from the code, and they version independently of it — so
108
+ `load_evaluator` fetches them from the Hub on first use and reads them from
109
+ the Hugging Face cache (`$HF_HOME`, default `~/.cache/huggingface`) every time
110
+ after. **One network call, once per model, and never again.**
111
+
112
+ To fill that cache ahead of time — a container build, a machine that is about
113
+ to go offline, an air-gapped copy — use the fetch command. It needs neither
114
+ torch nor onnxruntime, so it runs before either is installed:
115
+
116
+ ```bash
117
+ quantik-models-fetch --all # or: quantik-models-fetch cpool attn
118
+ ```
119
+
120
+ Once a model is cached, everything works with no network at all.
121
+
122
+ Nothing else needs special attention. Every way this can fail raises
123
+ `hub.HubError` with the remedy in the message rather than a traceback through
124
+ `huggingface_hub`:
125
+
126
+ | what went wrong | what you get |
127
+ |---|---|
128
+ | offline, model already cached | it just works — the cache is used |
129
+ | offline, nothing cached | the cache path, and the `quantik-models-fetch` line to run while online |
130
+ | truncated download | re-fetched once automatically; a second failure names the cache to clear |
131
+ | typo in the model name | the four names that do exist |
132
+ | bad `revision` | a link to the repo's commit list |
133
+ | rate limited | that it clears on its own, and that logging in raises the limit |
134
+
135
+ `hub.resolve()` returns the commit the download actually resolved to, which is
136
+ what to record when you report a number — `revision="main"` is not a pin.
137
+
138
+ ## The models
139
+
140
+ Four networks answering the same question in different ways, all
141
+ interchangeable because they agree on one contract:
142
+
143
+ input (B, 9, 4, 4) float32 tensor-board.v1, mover-relative
144
+ output (B, 64) policy logits action_index = shape * 16 + position
145
+ (B,) value in [-1, 1] +1 = good for the side to move
146
+
147
+ **Legality masking is applied outside every model**, using the same code path
148
+ in training and at inference — so no engine here can return an illegal move.
149
+
150
+ | model | Hub repository | IID top-1 | vs `minimax-d2` |
151
+ |---|---|---|---|
152
+ | **`cpool`** | [`quantik-cpool-c191-b6`](https://huggingface.co/brpoplpush/quantik-cpool-c191-b6) | **0.9893** | **49.4%** |
153
+ | `attn` | [`quantik-attn-d192-b6`](https://huggingface.co/brpoplpush/quantik-attn-d192-b6) | 0.9879 | 43.1% |
154
+ | `resnet` | [`quantik-resnet-c128-b6`](https://huggingface.co/brpoplpush/quantik-resnet-c128-b6) | 0.9701 | 36.5% |
155
+ | `mlp` | [`quantik-mlp-h455-b4`](https://huggingface.co/brpoplpush/quantik-mlp-h455-b4) | 0.9516 | 31.9% |
156
+
157
+ `minimax-d2` is a fixed two-ply alpha-beta search — the only opponent whose
158
+ strength does not move with the field, and so the only column that answers
159
+ "is any of this good" rather than "which of these is better". `cpool` playing
160
+ raw policy, one forward pass per move, is even with it. **Full numbers, the
161
+ four measurements that disagree, and what not to conclude from them:
162
+ [`docs/models.md`](docs/models.md).**
163
+
164
+ > **The weights are CC BY-NC 4.0; this package is MIT.** A commercial
165
+ > application may use the pipeline, the rules engine and the evaluation
166
+ > harness freely, and may not ship these weights. Train your own and they
167
+ > are yours.
168
+
169
+ ### `cpool` — the constraint model
170
+
171
+ Quantik's rule is group-wise, not spatial: twelve overlapping groups (4 rows,
172
+ 4 columns, 4 zones), every cell in exactly three. Each block pools the sixteen
173
+ cell tokens into those groups, transforms them there, and scatters back.
174
+
175
+ ```mermaid
176
+ flowchart LR
177
+ IN["board<br/>(B,9,4,4)"] --> TOK["16 cell tokens<br/>Linear 9→C"]
178
+ TOK --> BLK
179
+ subgraph BLK["constraint block × B"]
180
+ direction LR
181
+ N["LayerNorm"] --> POOL["pool to 12 groups<br/>4 rows · 4 cols · 4 zones"]
182
+ POOL --> KIND["+ kind embedding<br/>line | zone"]
183
+ KIND --> GM["group MLP"]
184
+ GM --> SC["scatter to member cells"]
185
+ SC --> MG["merge with cell features<br/>+ FFN, residual"]
186
+ end
187
+ BLK --> PH["policy head<br/>Linear C→4 per cell<br/>transpose → 64"]
188
+ BLK --> VH["value head<br/>mean over cells · MLP · tanh"]
189
+ PH --> POL["policy logits (B,64)"]
190
+ VH --> VAL["value (B,)"]
191
+ ```
192
+
193
+ [`docs/architecture-constraint-pool.md`](docs/architecture-constraint-pool.md)
194
+
195
+ ### `attn` — the same bet without the prior
196
+
197
+ Transformer encoder over the sixteen cells, told *nothing* about rows,
198
+ columns or zones. It is the test of whether `cpool`'s explicit wiring was
199
+ necessary: on policy accuracy it ties, on the value head it does not.
200
+
201
+ [`docs/architectures.md`](docs/architectures.md) ·
202
+ [`docs/attention-negative-result.md`](docs/attention-negative-result.md)
203
+
204
+ ### `resnet` — the incumbent
205
+
206
+ Convolutional residual trunk, and the architecture every hyperparameter here
207
+ was originally chosen for. 99.2% of its parameters are the trunk.
208
+
209
+ [`docs/architecture-resnet.md`](docs/architecture-resnet.md)
210
+
211
+ ### `mlp` — the control
212
+
213
+ Throws spatial structure away entirely: 144 flat features through dense
214
+ residual blocks. It exists to make "convolution is worth having on a 4×4
215
+ board" falsifiable rather than assumed. It loses, so the spatial prior is
216
+ real.
217
+
218
+ [`docs/architecture-mlp.md`](docs/architecture-mlp.md)
219
+
220
+ ![Validation top-1 per epoch](docs/figures/training-curves.svg)
221
+
222
+ The dashed lines are two architectures trained at `2e-3`, the rate the ResNet
223
+ was tuned for and everything added later inherited by silence. `attn` did not
224
+ learn at all at that rate; `cpool` converged perfectly well, to a lower place.
225
+ A single-rate comparison cannot tell either of those apart from "this
226
+ architecture is worse" — which is how three published conclusions here turned
227
+ out to be hyperparameter artifacts.
228
+ [`docs/learning-rate-sweep.md`](docs/learning-rate-sweep.md).
229
+
230
+ ## Playing against them
231
+
232
+ The play service serves the board and the models on one port, and records
233
+ finished games:
234
+
235
+ ```bash
236
+ pip install 'quantik-models[serve,hub]'
237
+ quantik-models-play --models staging
238
+ ```
239
+
240
+ It prints a LAN address to open on a phone. `--no-store` opens no database,
241
+ which is the configuration the public container runs.
242
+ [`docs/play-service.md`](docs/play-service.md).
243
+
244
+ ## Training your own
245
+
246
+ ```bash
247
+ pip install 'quantik-models[torch,onnx]'
248
+ ```
249
+
250
+ ```bash
251
+ # check the assumptions before a long run (~1 min/arch)
252
+ python -m quantik_models.train.preflight --preset medium --epochs 16
253
+
254
+ # train to convergence: --epochs is the cap, --patience the rule
255
+ python -m quantik_models.train.supervised --arch cpool --preset medium \
256
+ --corpus runs/oracle/corpus/exact-sampled.npz --name my-run \
257
+ --epochs 60 --patience 5
258
+
259
+ # regenerate every published number for it
260
+ scripts/evaluate_lineup.sh runs/eval/today cpool=runs/train/my-run/best
261
+
262
+ # stage it as a Hugging Face model repository (writes files; uploads nothing)
263
+ quantik-models-hf-stage runs/train/my-run/best staging/my-model
264
+ ```
265
+
266
+ Training writes `weights.safetensors`, `model.onnx`, a
267
+ `model-checkpoint.v1` `manifest.json` and a training report. Corpora, the
268
+ label strategy and the retrain/fine-tune path — including freezing part of a
269
+ network — are in [`docs/`](docs/README.md).
270
+
271
+ ## Documentation
272
+
273
+ [`docs/README.md`](docs/README.md) is the reading order. The four to start
274
+ with:
275
+
276
+ | | |
277
+ |---|---|
278
+ | [`docs/models.md`](docs/models.md) | the published models: how to load one, what the numbers mean, what not to conclude |
279
+ | [`docs/decisions/0001-architecture-lineup.md`](docs/decisions/0001-architecture-lineup.md) | which architectures were trained, which six were declined, and the methodology |
280
+ | [`docs/benchmarks.md`](docs/benchmarks.md) | the figures, and what each does and does not establish |
281
+ | [`docs/oracle-benchmark.md`](docs/oracle-benchmark.md) | the field against a fixed classical engine |
282
+
283
+ ## Related
284
+
285
+ - [`quantik-core`](https://pypi.org/project/quantik-core/) — the rules
286
+ engine, QFEN, bitboards and the exact solver. Also on
287
+ [crates.io](https://crates.io/crates/quantik-core).
288
+ - [The models on the Hub](https://huggingface.co/brpoplpush) — weights,
289
+ ONNX graphs and model cards.
290
+
291
+ ## License
292
+
293
+ MIT — see [LICENSE](LICENSE). The published **weights** are CC BY-NC 4.0 and
294
+ are not distributed with this package.